diff --git a/apps/documents/__init__.py b/apps/documents/__init__.py index a878425637..64d9d8f4b5 100644 --- a/apps/documents/__init__.py +++ b/apps/documents/__init__.py @@ -24,45 +24,45 @@ PERMISSION_DOCUMENT_TRANSFORM = 'document_transform' PERMISSION_DOCUMENT_TOOLS = 'document_tools' register_permissions('documents', [ - {'name':PERMISSION_DOCUMENT_CREATE, 'label':_(u'Create document')}, - {'name':PERMISSION_DOCUMENT_PROPERTIES_EDIT, 'label':_(u'Edit document properties')}, - {'name':PERMISSION_DOCUMENT_METADATA_EDIT, 'label':_(u'Edit document metadata')}, - {'name':PERMISSION_DOCUMENT_VIEW, 'label':_(u'View document')}, - {'name':PERMISSION_DOCUMENT_DELETE, 'label':_(u'Delete document')}, - {'name':PERMISSION_DOCUMENT_DOWNLOAD, 'label':_(u'Download document')}, - {'name':PERMISSION_DOCUMENT_TRANSFORM, 'label':_(u'Transform document')}, - {'name':PERMISSION_DOCUMENT_TOOLS, 'label':_(u'Execute document modifying tools')}, + {'name': PERMISSION_DOCUMENT_CREATE, 'label': _(u'Create document')}, + {'name': PERMISSION_DOCUMENT_PROPERTIES_EDIT, 'label': _(u'Edit document properties')}, + {'name': PERMISSION_DOCUMENT_METADATA_EDIT, 'label': _(u'Edit document metadata')}, + {'name': PERMISSION_DOCUMENT_VIEW, 'label': _(u'View document')}, + {'name': PERMISSION_DOCUMENT_DELETE, 'label': _(u'Delete document')}, + {'name': PERMISSION_DOCUMENT_DOWNLOAD, 'label': _(u'Download document')}, + {'name': PERMISSION_DOCUMENT_TRANSFORM, 'label': _(u'Transform document')}, + {'name': PERMISSION_DOCUMENT_TOOLS, 'label': _(u'Execute document modifying tools')}, ]) -document_list = {'text':_(u'documents list'), 'view':'document_list', 'famfam':'page', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} -document_create = {'text':_('upload a new document'), 'view':'document_create', 'famfam':'page_add', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_CREATE]}} -document_create_multiple = {'text':_('upload multiple new documents'), 'view':'document_create_multiple', 'famfam':'page_add', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_CREATE]}} -document_create_sibling = {'text':_('upload new document using same metadata'), 'view':'document_create_sibling', 'args':'object.id', 'famfam':'page_copy', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_CREATE]}} -document_view = {'text':_('details (advanced)'), 'view':'document_view', 'args':'object.id', 'famfam':'page', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} -document_view_simple = {'text':_('details (simple)'), 'view':'document_view_simple', 'args':'object.id', 'famfam':'page', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} -document_delete = {'text':_('delete'), 'view':'document_delete', 'args':'object.id', 'famfam':'page_delete', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_DELETE]}} -document_multiple_delete = {'text':_('delete'), 'view':'document_multiple_delete', 'famfam':'page_delete', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_DELETE]}} -document_edit = {'text':_('edit'), 'view':'document_edit', 'args':'object.id', 'famfam':'page_edit', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_PROPERTIES_EDIT]}} -document_edit_metadata = {'text':_('edit metadata'), 'view':'document_edit_metadata', 'args':'object.id', 'famfam':'page_edit', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_METADATA_EDIT]}} -document_multiple_edit_metadata = {'text':_('edit metadata'), 'view':'document_multiple_edit_metadata', 'famfam':'page_edit', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_METADATA_EDIT]}} -document_preview = {'text':_('preview'), 'class':'fancybox', 'view':'document_preview', 'args':'object.id', 'famfam':'magnifier', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} -document_download = {'text':_('download'), 'view':'document_download', 'args':'object.id', 'famfam':'page_save', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_DOWNLOAD]}} -document_find_duplicates = {'text':_('find duplicates'), 'view':'document_find_duplicates', 'args':'object.id', 'famfam':'page_refresh', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} -document_find_all_duplicates = {'text':_('find all duplicates'), 'view':'document_find_all_duplicates', 'famfam':'page_refresh', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} -document_clear_transformations = {'text':_('clear all transformations'), 'view':'document_clear_transformations', 'args':'object.id', 'famfam':'page_paintbrush', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_TRANSFORM]}} -document_multiple_clear_transformations = {'text':_('clear all transformations'), 'view':'document_multiple_clear_transformations', 'famfam':'page_paintbrush', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_TRANSFORM]}} +document_list = {'text': _(u'documents list'), 'view': 'document_list', 'famfam': 'page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} +document_create = {'text': _('upload a new document'), 'view': 'document_create', 'famfam': 'page_add', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_CREATE]}} +document_create_multiple = {'text': _('upload multiple new documents'), 'view': 'document_create_multiple', 'famfam': 'page_add', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_CREATE]}} +document_create_sibling = {'text': _('upload new document using same metadata'), 'view': 'document_create_sibling', 'args': 'object.id', 'famfam': 'page_copy', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_CREATE]}} +document_view = {'text': _('details (advanced)'), 'view': 'document_view', 'args': 'object.id', 'famfam': 'page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} +document_view_simple = {'text': _('details (simple)'), 'view': 'document_view_simple', 'args': 'object.id', 'famfam': 'page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} +document_delete = {'text': _('delete'), 'view': 'document_delete', 'args': 'object.id', 'famfam': 'page_delete', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_DELETE]}} +document_multiple_delete = {'text': _('delete'), 'view': 'document_multiple_delete', 'famfam': 'page_delete', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_DELETE]}} +document_edit = {'text': _('edit'), 'view': 'document_edit', 'args': 'object.id', 'famfam': 'page_edit', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_PROPERTIES_EDIT]}} +document_edit_metadata = {'text': _('edit metadata'), 'view': 'document_edit_metadata', 'args': 'object.id', 'famfam': 'page_edit', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_METADATA_EDIT]}} +document_multiple_edit_metadata = {'text': _('edit metadata'), 'view': 'document_multiple_edit_metadata', 'famfam': 'page_edit', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_METADATA_EDIT]}} +document_preview = {'text': _('preview'), 'class': 'fancybox', 'view': 'document_preview', 'args': 'object.id', 'famfam': 'magnifier', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} +document_download = {'text': _('download'), 'view': 'document_download', 'args': 'object.id', 'famfam': 'page_save', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_DOWNLOAD]}} +document_find_duplicates = {'text': _('find duplicates'), 'view': 'document_find_duplicates', 'args': 'object.id', 'famfam': 'page_refresh', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} +document_find_all_duplicates = {'text': _('find all duplicates'), 'view': 'document_find_all_duplicates', 'famfam': 'page_refresh', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} +document_clear_transformations = {'text': _('clear all transformations'), 'view': 'document_clear_transformations', 'args': 'object.id', 'famfam': 'page_paintbrush', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}} +document_multiple_clear_transformations = {'text': _('clear all transformations'), 'view': 'document_multiple_clear_transformations', 'famfam': 'page_paintbrush', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}} -document_page_transformation_create = {'text':_('create new transformation'), 'view':'document_page_transformation_create', 'args':'object.id', 'famfam':'pencil_add', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_TRANSFORM]}} -document_page_transformation_edit = {'text':_('edit'), 'view':'document_page_transformation_edit', 'args':'object.id', 'famfam':'pencil_go', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_TRANSFORM]}} -document_page_transformation_delete = {'text':_('delete'), 'view':'document_page_transformation_delete', 'args':'object.id', 'famfam':'pencil_delete', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_TRANSFORM]}} -document_page_transformation_go_back = {'text':_('return to document'), 'view':'document_view', 'args':'object.document_page.document.id', 'famfam':'page_go', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} +document_page_transformation_create = {'text': _('create new transformation'), 'view': 'document_page_transformation_create', 'args': 'object.id', 'famfam': 'pencil_add', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}} +document_page_transformation_edit = {'text': _('edit'), 'view': 'document_page_transformation_edit', 'args': 'object.id', 'famfam': 'pencil_go', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}} +document_page_transformation_delete = {'text': _('delete'), 'view': 'document_page_transformation_delete', 'args': 'object.id', 'famfam': 'pencil_delete', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}} +document_page_transformation_go_back = {'text': _('return to document'), 'view': 'document_view', 'args': 'object.document_page.document.id', 'famfam': 'page_go', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} -document_page_go_back = {'text':_('return to document'), 'view':'document_view', 'args':'object.document.id', 'famfam':'page_go', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} +document_page_go_back = {'text': _('return to document'), 'view': 'document_view', 'args': 'object.document.id', 'famfam': 'page_go', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} -document_missing_list = {'text':_('Find missing document files'), 'url':reverse('document_missing_list'), 'famfam':'folder_page', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}} +document_missing_list = {'text': _('Find missing document files'), 'url': reverse('document_missing_list'), 'famfam': 'folder_page', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}} -staging_file_preview = {'text':_('preview'), 'class':'fancybox-noscaling', 'view':'staging_file_preview', 'args':'object.id', 'famfam':'drive_magnify'} -staging_file_delete = {'text':_('delete'), 'view':'staging_file_delete', 'args':'object.id', 'famfam':'drive_delete'} +staging_file_preview = {'text': _('preview'), 'class': 'fancybox-noscaling', 'view': 'staging_file_preview', 'args': 'object.id', 'famfam': 'drive_magnify'} +staging_file_delete = {'text': _('delete'), 'view': 'staging_file_delete', 'args': 'object.id', 'famfam': 'drive_delete'} register_links(Document, [document_view_simple, document_view, document_edit, document_edit_metadata, document_delete, document_download, document_find_duplicates, document_clear_transformations], menu_name='sidebar') register_links(Document, [document_list, document_create, document_create_multiple, document_create_sibling], menu_name='sidebar') @@ -95,22 +95,22 @@ def document_exists(document): register_model_list_columns(Document, [ - {'name':_(u'thumbnail'), 'attribute': + {'name':_(u'thumbnail'), 'attribute': lambda x: '' % (reverse('document_preview', args=[x.id]), reverse('document_thumbnail', args=[x.id])) }, - {'name':_(u'metadata'), 'attribute': - lambda x: ', '.join(['%s - %s' %(metadata.metadata_type, metadata.value) for metadata in x.documentmetadata_set.all()]) + {'name':_(u'metadata'), 'attribute': + lambda x: u', '.join([u'%s - %s' % (metadata.metadata_type, metadata.value) for metadata in x.documentmetadata_set.all()]) }, ]) if ENABLE_SINGLE_DOCUMENT_UPLOAD: register_menu([ - {'text':_('documents'), 'view':'document_create', 'links':[ + {'text': _('documents'), 'view': 'document_create', 'links': [ document_create, document_create_multiple, document_list - ],'famfam':'page','position':1}]) + ], 'famfam': 'page', 'position': 1}]) else: register_menu([ - {'text':_('documents'), 'view':'document_create_multiple', 'links':[ + {'text': _('documents'), 'view': 'document_create_multiple', 'links': [ document_create_multiple, document_list - ],'famfam':'page','position':1}]) + ], 'famfam': 'page', 'position': 1}]) diff --git a/apps/documents/metadata.py b/apps/documents/metadata.py index 0cda7f7856..a3331912c5 100644 --- a/apps/documents/metadata.py +++ b/apps/documents/metadata.py @@ -9,12 +9,13 @@ from django.core.exceptions import ObjectDoesNotExist from models import DocumentMetadata, MetadataType + def decode_metadata_from_url(url_dict): '''Parses a URL query string to a list of metadata ''' metadata_dict = { - 'id':{}, - 'value':{} + 'id': {}, + 'value': {} } metadata_list = [] #Match out of order metadata_type ids with metadata values from request @@ -22,18 +23,18 @@ def decode_metadata_from_url(url_dict): if 'metadata' in key: index, element = key[8:].split('_') metadata_dict[element][index] = value - + #Convert the nested dictionary into a list of id+values dictionaries for order, identifier in metadata_dict['id'].items(): if order in metadata_dict['value'].keys(): metadata_list.append({ - 'id':identifier, - 'value':metadata_dict['value'][order] + 'id': identifier, + 'value': metadata_dict['value'][order] }) return metadata_list - - + + def save_metadata_list(metadata_list, document): '''Takes a list of metadata values and associates a document to it ''' @@ -41,7 +42,7 @@ def save_metadata_list(metadata_list, document): if item['value']: save_metadata(item, document) else: - #If there is no metadata value, delete the metadata entry + #If there is no metadata value, delete the metadata entry #completely from the document try: metadata_type = MetadataType.objects.get(id=item['id']) @@ -52,8 +53,8 @@ def save_metadata_list(metadata_list, document): document_metadata.delete() except ObjectDoesNotExist: pass - - + + def save_metadata(metadata_dict, document): '''save metadata_dict ''' @@ -66,7 +67,7 @@ def save_metadata(metadata_dict, document): ), ) #Handle 'plus sign as space' in the url - + #unquote_plus handles utf-8?!? #http://stackoverflow.com/questions/4382875/handling-iri-in-django #.decode('utf-8') @@ -78,20 +79,17 @@ def metadata_repr(metadata_list): '''Return a printable representation of a metadata list ''' return ', '.join(metadata_repr_as_list(metadata_list)) - - + + def metadata_repr_as_list(metadata_list): '''Turn a list of metadata into a list of printable representations ''' output = [] for metadata_dict in metadata_list: try: - output.append('%s - %s' % (MetadataType.objects.get( + output.append(u'%s - %s' % (MetadataType.objects.get( pk=metadata_dict['id']), metadata_dict.get('value', ''))) except: pass - + return output - - - diff --git a/apps/documents/urls.py b/apps/documents/urls.py index 7f9b846c20..b7d492630e 100644 --- a/apps/documents/urls.py +++ b/apps/documents/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import * +from django.conf.urls.defaults import patterns, url from django.utils.translation import ugettext_lazy as _ from django.views.generic.create_update import create_object, update_object @@ -14,10 +14,10 @@ from converter.api import QUALITY_HIGH urlpatterns = patterns('documents.views', url(r'^document/list/$', 'document_list', (), 'document_list'), - url(r'^document/create/from/local/single/$', 'document_create', {'multiple':False}, 'document_create'), - url(r'^document/create/from/local/multiple/$', 'document_create', {'multiple':True}, 'document_create_multiple'), - url(r'^document/type/(?P\d+)/upload/single/$', 'upload_document_with_type', {'multiple':False}, 'upload_document_with_type'), - url(r'^document/type/(?P\d+)/upload/multiple/$', 'upload_document_with_type', {'multiple':True}, 'upload_multiple_documents_with_type'), + url(r'^document/create/from/local/single/$', 'document_create', {'multiple': False}, 'document_create'), + url(r'^document/create/from/local/multiple/$', 'document_create', {'multiple': True}, 'document_create_multiple'), + url(r'^document/type/(?P\d+)/upload/single/$', 'upload_document_with_type', {'multiple': False}, 'upload_document_with_type'), + url(r'^document/type/(?P\d+)/upload/multiple/$', 'upload_document_with_type', {'multiple': True}, 'upload_multiple_documents_with_type'), url(r'^document/(?P\d+)/$', 'document_view', (), 'document_view'), url(r'^document/(?P\d+)/simple/$', 'document_view_simple', (), 'document_view_simple'), url(r'^document/(?P\d+)/delete/$', 'document_delete', (), 'document_delete'), @@ -25,15 +25,15 @@ urlpatterns = patterns('documents.views', url(r'^document/(?P\d+)/edit/$', 'document_edit', (), 'document_edit'), url(r'^document/(?P\d+)/edit/metadata/$', 'document_edit_metadata', (), 'document_edit_metadata'), url(r'^document/multiple/edit/metadata/$', 'document_multiple_edit_metadata', (), 'document_multiple_edit_metadata'), - - url(r'^document/(?P\d+)/display/preview/$', 'get_document_image', {'size':PREVIEW_SIZE}, 'document_preview'), - url(r'^document/(?P\d+)/display/preview/multipage/$', 'get_document_image', {'size':MULTIPAGE_PREVIEW_SIZE}, 'document_preview_multipage'), - url(r'^document/(?P\d+)/display/preview/transformation/$', 'get_document_image', {'size':TRANFORMATION_PREVIEW_SIZE}, 'document_preview_transformation'), - url(r'^document/(?P\d+)/display/thumbnail/$', 'get_document_image', {'size':THUMBNAIL_SIZE}, 'document_thumbnail'), - url(r'^document/(?P\d+)/display/$', 'get_document_image', {'size':DISPLAY_SIZE,'quality':QUALITY_HIGH}, 'document_display'), - + + url(r'^document/(?P\d+)/display/preview/$', 'get_document_image', {'size': PREVIEW_SIZE}, 'document_preview'), + url(r'^document/(?P\d+)/display/preview/multipage/$', 'get_document_image', {'size': MULTIPAGE_PREVIEW_SIZE}, 'document_preview_multipage'), + url(r'^document/(?P\d+)/display/preview/transformation/$', 'get_document_image', {'size': TRANFORMATION_PREVIEW_SIZE}, 'document_preview_transformation'), + url(r'^document/(?P\d+)/display/thumbnail/$', 'get_document_image', {'size': THUMBNAIL_SIZE}, 'document_thumbnail'), + url(r'^document/(?P\d+)/display/$', 'get_document_image', {'size': DISPLAY_SIZE, 'quality': QUALITY_HIGH}, 'document_display'), + url(r'^document/(?P\d+)/download/$', 'document_download', (), 'document_download'), - url(r'^document/(?P\d+)/create/siblings/$', 'document_create_sibling', {'multiple':True if ENABLE_SINGLE_DOCUMENT_UPLOAD == False else False}, 'document_create_sibling'), + url(r'^document/(?P\d+)/create/siblings/$', 'document_create_sibling', {'multiple': True if ENABLE_SINGLE_DOCUMENT_UPLOAD == False else False}, 'document_create_sibling'), url(r'^document/(?P\d+)/find_duplicates/$', 'document_find_duplicates', (), 'document_find_duplicates'), url(r'^document/(?P\d+)/clear_transformations/$', 'document_clear_transformations', (), 'document_clear_transformations'), url(r'^document/multiple/clear_transformations/$', 'document_multiple_clear_transformations', (), 'document_multiple_clear_transformations'), @@ -41,11 +41,11 @@ urlpatterns = patterns('documents.views', url(r'^staging_file/(?P\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'), url(r'^staging_file/(?P\w+)/delete/$', 'staging_file_delete', (), 'staging_file_delete'), - + url(r'^document/page/(?P\d+)/$', 'document_page_view', (), 'document_page_view'), url(r'^document/page/(?P\d+)/transformation/create/$', 'document_page_transformation_create', (), 'document_page_transformation_create'), url(r'^document/page/transformation/(?P\d+)/edit/$', 'document_page_transformation_edit', (), 'document_page_transformation_edit'), url(r'^document/page/transformation/(?P\d+)/delete/$', 'document_page_transformation_delete', (), 'document_page_transformation_delete'), - + url(r'^document/missing/list/$', 'document_missing_list', (), 'document_missing_list'), ) diff --git a/apps/documents/utils.py b/apps/documents/utils.py index f5f9384e9c..0c8122bcbc 100644 --- a/apps/documents/utils.py +++ b/apps/documents/utils.py @@ -4,7 +4,7 @@ from common import TEMPORARY_DIRECTORY #http://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python -def copyfile(source, dest, buffer_size=1024*1024): +def copyfile(source, dest, buffer_size=1024 * 1024): """ Copy a file from source to dest. source and dest can either be strings or any object with a read or @@ -26,8 +26,6 @@ def copyfile(source, dest, buffer_size=1024*1024): dest.close() -def document_save_to_temp_dir(document, filename, buffer_size=1024*1024): +def document_save_to_temp_dir(document, filename, buffer_size=1024 * 1024): temporary_path = os.path.join(TEMPORARY_DIRECTORY, filename) return document.save_to_file(temporary_path, buffer_size) - - diff --git a/apps/filesystem_serving/urls.py b/apps/filesystem_serving/urls.py index 7bd5f95cb0..ec434df234 100644 --- a/apps/filesystem_serving/urls.py +++ b/apps/filesystem_serving/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import * +from django.conf.urls.defaults import patterns, url urlpatterns = patterns('filesystem_serving.views', url(r'^recreate_all_links/$', 'recreate_all_links', (), 'recreate_all_links'), diff --git a/apps/ocr/__init__.py b/apps/ocr/__init__.py index 7e921c87bb..5268939f4e 100644 --- a/apps/ocr/__init__.py +++ b/apps/ocr/__init__.py @@ -22,23 +22,23 @@ PERMISSION_OCR_QUEUE_ENABLE_DISABLE = 'ocr_queue_enable_disable' PERMISSION_OCR_CLEAN_ALL_PAGES = 'ocr_clean_all_pages' register_permissions('ocr', [ - {'name':PERMISSION_OCR_DOCUMENT, 'label':_(u'Submit document for OCR')}, - {'name':PERMISSION_OCR_DOCUMENT_DELETE, 'label':_(u'Delete document for OCR queue')}, - {'name':PERMISSION_OCR_QUEUE_ENABLE_DISABLE, 'label':_(u'Can enable/disable an OCR queue')}, - {'name':PERMISSION_OCR_CLEAN_ALL_PAGES, 'label':_(u'Can execute an OCR clean up on all document pages')}, + {'name': PERMISSION_OCR_DOCUMENT, 'label': _(u'Submit document for OCR')}, + {'name': PERMISSION_OCR_DOCUMENT_DELETE, 'label': _(u'Delete document for OCR queue')}, + {'name': PERMISSION_OCR_QUEUE_ENABLE_DISABLE, 'label': _(u'Can enable/disable an OCR queue')}, + {'name': PERMISSION_OCR_CLEAN_ALL_PAGES, 'label': _(u'Can execute an OCR clean up on all document pages')}, ]) #Links -submit_document = {'text':_('submit to OCR queue'), 'view':'submit_document', 'args':'object.id', 'famfam':'hourglass_add', 'permissions':{'namespace':'ocr', 'permissions':[PERMISSION_OCR_DOCUMENT]}} -re_queue_document = {'text':_('re-queue'), 'view':'re_queue_document', 'args':'object.id', 'famfam':'hourglass_add', 'permissions':{'namespace':'ocr', 'permissions':[PERMISSION_OCR_DOCUMENT]}} -re_queue_multiple_document = {'text':_('re-queue'), 'view':'re_queue_multiple_document', 'famfam':'hourglass_add', 'permissions':{'namespace':'ocr', 'permissions':[PERMISSION_OCR_DOCUMENT]}} -queue_document_delete = {'text':_(u'delete'), 'view':'queue_document_delete', 'args':'object.id', 'famfam':'hourglass_delete', 'permissions':{'namespace':'ocr', 'permissions':[PERMISSION_OCR_DOCUMENT_DELETE]}} -queue_document_multiple_delete = {'text':_(u'delete'), 'view':'queue_document_multiple_delete', 'famfam':'hourglass_delete', 'permissions':{'namespace':'ocr', 'permissions':[PERMISSION_OCR_DOCUMENT_DELETE]}} +submit_document = {'text': _('submit to OCR queue'), 'view': 'submit_document', 'args': 'object.id', 'famfam': 'hourglass_add', 'permissions': {'namespace': 'ocr', 'permissions': [PERMISSION_OCR_DOCUMENT]}} +re_queue_document = {'text': _('re-queue'), 'view': 're_queue_document', 'args': 'object.id', 'famfam': 'hourglass_add', 'permissions': {'namespace': 'ocr', 'permissions': [PERMISSION_OCR_DOCUMENT]}} +re_queue_multiple_document = {'text': _('re-queue'), 'view': 're_queue_multiple_document', 'famfam': 'hourglass_add', 'permissions': {'namespace': 'ocr', 'permissions': [PERMISSION_OCR_DOCUMENT]}} +queue_document_delete = {'text': _(u'delete'), 'view': 'queue_document_delete', 'args': 'object.id', 'famfam': 'hourglass_delete', 'permissions': {'namespace': 'ocr', 'permissions': [PERMISSION_OCR_DOCUMENT_DELETE]}} +queue_document_multiple_delete = {'text': _(u'delete'), 'view': 'queue_document_multiple_delete', 'famfam': 'hourglass_delete', 'permissions': {'namespace': 'ocr', 'permissions': [PERMISSION_OCR_DOCUMENT_DELETE]}} -document_queue_disable = {'text':_(u'stop queue'), 'view':'document_queue_disable', 'args':'object.id', 'famfam':'control_stop_blue', 'permissions':{'namespace':'ocr', 'permissions':[PERMISSION_OCR_QUEUE_ENABLE_DISABLE]}} -document_queue_enable = {'text':_(u'activate queue'), 'view':'document_queue_enable', 'args':'object.id', 'famfam':'control_play_blue', 'permissions':{'namespace':'ocr', 'permissions':[PERMISSION_OCR_QUEUE_ENABLE_DISABLE]}} +document_queue_disable = {'text': _(u'stop queue'), 'view': 'document_queue_disable', 'args': 'object.id', 'famfam': 'control_stop_blue', 'permissions': {'namespace': 'ocr', 'permissions': [PERMISSION_OCR_QUEUE_ENABLE_DISABLE]}} +document_queue_enable = {'text': _(u'activate queue'), 'view': 'document_queue_enable', 'args': 'object.id', 'famfam': 'control_play_blue', 'permissions': {'namespace': 'ocr', 'permissions': [PERMISSION_OCR_QUEUE_ENABLE_DISABLE]}} -all_document_ocr_cleanup = {'text':_(u'clean up pages content'), 'view':'all_document_ocr_cleanup', 'famfam':'text_strikethrough', 'permissions':{'namespace':'ocr', 'permissions':[PERMISSION_OCR_CLEAN_ALL_PAGES]}} +all_document_ocr_cleanup = {'text': _(u'clean up pages content'), 'view': 'all_document_ocr_cleanup', 'famfam': 'text_strikethrough', 'permissions': {'namespace': 'ocr', 'permissions': [PERMISSION_OCR_CLEAN_ALL_PAGES]}} register_links(Document, [submit_document], menu_name='sidebar') register_links(DocumentQueue, [document_queue_disable, document_queue_enable]) @@ -47,9 +47,9 @@ register_multi_item_links(['queue_document_list'], [re_queue_multiple_document, #Menus register_menu([ - {'text':_('OCR'), 'view':'queue_document_list', 'links':[ + {'text': _('OCR'), 'view': 'queue_document_list', 'links':[ #ocr_queue - ],'famfam':'hourglass','position':4}]) + ], 'famfam': 'hourglass', 'position': 4}]) try: diff --git a/apps/ocr/admin.py b/apps/ocr/admin.py index 90a8606a44..c3f19c37bd 100644 --- a/apps/ocr/admin.py +++ b/apps/ocr/admin.py @@ -8,12 +8,11 @@ class QueueDocumentInline(admin.StackedInline): extra = 1 classes = ('collapse-open',) allow_add = True - + class DocumentQueueAdmin(admin.ModelAdmin): inlines = [QueueDocumentInline] list_display = ('name', 'label', 'state') - -admin.site.register(DocumentQueue, DocumentQueueAdmin) +admin.site.register(DocumentQueue, DocumentQueueAdmin) diff --git a/apps/ocr/api.py b/apps/ocr/api.py index ad1f7e3a96..120c39ecee 100644 --- a/apps/ocr/api.py +++ b/apps/ocr/api.py @@ -9,17 +9,16 @@ import sys from django.utils.translation import ugettext as _ from django.utils.importlib import import_module -from common import TEMPORARY_DIRECTORY from converter.api import convert_document_for_ocr from documents.models import DocumentPage from ocr.conf.settings import TESSERACT_PATH from ocr.conf.settings import TESSERACT_LANGUAGE - + def get_language_backend(): try: - module = import_module(u'.'.join([u'ocr',u'lang', TESSERACT_LANGUAGE])) + module = import_module(u'.'.join([u'ocr', u'lang', TESSERACT_LANGUAGE])) except ImportError: sys.stderr.write('\nError: No OCR app language backend for language: %s\n\n' % TESSERACT_LANGUAGE) return None @@ -44,7 +43,7 @@ def run_tesseract(input_filename, output_filename_base, lang=None): command = [TESSERACT_PATH, input_filename, output_filename_base] if lang is not None: command += ['-l', lang] - + proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) return_code = proc.wait() if return_code != 0: @@ -87,10 +86,10 @@ def ocr_cleanup(text): if result: output.append(result) output.append('\n') - + return u' '.join(output) - + def clean_pages(): for page in DocumentPage.objects.all(): if page.content: diff --git a/apps/ocr/conf/settings.py b/apps/ocr/conf/settings.py index a0f0a80612..fd0220d991 100644 --- a/apps/ocr/conf/settings.py +++ b/apps/ocr/conf/settings.py @@ -1,7 +1,8 @@ from django.conf import settings + TESSERACT_PATH = getattr(settings, 'OCR_TESSERACT_PATH', u'/usr/bin/tesseract') TESSERACT_LANGUAGE = getattr(settings, 'OCR_TESSERACT_LANGUAGE', None) -REPLICATION_DELAY = getattr(settings, 'OCR_REPLICATION_DELAY', 10) #In seconds +REPLICATION_DELAY = getattr(settings, 'OCR_REPLICATION_DELAY', 10) # In seconds NODE_CONCURRENT_EXECUTION = getattr(settings, 'OCR_NODE_CONCURRENT_EXECUTION', 1) AUTOMATIC_OCR = getattr(settings, 'OCR_AUTOMATIC_OCR', False) diff --git a/apps/ocr/models.py b/apps/ocr/models.py index 095036ffd2..e42418b84e 100644 --- a/apps/ocr/models.py +++ b/apps/ocr/models.py @@ -10,7 +10,7 @@ from literals import DOCUMENTQUEUE_STATE_STOPPED, \ QUEUEDOCUMENT_STATE_CHOICES from exceptions import AlreadyQueued - + class DocumentQueueManager(models.Manager): def queue_document(self, document, queue_name='default'): document_queue = DocumentQueue.objects.get(name=queue_name) @@ -18,7 +18,7 @@ class DocumentQueueManager(models.Manager): raise AlreadyQueued queue_document = QueueDocument(document_queue=document_queue, document=document, delay=True) - queue_document.save() + queue_document.save() return document_queue @@ -30,16 +30,16 @@ class DocumentQueue(models.Model): choices=DOCUMENTQUEUE_STATE_CHOICES, default=DOCUMENTQUEUE_STATE_STOPPED, verbose_name=_(u'state')) - + objects = DocumentQueueManager() - + class Meta: verbose_name = _(u'document queue') verbose_name_plural = _(u'document queues') def __unicode__(self): return self.label - + class QueueDocument(models.Model): document_queue = models.ForeignKey(DocumentQueue, verbose_name=_(u'document queue')) @@ -52,7 +52,7 @@ class QueueDocument(models.Model): verbose_name=_(u'state')) result = models.TextField(blank=True, null=True, verbose_name=_(u'result')) node_name = models.CharField(max_length=32, verbose_name=_(u'node name'), blank=True, null=True) - + class Meta: ordering = ('datetime_submitted',) verbose_name = _(u'queue document') diff --git a/apps/ocr/statistics.py b/apps/ocr/statistics.py index 5391ed987c..3d5728b94e 100644 --- a/apps/ocr/statistics.py +++ b/apps/ocr/statistics.py @@ -9,8 +9,8 @@ def get_statistics(): _(u'Document queues: %d') % DocumentQueue.objects.count(), _(u'Queued documents: %d') % QueueDocument.objects.only('pk').count() ] - + return { - 'title':_(u'OCR statistics'), + 'title': _(u'OCR statistics'), 'paragraphs': paragraphs } diff --git a/apps/ocr/tasks.py b/apps/ocr/tasks.py index 98ff963a84..a191f31ac8 100644 --- a/apps/ocr/tasks.py +++ b/apps/ocr/tasks.py @@ -16,7 +16,7 @@ from models import QueueDocument, DocumentQueue from ocr.conf.settings import NODE_CONCURRENT_EXECUTION from ocr.conf.settings import REPLICATION_DELAY - + @task def task_process_queue_document(queue_document_id): queue_document = QueueDocument.objects.get(id=queue_document_id) @@ -32,7 +32,7 @@ def task_process_queue_document(queue_document_id): except Exception, e: queue_document.state = QUEUEDOCUMENT_STATE_ERROR queue_document.result = e - queue_document.save() + queue_document.save() class DocumentQueueWatcher(PeriodicTask): @@ -47,7 +47,7 @@ class DocumentQueueWatcher(PeriodicTask): logger.debug('Active queues: %s' % DocumentQueue.objects.filter(state=DOCUMENTQUEUE_STATE_ACTIVE)) q_pending = Q(state=QUEUEDOCUMENT_STATE_PENDING) q_delayed = Q(delay=True) - q_delay_interval = Q(datetime_submitted__lt=datetime.now()-timedelta(seconds=REPLICATION_DELAY)) + q_delay_interval = Q(datetime_submitted__lt=datetime.now() - timedelta(seconds=REPLICATION_DELAY)) for document_queue in DocumentQueue.objects.filter(state=DOCUMENTQUEUE_STATE_ACTIVE): logger.debug('Analysing queue: %s' % document_queue) if QueueDocument.objects.filter( @@ -56,7 +56,7 @@ class DocumentQueueWatcher(PeriodicTask): try: oldest_queued_document_qs = document_queue.queuedocument_set.filter( (q_pending & ~q_delayed) | (q_pending & q_delayed & q_delay_interval)) - + if oldest_queued_document_qs: oldest_queued_document = oldest_queued_document_qs.order_by('datetime_submitted')[0] task_process_queue_document.delay(oldest_queued_document.id) diff --git a/apps/ocr/urls.py b/apps/ocr/urls.py index b65f910e26..a245783c11 100644 --- a/apps/ocr/urls.py +++ b/apps/ocr/urls.py @@ -1,5 +1,4 @@ -from django.conf.urls.defaults import * -from django.utils.translation import ugettext_lazy as _ +from django.conf.urls.defaults import patterns, url urlpatterns = patterns('ocr.views', url(r'^(?P\d+)/submit/$', 'submit_document', (), 'submit_document'), @@ -11,6 +10,6 @@ urlpatterns = patterns('ocr.views', url(r'^ocr/queue/(?P\d+)/enable/$', 'document_queue_enable', (), 'document_queue_enable'), url(r'^ocr/queue/(?P\d+)/disable/$', 'document_queue_disable', (), 'document_queue_disable'), - + url(r'^ocr/document/all/clean_up/$', 'all_document_ocr_cleanup', (), 'all_document_ocr_cleanup'), ) diff --git a/apps/ocr/views.py b/apps/ocr/views.py index b32f5b8399..bb7aa13f3c 100644 --- a/apps/ocr/views.py +++ b/apps/ocr/views.py @@ -1,7 +1,7 @@ import datetime from django.http import HttpResponseRedirect -from django.shortcuts import render_to_response, get_object_or_404, redirect +from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from django.contrib import messages from django.views.generic.list_detail import object_list @@ -16,11 +16,12 @@ from ocr import PERMISSION_OCR_DOCUMENT, PERMISSION_OCR_DOCUMENT_DELETE, \ from models import DocumentQueue, QueueDocument from literals import QUEUEDOCUMENT_STATE_PENDING, \ - QUEUEDOCUMENT_STATE_PROCESSING, QUEUEDOCUMENT_STATE_ERROR, \ - DOCUMENTQUEUE_STATE_STOPPED, DOCUMENTQUEUE_STATE_ACTIVE + QUEUEDOCUMENT_STATE_PROCESSING, DOCUMENTQUEUE_STATE_STOPPED, \ + DOCUMENTQUEUE_STATE_ACTIVE from exceptions import AlreadyQueued from api import clean_pages + def _display_thumbnail(ocr_document): try: preview_url = reverse('document_preview', args=[ocr_document.document.pk]) @@ -32,7 +33,7 @@ def _display_thumbnail(ocr_document): def queue_document_list(request, queue_name='default'): check_permissions(request.user, 'ocr', [PERMISSION_OCR_DOCUMENT]) - + document_queue = get_object_or_404(DocumentQueue, name=queue_name) return object_list( @@ -40,30 +41,30 @@ def queue_document_list(request, queue_name='default'): queryset=document_queue.queuedocument_set.all(), template_name='generic_list.html', extra_context={ - 'title':_(u'documents in queue: %s') % document_queue, - 'hide_object':True, - 'object':document_queue, - 'object_name':_(u'document queue'), - 'extra_columns':[ - {'name':'document', 'attribute': lambda x: '%s' % (x.document.get_absolute_url(), x.document) if hasattr(x, 'document') else _(u'Missing document.')}, - {'name':_(u'thumbnail'), 'attribute': lambda x: _display_thumbnail(x) }, - {'name':'submitted', 'attribute': lambda x: unicode(x.datetime_submitted).split('.')[0], 'keep_together':True}, - {'name':'delay', 'attribute':'delay'}, - {'name':'state', 'attribute': lambda x: x.get_state_display()}, - {'name':'node', 'attribute':'node_name'}, - {'name':'result', 'attribute':'result'}, + 'title': _(u'documents in queue: %s') % document_queue, + 'hide_object': True, + 'object': document_queue, + 'object_name': _(u'document queue'), + 'extra_columns': [ + {'name': 'document', 'attribute': lambda x: '%s' % (x.document.get_absolute_url(), x.document) if hasattr(x, 'document') else _(u'Missing document.')}, + {'name': _(u'thumbnail'), 'attribute': lambda x: _display_thumbnail(x)}, + {'name': 'submitted', 'attribute': lambda x: unicode(x.datetime_submitted).split('.')[0], 'keep_together':True}, + {'name': 'delay', 'attribute': 'delay'}, + {'name': 'state', 'attribute': lambda x: x.get_state_display()}, + {'name': 'node', 'attribute': 'node_name'}, + {'name': 'result', 'attribute': 'result'}, ], - 'multi_select_as_buttons':True, - 'sidebar_subtemplates_list':[ + 'multi_select_as_buttons': True, + 'sidebar_subtemplates_list': [ { - 'title':_(u'document queue properties'), - 'name':'generic_subtemplate.html', - 'content':_(u'Current state: %s') % document_queue.get_state_display(), + 'title': _(u'document queue properties'), + 'name': 'generic_subtemplate.html', + 'content': _(u'Current state: %s') % document_queue.get_state_display(), }], }, - ) - - + ) + + def queue_document_delete(request, queue_document_id=None, queue_document_id_list=[]): check_permissions(request.user, 'ocr', [PERMISSION_OCR_DOCUMENT_DELETE]) @@ -76,7 +77,7 @@ def queue_document_delete(request, queue_document_id=None, queue_document_id_lis else: messages.error(request, _(u'Must provide at least one queue document.')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) - + next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) @@ -85,57 +86,57 @@ def queue_document_delete(request, queue_document_id=None, queue_document_id_lis try: queue_document.delete() messages.success(request, _(u'Document: %(document)s deleted successfully.') % { - 'document':queue_document.document}) + 'document': queue_document.document}) except Exception, e: messages.error(request, _(u'Error deleting document: %(document)s; %(error)s') % { - 'document':queue_document, 'error':e}) + 'document': queue_document, 'error': e}) return HttpResponseRedirect(next) context = { - 'next':next, - 'previous':previous, - 'delete_view':True + 'next': next, + 'previous': previous, + 'delete_view': True } - + if len(queue_documents) == 1: - context['object'] = queue_documents[0] + context['object'] = queue_documents[0] context['title'] = _(u'Are you sure you with to delete from queue document: %s?') % ', '.join([unicode(d) for d in queue_documents]) elif len(queue_documents) > 1: context['title'] = _(u'Are you sure you with to delete from queue documents: %s?') % ', '.join([unicode(d) for d in queue_documents]) - + return render_to_response('generic_confirm.html', context, context_instance=RequestContext(request)) - + def queue_document_multiple_delete(request): return queue_document_delete(request, queue_document_id_list=request.GET.get('id_list', [])) - + def submit_document(request, document_id): check_permissions(request.user, 'ocr', [PERMISSION_OCR_DOCUMENT]) - + document = get_object_or_404(Document, pk=document_id) - return submit_document_to_queue(request, document=document, + return submit_document_to_queue(request, document=document, post_submit_redirect=request.META['HTTP_REFERER']) - + def submit_document_to_queue(request, document, post_submit_redirect=None): """This view is meant to be reusable""" - + try: document_queue = DocumentQueue.objects.queue_document(document) messages.success(request, _(u'Document: %(document)s was added to the OCR queue: %(queue)s.') % { - 'document':document, 'queue':document_queue.label}) + 'document': document, 'queue': document_queue.label}) except AlreadyQueued: messages.warning(request, _(u'Document: %(document)s is already queued.') % { - 'document':document}) + 'document': document}) except Exception, e: messages.error(request, e) if post_submit_redirect: return HttpResponseRedirect(post_submit_redirect) - + def re_queue_document(request, queue_document_id=None, queue_document_id_list=[]): check_permissions(request.user, 'ocr', [PERMISSION_OCR_DOCUMENT]) @@ -149,7 +150,7 @@ def re_queue_document(request, queue_document_id=None, queue_document_id_list=[] else: messages.error(request, _(u'Must provide at least one queue document.')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) - + next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) @@ -175,26 +176,26 @@ def re_queue_document(request, queue_document_id=None, queue_document_id_list=[] queue_document.node_name = None queue_document.save() messages.success(request, _(u'Document: %(document)s was re-queued to the OCR queue: %(queue)s') % { - 'document':queue_document.document, 'queue':queue_document.document_queue.label}) + 'document': queue_document.document, 'queue': queue_document.document_queue.label}) else: messages.success(request, _(u'Document: %(document)s can\'t be re-queued.') % { - 'document':queue_document.document}) + 'document': queue_document.document}) except Exception, e: messages.error(request, e) return HttpResponseRedirect(next) context = { - 'next':next, - 'previous':previous, + 'next': next, + 'previous': previous, } - + if len(queue_documents) == 1: - context['object'] = queue_documents[0] + context['object'] = queue_documents[0] context['title'] = _(u'Are you sure you with to re-queue document: %s?') % ', '.join([unicode(d) for d in queue_documents]) elif len(queue_documents) > 1: context['title'] = _(u'Are you sure you with to re-queue documents: %s?') % ', '.join([unicode(d) for d in queue_documents]) - + return render_to_response('generic_confirm.html', context, context_instance=RequestContext(request)) @@ -207,9 +208,9 @@ def document_queue_disable(request, document_queue_id): check_permissions(request.user, 'ocr', [PERMISSION_OCR_QUEUE_ENABLE_DISABLE]) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None))) - previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) + previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) document_queue = get_object_or_404(DocumentQueue, pk=document_queue_id) - + if document_queue.state == DOCUMENTQUEUE_STATE_STOPPED: messages.warning(request, _(u'Document queue: %s, already stopped.') % document_queue) return HttpResponseRedirect(previous) @@ -219,22 +220,22 @@ def document_queue_disable(request, document_queue_id): document_queue.save() messages.success(request, _(u'Document queue: %s, stopped successfully.') % document_queue) return HttpResponseRedirect(next) - + return render_to_response('generic_confirm.html', { - 'object':document_queue, - 'title':_(u'Are you sure you wish to disable document queue: %s') % document_queue, - 'next':next, - 'previous':previous, - }, context_instance=RequestContext(request)) - + 'object': document_queue, + 'title': _(u'Are you sure you wish to disable document queue: %s') % document_queue, + 'next': next, + 'previous': previous, + }, context_instance=RequestContext(request)) + def document_queue_enable(request, document_queue_id): check_permissions(request.user, 'ocr', [PERMISSION_OCR_QUEUE_ENABLE_DISABLE]) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None))) - previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) + previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) document_queue = get_object_or_404(DocumentQueue, pk=document_queue_id) - + if document_queue.state == DOCUMENTQUEUE_STATE_ACTIVE: messages.warning(request, _(u'Document queue: %s, already active.') % document_queue) return HttpResponseRedirect(previous) @@ -244,12 +245,12 @@ def document_queue_enable(request, document_queue_id): document_queue.save() messages.success(request, _(u'Document queue: %s, activated successfully.') % document_queue) return HttpResponseRedirect(next) - + return render_to_response('generic_confirm.html', { - 'object':document_queue, - 'title':_(u'Are you sure you wish to activate document queue: %s') % document_queue, - 'next':next, - 'previous':previous, + 'object': document_queue, + 'title': _(u'Are you sure you wish to activate document queue: %s') % document_queue, + 'next': next, + 'previous': previous, }, context_instance=RequestContext(request)) @@ -258,18 +259,18 @@ def all_document_ocr_cleanup(request): previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None))) - + if request.method != 'POST': return render_to_response('generic_confirm.html', { - 'previous':previous, - 'next':next, - 'message':_(u'On large databases this operation may take some time to execute.'), + 'previous': previous, + 'next': next, + 'message': _(u'On large databases this operation may take some time to execute.'), }, context_instance=RequestContext(request)) - else: + else: try: clean_pages() messages.success(request, _(u'Document pages content clean up complete.')) except Exception, e: messages.error(request, _(u'Document pages content clean up error: %s') % e) - + return HttpResponseRedirect(next) diff --git a/apps/permissions/__init__.py b/apps/permissions/__init__.py index 94f7521ee8..0236b85a2a 100644 --- a/apps/permissions/__init__.py +++ b/apps/permissions/__init__.py @@ -4,7 +4,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.utils.translation import ugettext_lazy as _ from navigation.api import register_links, register_menu - + from permissions.conf.settings import DEFAULT_ROLES from models import Role @@ -16,11 +16,11 @@ PERMISSION_PERMISSION_GRANT = 'permission_grant' PERMISSION_PERMISSION_REVOKE = 'permission_revoke' -role_list = {'text':_(u'roles'), 'view':'role_list', 'famfam':'medal_gold_1', 'permissions':{'namespace':'permissions', 'permissions':[PERMISSION_ROLE_VIEW]}} -role_create = {'text':_(u'create new role'), 'view':'role_create', 'famfam':'medal_gold_add', 'permissions':{'namespace':'permissions', 'permissions':[PERMISSION_ROLE_CREATE]}} -role_edit = {'text':_(u'edit'), 'view':'role_edit', 'args':'object.id', 'famfam':'medal_gold_1', 'permissions':{'namespace':'permissions', 'permissions':[PERMISSION_ROLE_EDIT]}} -role_permissions = {'text':_(u'role permissions'), 'view':'role_permissions', 'args':'object.id', 'famfam':'key_go', 'permissions':{'namespace':'permissions', 'permissions':[PERMISSION_PERMISSION_GRANT, PERMISSION_PERMISSION_REVOKE]}} -role_delete = {'text':_(u'delete'), 'view':'role_delete', 'args':'object.id', 'famfam':'medal_gold_delete', 'permissions':{'namespace':'permissions', 'permissions':[PERMISSION_ROLE_DELETE]}} +role_list = {'text': _(u'roles'), 'view': 'role_list', 'famfam': 'medal_gold_1', 'permissions': {'namespace': 'permissions', 'permissions': [PERMISSION_ROLE_VIEW]}} +role_create = {'text': _(u'create new role'), 'view': 'role_create', 'famfam': 'medal_gold_add', 'permissions': {'namespace': 'permissions', 'permissions': [PERMISSION_ROLE_CREATE]}} +role_edit = {'text': _(u'edit'), 'view': 'role_edit', 'args': 'object.id', 'famfam': 'medal_gold_1', 'permissions': {'namespace': 'permissions', 'permissions': [PERMISSION_ROLE_EDIT]}} +role_permissions = {'text': _(u'role permissions'), 'view': 'role_permissions', 'args': 'object.id', 'famfam': 'key_go', 'permissions': {'namespace': 'permissions', 'permissions': [PERMISSION_PERMISSION_GRANT, PERMISSION_PERMISSION_REVOKE]}} +role_delete = {'text': _(u'delete'), 'view': 'role_delete', 'args': 'object.id', 'famfam': 'medal_gold_delete', 'permissions': {'namespace': 'permissions', 'permissions': [PERMISSION_ROLE_DELETE]}} register_links(Role, [role_permissions, role_edit, role_delete]) register_links(['role_list', 'role_view', 'role_create', 'role_edit', 'role_permissions', 'role_delete'], [role_create], menu_name='sidebar') diff --git a/apps/permissions/forms.py b/apps/permissions/forms.py index 40bec56fe8..9d7851216d 100644 --- a/apps/permissions/forms.py +++ b/apps/permissions/forms.py @@ -9,9 +9,8 @@ from models import Role class RoleForm(forms.ModelForm): class Meta: model = Role - + class RoleForm_view(DetailForm): class Meta: model = Role - diff --git a/apps/permissions/middleware/permission_denied_middleware.py b/apps/permissions/middleware/permission_denied_middleware.py index 2902d7c0af..50cc15289e 100644 --- a/apps/permissions/middleware/permission_denied_middleware.py +++ b/apps/permissions/middleware/permission_denied_middleware.py @@ -1,16 +1,17 @@ from django.conf import settings -from django.core.exceptions import PermissionDenied +from django.core.exceptions import PermissionDenied from django.http import HttpResponseForbidden from django.template import RequestContext, Template, loader, TemplateDoesNotExist from django.utils.importlib import import_module + #http://mitchfournier.com/2010/07/12/show-a-custom-403-forbidden-error-page-in-django/ class PermissionDeniedMiddleware(object): def process_exception(self, request, exception): if isinstance(exception, PermissionDenied): try: # Handle import error but allow any type error from view - callback = getattr(import_module(settings.ROOT_URLCONF),'handler403') + callback = getattr(import_module(settings.ROOT_URLCONF), 'handler403') return callback(request, exception) except (ImportError, AttributeError): # Try to get a 403 template diff --git a/apps/permissions/models.py b/apps/permissions/models.py index 013a236812..de6687d1f0 100644 --- a/apps/permissions/models.py +++ b/apps/permissions/models.py @@ -9,13 +9,14 @@ class PermissionManager(models.Manager): ct = ContentType.objects.get_for_model(holder) return [Permission.objects.get(id=id) for id in PermissionHolder.objects.filter(holder_type=ct, holder_id=holder.id).values_list('permission_id', flat=True)] + class Permission(models.Model): namespace = models.CharField(max_length=64, verbose_name=_(u'namespace')) name = models.CharField(max_length=64, verbose_name=_(u'name')) label = models.CharField(max_length=64, verbose_name=_(u'label')) objects = PermissionManager() - + class Meta: ordering = ('namespace', 'label') unique_together = ('namespace', 'name') @@ -28,16 +29,16 @@ class Permission(models.Model): class PermissionHolder(models.Model): permission = models.ForeignKey(Permission, verbose_name=_(u'permission')) - holder_type = models.ForeignKey(ContentType, - related_name='permission_holder', - limit_choices_to = {'model__in': ('user', 'group', 'role')}) + holder_type = models.ForeignKey(ContentType, + related_name='permission_holder', + limit_choices_to={'model__in': ('user', 'group', 'role')}) holder_id = models.PositiveIntegerField() holder_object = generic.GenericForeignKey(ct_field='holder_type', fk_field='holder_id') class Meta: verbose_name = _(u'permission holder') verbose_name_plural = _(u'permission holders') - + def __unicode__(self): return unicode(self.holder_object) @@ -45,7 +46,7 @@ class PermissionHolder(models.Model): class Role(models.Model): name = models.CharField(max_length=64, unique=True) label = models.CharField(max_length=64, unique=True, verbose_name=_(u'label')) - + class Meta: ordering = ('label',) verbose_name = _(u'role') @@ -54,12 +55,12 @@ class Role(models.Model): def add_member(self, member): role_member, created = RoleMember.objects.get_or_create( role=self, - member_type = ContentType.objects.get_for_model(member), + member_type=ContentType.objects.get_for_model(member), member_id=member.id) - + def __unicode__(self): return self.label - + @models.permalink def get_absolute_url(self): return ('role_list',) @@ -68,8 +69,8 @@ class Role(models.Model): class RoleMember(models.Model): role = models.ForeignKey(Role, verbose_name=_(u'role')) member_type = models.ForeignKey(ContentType, - related_name='role_member', - limit_choices_to = {'model__in': ('user', 'group')}) + related_name='role_member', + limit_choices_to={'model__in': ('user', 'group')}) member_id = models.PositiveIntegerField() member_object = generic.GenericForeignKey(ct_field='member_type', fk_field='member_id') @@ -77,6 +78,6 @@ class RoleMember(models.Model): #ordering = ('label',) verbose_name = _(u'role member') verbose_name_plural = _(u'role members') - + def __unicode__(self): return unicode(self.member_object) diff --git a/apps/permissions/templatetags/permission_tags.py b/apps/permissions/templatetags/permission_tags.py index 7f77d3c198..6dc6055f65 100644 --- a/apps/permissions/templatetags/permission_tags.py +++ b/apps/permissions/templatetags/permission_tags.py @@ -1,4 +1,4 @@ -from django.core.exceptions import PermissionDenied +from django.core.exceptions import PermissionDenied from django.template import TemplateSyntaxError, Library, \ Node, Variable @@ -12,7 +12,7 @@ class CheckPermissionsNode(Node): self.requester = requester self.namespace = namespace self.permission_list = permission_list - + def render(self, context): requester = Variable(self.requester).resolve(context) namespace = Variable(self.namespace).resolve(context) @@ -32,7 +32,6 @@ def check_permissions(parser, token): # Splitting by None == splitting by spaces. tag_name, args = token.contents.split(None, 1) except ValueError: - raise TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0] - + raise TemplateSyntaxError('%r tag requires arguments' % token.contents.split()[0]) + return CheckPermissionsNode(*args.split()) - diff --git a/apps/permissions/urls.py b/apps/permissions/urls.py index 76bb2af84e..761c1e0be8 100644 --- a/apps/permissions/urls.py +++ b/apps/permissions/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import * +from django.conf.urls.defaults import patterns, url urlpatterns = patterns('permissions.views', url(r'^role/list/$', 'role_list', (), 'role_list'), @@ -7,6 +7,6 @@ urlpatterns = patterns('permissions.views', url(r'^role/(?P\d+)/edit/$', 'role_edit', (), 'role_edit'), url(r'^role/(?P\d+)/delete/$', 'role_delete', (), 'role_delete'), - url(r'^permission/(?P\d+)/for/(?P[\w\-]+)/(?P[\w\-]+)/(?P\d+)/grant/$', 'permission_grant_revoke', {'action':'grant'}, 'permission_grant'), - url(r'^permission/(?P\d+)/for/(?P[\w\-]+)/(?P[\w\-]+)/(?P\d+)/revoke/$', 'permission_grant_revoke', {'action':'revoke'}, 'permission_revoke'), + url(r'^permission/(?P\d+)/for/(?P[\w\-]+)/(?P[\w\-]+)/(?P\d+)/grant/$', 'permission_grant_revoke', {'action': 'grant'}, 'permission_grant'), + url(r'^permission/(?P\d+)/for/(?P[\w\-]+)/(?P[\w\-]+)/(?P\d+)/revoke/$', 'permission_grant_revoke', {'action': 'revoke'}, 'permission_revoke'), ) diff --git a/apps/permissions/views.py b/apps/permissions/views.py index 8b9d031c09..aff2b5b409 100644 --- a/apps/permissions/views.py +++ b/apps/permissions/views.py @@ -19,14 +19,14 @@ from api import check_permissions def role_list(request): check_permissions(request.user, 'permissions', [PERMISSION_ROLE_VIEW]) - + return object_list( request, queryset=Role.objects.all(), template_name='generic_list.html', extra_context={ - 'title':_(u'roles'), - 'hide_link':True, + 'title': _(u'roles'), + 'hide_link': True, }, ) @@ -38,19 +38,19 @@ def _role_permission_link(requester, permission, permission_list): if permission in permission_list: return template % { - 'url':reverse('permission_revoke', + 'url': reverse('permission_revoke', args=[permission.id, ct.app_label, ct.model, requester.id]), - 'icon':'delete', 'text':_(u'Revoke')} + 'icon': 'delete', 'text': _(u'Revoke')} else: return template % { - 'url':reverse('permission_grant', + 'url': reverse('permission_grant', args=[permission.id, ct.app_label, ct.model, requester.id]), - 'icon':'add', 'text':_(u'Grant')} - - + 'icon': 'add', 'text': _(u'Grant')} + + def role_permissions(request, role_id): check_permissions(request.user, 'permissions', [PERMISSION_PERMISSION_GRANT, PERMISSION_PERMISSION_REVOKE]) - + role = get_object_or_404(Role, pk=role_id) form = RoleForm_view(instance=role) @@ -69,47 +69,48 @@ def role_permissions(request, role_id): 'hide_object':True, }, ] - + return render_to_response('generic_detail.html', { - 'form':form, - 'object':role, - 'object_name':_(u'role'), - 'subtemplates_dict':subtemplates_dict, + 'form': form, + 'object': role, + 'object_name': _(u'role'), + 'subtemplates_dict': subtemplates_dict, }, context_instance=RequestContext(request)) def role_edit(request, role_id): check_permissions(request.user, 'permissions', [PERMISSION_ROLE_EDIT]) - return update_object(request, template_name='generic_form.html', + return update_object(request, template_name='generic_form.html', form_class=RoleForm, object_id=role_id, extra_context={ - 'object_name':_(u'role')}) + 'object_name': _(u'role')}) def role_create(request): check_permissions(request.user, 'permissions', [PERMISSION_ROLE_CREATE]) - return create_object(request, model=Role, + return create_object(request, model=Role, template_name='generic_form.html', post_save_redirect=reverse('role_list')) - + def role_delete(request, role_id): check_permissions(request.user, 'permissions', [PERMISSION_ROLE_DELETE]) - + next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) - - return delete_object(request, model=Role, object_id=role_id, - template_name='generic_confirm.html', + + return delete_object(request, model=Role, object_id=role_id, + template_name='generic_confirm.html', post_delete_redirect=reverse('role_list'), extra_context={ - 'delete_view':True, - 'next':next, - 'previous':previous, - 'object_name':_(u'role'), + 'delete_view': True, + 'next': next, + 'previous': previous, + 'object_name': _(u'role'), }) + def permission_grant_revoke(request, permission_id, app_label, module_name, pk, action): ct = get_object_or_404(ContentType, app_label=app_label, model=module_name) requester_model = ct.model_class() @@ -119,42 +120,41 @@ def permission_grant_revoke(request, permission_id, app_label, module_name, pk, if action == 'grant': check_permissions(request.user, 'permissions', [PERMISSION_PERMISSION_GRANT]) title = _('Are you sure you wish to grant the permission "%(permission)s" to %(ct_name)s: %(requester)s') % { - 'permission':permission, 'ct_name':ct.name, 'requester':requester} + 'permission': permission, 'ct_name': ct.name, 'requester': requester} elif action == 'revoke': check_permissions(request.user, 'permissions', [PERMISSION_PERMISSION_REVOKE]) title = _('Are you sure you wish to revoke the permission "%(permission)s" from %(ct_name)s: %(requester)s') % { - 'permission':permission, 'ct_name':ct.name, 'requester':requester} + 'permission': permission, 'ct_name': ct.name, 'requester': requester} else: return HttpResponseRedirect('/') next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', None))) - if request.method == 'POST': if action == 'grant': permission_holder, created = PermissionHolder.objects.get_or_create(permission=permission, holder_type=ct, holder_id=requester.id) if created: messages.success(request, _(u'Permission "%(permission)s" granted to %(ct_name)s: %(requester)s.') % { - 'permission':permission, 'ct_name':ct.name, 'requester':requester}) + 'permission': permission, 'ct_name': ct.name, 'requester': requester}) else: messages.warning(request, _(u'%(ct_name)s: %(requester)s, already had the permission "%(permission)s" granted.') % { - 'ct_name':ct.name, 'requester':requester, 'permission':permission}) + 'ct_name': ct.name, 'requester': requester, 'permission': permission}) elif action == 'revoke': try: permission_holder = PermissionHolder.objects.get(permission=permission, holder_type=ct, holder_id=requester.id) permission_holder.delete() messages.success(request, _(u'Permission "%(permission)s" revoked from %(ct_name)s: %(requester)s.') % { - 'permission':permission, 'ct_name':ct.name, 'requester':requester}) + 'permission': permission, 'ct_name': ct.name, 'requester': requester}) except ObjectDoesNotExist: messages.warning(request, _(u'%(ct_name)s: %(requester)s doesn\'t have the permission "%(permission)s".') % { - 'ct_name':ct.name, 'requester':requester, 'permission':permission}) + 'ct_name': ct.name, 'requester': requester, 'permission': permission}) return HttpResponseRedirect(next) - + return render_to_response('generic_confirm.html', { - 'object':requester, - 'next':next, - 'previous':previous, - 'title':title, + 'object': requester, + 'next': next, + 'previous': previous, + 'title': title, }, context_instance=RequestContext(request))