Created new metadata app and move all code relating metadata to it

This commit is contained in:
Roberto Rosario
2011-05-10 03:41:35 -04:00
parent b4daa2d52b
commit ea20cde597
20 changed files with 601 additions and 320 deletions

View File

@@ -15,7 +15,6 @@ from documents.conf.settings import ENABLE_SINGLE_DOCUMENT_UPLOAD
PERMISSION_DOCUMENT_CREATE = 'document_create'
PERMISSION_DOCUMENT_PROPERTIES_EDIT = 'document_properties_edit'
PERMISSION_DOCUMENT_EDIT = 'document_edit'
PERMISSION_DOCUMENT_METADATA_EDIT = 'document_metadata_edit'
PERMISSION_DOCUMENT_VIEW = 'document_view'
PERMISSION_DOCUMENT_DELETE = 'document_delete'
PERMISSION_DOCUMENT_DOWNLOAD = 'document_download'
@@ -26,7 +25,6 @@ register_permissions('documents', [
{'name': PERMISSION_DOCUMENT_CREATE, 'label': _(u'Create document')},
{'name': PERMISSION_DOCUMENT_PROPERTIES_EDIT, 'label': _(u'Edit document properties')},
{'name': PERMISSION_DOCUMENT_EDIT, 'label': _(u'Edit document')},
{'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')},
@@ -44,8 +42,6 @@ document_view_simple = {'text': _(u'details (simple)'), 'view': 'document_view_s
document_delete = {'text': _(u'delete'), 'view': 'document_delete', 'args': 'object.id', 'famfam': 'page_delete', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_DELETE]}}
document_multiple_delete = {'text': _(u'delete'), 'view': 'document_multiple_delete', 'famfam': 'page_delete', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_DELETE]}}
document_edit = {'text': _(u'edit'), 'view': 'document_edit', 'args': 'object.id', 'famfam': 'page_edit', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_PROPERTIES_EDIT]}}
document_edit_metadata = {'text': _(u'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': _(u'edit metadata'), 'view': 'document_multiple_edit_metadata', 'famfam': 'page_edit', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_METADATA_EDIT]}}
document_preview = {'text': _(u'preview'), 'class': 'fancybox', 'view': 'document_preview', 'args': 'object.id', 'famfam': 'magnifier', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
document_download = {'text': _(u'download'), 'view': 'document_download', 'args': 'object.id', 'famfam': 'page_save', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_DOWNLOAD]}}
document_find_duplicates = {'text': _(u'find duplicates'), 'view': 'document_find_duplicates', 'args': 'object.id', 'famfam': 'page_refresh', 'permissions': {'namespace': 'documents', 'permissions': [PERMISSION_DOCUMENT_VIEW]}}
@@ -83,10 +79,10 @@ metadata_group_create_sibling = {'text': _(u'upload new document using same meta
staging_file_preview = {'text': _(u'preview'), 'class': 'fancybox-noscaling', 'view': 'staging_file_preview', 'args': 'object.id', 'famfam': 'drive_magnify'}
staging_file_delete = {'text': _(u'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_print, document_delete, document_download, document_find_duplicates, document_clear_transformations])
register_links(Document, [document_view_simple, document_view, document_edit, document_print, document_delete, document_download, document_find_duplicates, document_clear_transformations])
register_links(Document, [document_create_sibling], menu_name='sidebar')
register_multi_item_links(['metadatagroup_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_edit_metadata, document_multiple_delete])
register_multi_item_links(['metadatagroup_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_delete])
if ENABLE_SINGLE_DOCUMENT_UPLOAD:
register_links(['document_list_recent', 'document_list', 'document_create', 'document_create_multiple', 'upload_document_with_type', 'upload_multiple_documents_with_type'], [document_list_recent, document_list, document_create, document_create_multiple], menu_name='sidebar')

View File

@@ -1,17 +1,14 @@
from django.contrib import admin
from documents.models import MetadataType, DocumentType, Document, \
MetadataSet, MetadataSetItem, DocumentMetadata, \
from metadata.admin import DocumentMetadataInline
from documents.models import DocumentType, Document, \
DocumentTypeFilename, MetadataIndex, DocumentPage, DocumentGroup, \
DocumentGroupItem, DocumentPageTransformation, RecentDocument
from filesystem_serving.admin import DocumentMetadataIndexInline
class MetadataTypeAdmin(admin.ModelAdmin):
list_display = ('name', 'title', 'default', 'lookup')
class MetadataIndexInline(admin.StackedInline):
model = MetadataIndex
extra = 1
@@ -19,13 +16,6 @@ class MetadataIndexInline(admin.StackedInline):
allow_add = True
class MetadataSetItemInline(admin.StackedInline):
model = MetadataSetItem
extra = 1
classes = ('collapse-open',)
allow_add = True
class DocumentTypeFilenameInline(admin.StackedInline):
model = DocumentTypeFilename
extra = 1
@@ -39,13 +29,6 @@ class DocumentTypeAdmin(admin.ModelAdmin):
]
class DocumentMetadataInline(admin.StackedInline):
model = DocumentMetadata
extra = 0
classes = ('collapse-open',)
allow_add = False
class DocumentPageTransformationAdmin(admin.ModelAdmin):
model = DocumentPageTransformation
@@ -85,15 +68,9 @@ class RecentDocumentAdmin(admin.ModelAdmin):
date_hierarchy = 'datetime_accessed'
class MetadataSetAdmin(admin.ModelAdmin):
inlines = [MetadataSetItemInline]
admin.site.register(MetadataType, MetadataTypeAdmin)
admin.site.register(DocumentType, DocumentTypeAdmin)
admin.site.register(Document, DocumentAdmin)
admin.site.register(MetadataGroup, MetadataGroupAdmin)
admin.site.register(DocumentGroup, DocumentGroupAdmin)
admin.site.register(DocumentPageTransformation,
DocumentPageTransformationAdmin)
admin.site.register(RecentDocument, RecentDocumentAdmin)
admin.site.register(MetadataSet, MetadataSetAdmin)

View File

@@ -1,11 +1,9 @@
"""Configuration options for the documents app"""
import datetime
import hashlib
import uuid
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from common.utils import proper_name
from storage.backends.filebasedstorage import FileBasedStorage
@@ -21,14 +19,6 @@ def default_uuid():
"""unicode(uuid.uuid4())"""
return unicode(uuid.uuid4())
default_available_functions = {
'current_date': datetime.datetime.now().date,
}
default_available_models = {
'User': User
}
available_transformations = {
'rotate': {'label': _(u'Rotate [degrees]'), 'arguments': [{'name': 'degrees'}]}
}
@@ -42,8 +32,6 @@ register_settings(
module=u'documents.conf.settings',
settings=[
# Definition
{'name': u'AVAILABLE_FUNCTIONS', 'global_name': u'DOCUMENTS_METADATA_AVAILABLE_FUNCTIONS', 'default': default_available_functions},
{'name': u'AVAILABLE_MODELS', 'global_name': u'DOCUMENTS_METADATA_AVAILABLE_MODELS', 'default': default_available_models},
{'name': u'AVAILABLE_INDEXING_FUNCTIONS', 'global_name': u'DOCUMENTS_INDEXING_AVAILABLE_FUNCTIONS', 'default': available_indexing_functions},
# Upload
{'name': u'USE_STAGING_DIRECTORY', 'global_name': u'DOCUMENTS_USE_STAGING_DIRECTORY', 'default': False},

View File

@@ -16,12 +16,11 @@ from common.literals import PAGE_SIZE_CHOICES, PAGE_ORIENTATION_CHOICES
from common.conf.settings import DEFAULT_PAPER_SIZE
from common.conf.settings import DEFAULT_PAGE_ORIENTATION
from common.utils import urlquote
from metadata.models import MetadataSet, MetadataType
from documents.staging import StagingFile
from documents.models import Document, DocumentType, \
DocumentPage, DocumentPageTransformation, MetadataSet, MetadataType
from documents.conf.settings import AVAILABLE_FUNCTIONS
from documents.conf.settings import AVAILABLE_MODELS
DocumentPage, DocumentPageTransformation
class DocumentPageTransformationForm(forms.ModelForm):
@@ -249,54 +248,6 @@ class DocumentTypeSelectForm(forms.Form):
document_type = forms.ModelChoiceField(queryset=DocumentType.objects.all(), label=(u'Document type'), required=False)
class MetadataForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MetadataForm, self).__init__(*args, **kwargs)
#Set form fields initial values
if 'initial' in kwargs:
self.metadata_type = kwargs['initial'].pop('metadata_type', None)
#self.document_type = kwargs['initial'].pop('document_type', None)
# FIXME:
#required = self.document_type.documenttypemetadatatype_set.get(metadata_type=self.metadata_type).required
required = False
required_string = u''
if required:
self.fields['value'].required = True
required_string = ' (%s)' % ugettext(u'required')
else:
#TODO: FIXME: not working correctly
self.fields['value'].required = False
self.fields['name'].initial = '%s%s' % ((self.metadata_type.title if self.metadata_type.title else self.metadata_type.name), required_string)
self.fields['id'].initial = self.metadata_type.id
if self.metadata_type.default:
try:
self.fields['value'].initial = eval(self.metadata_type.default, AVAILABLE_FUNCTIONS)
except Exception, err:
self.fields['value'].initial = err
if self.metadata_type.lookup:
try:
choices = eval(self.metadata_type.lookup, AVAILABLE_MODELS)
self.fields['value'] = forms.ChoiceField(label=self.fields['value'].label)
choices = zip(choices, choices)
if not required:
choices.insert(0, ('', '------'))
self.fields['value'].choices = choices
self.fields['value'].required = required
except Exception, err:
self.fields['value'].initial = err
self.fields['value'].widget = forms.TextInput(attrs={'readonly': 'readonly'})
id = forms.CharField(label=_(u'id'), widget=forms.HiddenInput)
name = forms.CharField(label=_(u'Name'),
required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'}))
value = forms.CharField(label=_(u'Value'), required=False)
MetadataFormSet = formset_factory(MetadataForm, extra=0)
class DocumentCreateWizard(BoundFormWizard):
def generate_metadata_initial_values(self):
initial = []

View File

@@ -0,0 +1,52 @@
from django.db import models
#from documents.models import DocumentGroup
from metadata.classes import MetadataObject
class DocumentGroupManager(models.Manager):
def get_groups_for(self, document, group_obj=None):
errors = []
metadata_groups = {}
metadata_dict = {}
for document_metadata in document.documentmetadata_set.all():
metadata_dict[document_metadata.metadata_type.name] = document_metadata.value
eval_dict = {}
eval_dict['document'] = document
eval_dict['metadata'] = MetadataObject(metadata_dict)
#if group_obj:
# groups_qs = DocumentGroup.objects.filter((Q(document_type=document.document_type) | Q(document_type=None)) & Q(enabled=True) & Q(pk=group_obj.pk))
#else:
# groups_qs = DocumentGroup.objects.filter((Q(document_type=document.document_type) | Q(document_type=None)) & Q(enabled=True))
groups_qs=[]
for group in groups_qs:
total_query = Q()
for item in group.metadatagroupitem_set.filter(enabled=True):
try:
value_query = Q(**{'value__%s' % item.operator: eval(item.expression, eval_dict)})
if item.negated:
query = (Q(metadata_type__id=item.metadata_type_id) & ~value_query)
else:
query = (Q(metadata_type__id=item.metadata_type_id) & value_query)
if item.inclusion == INCLUSION_AND:
total_query &= query
elif item.inclusion == INCLUSION_OR:
total_query |= query
except Exception, e:
errors.append(e)
value_query = Q()
query = Q()
if total_query:
document_id_list = DocumentMetadata.objects.filter(total_query).values_list('document', flat=True)
metadata_groups[group] = Document.objects.filter(Q(id__in=document_id_list)).order_by('file_filename') or []
else:
metadata_groups[group] = []
if group_obj:
return metadata_groups[group_obj], errors
return metadata_groups, errors

View File

@@ -15,18 +15,16 @@ from taggit.managers import TaggableManager
from dynamic_search.api import register
from converter.api import get_page_count
from converter import TRANFORMATION_CHOICES
from metadata.classes import MetadataObject
from documents.conf.settings import AVAILABLE_INDEXING_FUNCTIONS
from documents.conf.settings import AVAILABLE_FUNCTIONS
from documents.conf.settings import AVAILABLE_MODELS
from documents.conf.settings import CHECKSUM_FUNCTION
from documents.conf.settings import UUID_FUNCTION
from documents.conf.settings import STORAGE_BACKEND
from documents.conf.settings import AVAILABLE_TRANSFORMATIONS
from documents.conf.settings import DEFAULT_TRANSFORMATIONS
from documents.conf.settings import RECENT_COUNT
from documents.classes import MetadataObject
from documents.managers import DocumentGroupManager
def get_filename_from_uuid(instance, filename):
filename, extension = os.path.splitext(filename)
@@ -190,7 +188,7 @@ class Document(models.Model):
return u', '.join([u'%s - %s' % (metadata.metadata_type, metadata.value) for metadata in self.documentmetadata_set.select_related('metadata_type', 'document').defer('document__document_type', 'document__file', 'document__description', 'document__file_filename', 'document__uuid', 'document__date_added', 'document__date_updated', 'document__file_mimetype', 'document__file_mime_encoding')])
def get_metadata_groups(self, group_obj=None):
return MetadataGroup.objects.get_groups_for(self, group_obj)
return DocumentGroup.objects.get_groups_for(self, group_obj)
def apply_default_transformations(self):
#Only apply default transformations on new documents
@@ -207,60 +205,8 @@ class Document(models.Model):
page_transformation.save()
available_functions_string = (_(u' Available functions: %s') % u','.join([u'%s()' % name for name, function in AVAILABLE_FUNCTIONS.items()])) if AVAILABLE_FUNCTIONS else u''
available_models_string = (_(u' Available models: %s') % u','.join([name for name, model in AVAILABLE_MODELS.items()])) if AVAILABLE_MODELS else u''
class MetadataType(models.Model):
name = models.CharField(max_length=48, verbose_name=_(u'name'), help_text=_(u'Do not use python reserved words, or spaces.'))
title = models.CharField(max_length=48, verbose_name=_(u'title'), blank=True, null=True)
default = models.CharField(max_length=128, blank=True, null=True,
verbose_name=_(u'default'),
help_text=_(u'Enter a string to be evaluated.%s') % available_functions_string)
lookup = models.CharField(max_length=128, blank=True, null=True,
verbose_name=_(u'lookup'),
help_text=_(u'Enter a string to be evaluated. Example: [user.get_full_name() for user in User.objects.all()].%s') % available_models_string)
#TODO: datatype?
def __unicode__(self):
return self.title if self.title else self.name
class Meta:
verbose_name = _(u'metadata type')
verbose_name_plural = _(u'metadata types')
class MetadataSet(models.Model):
title = models.CharField(max_length=48, verbose_name=_(u'title'))
def __unicode__(self):
return self.title if self.title else self.name
class Meta:
verbose_name = _(u'metadata set')
verbose_name_plural = _(u'metadata set')
class MetadataSetItem(models.Model):
"""
Define the set of metadata that relates to a set or group of
metadata fields
"""
metadata_set = models.ForeignKey(MetadataSet, verbose_name=_(u'metadata set'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'metadata type'))
#required = models.BooleanField(default=True, verbose_name=_(u'required'))
def __unicode__(self):
return unicode(self.metadata_type)
class Meta:
verbose_name = _(u'metadata set item')
verbose_name_plural = _(u'metadata set items')
available_indexing_functions_string = (_(u' Available functions: %s') % u','.join([u'%s()' % name for name, function in AVAILABLE_INDEXING_FUNCTIONS.items()])) if AVAILABLE_INDEXING_FUNCTIONS else u''
class MetadataIndex(models.Model):
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
expression = models.CharField(max_length=128,
@@ -276,23 +222,6 @@ class MetadataIndex(models.Model):
verbose_name_plural = _(u'metadata indexes')
class DocumentMetadata(models.Model):
"""
Link a document to a specific instance of a metadata type with it's
current value
"""
document = models.ForeignKey(Document, verbose_name=_(u'document'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'metadata type'))
value = models.TextField(blank=True, null=True, verbose_name=_(u'metadata value'), db_index=True)
def __unicode__(self):
return unicode(self.metadata_type)
class Meta:
verbose_name = _(u'document metadata')
verbose_name_plural = _(u'document metadata')
class DocumentTypeFilename(models.Model):
"""
List of filenames available to a specific document type for the
@@ -347,61 +276,13 @@ class DocumentPage(models.Model):
return ' '.join(transformation_list), warnings
class MetadataGroupManager(models.Manager):
def get_groups_for(self, document, group_obj=None):
errors = []
metadata_groups = {}
metadata_dict = {}
for document_metadata in document.documentmetadata_set.all():
metadata_dict[document_metadata.metadata_type.name] = document_metadata.value
eval_dict = {}
eval_dict['document'] = document
eval_dict['metadata'] = MetadataObject(metadata_dict)
if group_obj:
groups_qs = MetadataGroup.objects.filter((Q(document_type=document.document_type) | Q(document_type=None)) & Q(enabled=True) & Q(pk=group_obj.pk))
else:
groups_qs = MetadataGroup.objects.filter((Q(document_type=document.document_type) | Q(document_type=None)) & Q(enabled=True))
for group in groups_qs:
total_query = Q()
for item in group.metadatagroupitem_set.filter(enabled=True):
try:
value_query = Q(**{'value__%s' % item.operator: eval(item.expression, eval_dict)})
if item.negated:
query = (Q(metadata_type__id=item.metadata_type_id) & ~value_query)
else:
query = (Q(metadata_type__id=item.metadata_type_id) & value_query)
if item.inclusion == INCLUSION_AND:
total_query &= query
elif item.inclusion == INCLUSION_OR:
total_query |= query
except Exception, e:
errors.append(e)
value_query = Q()
query = Q()
if total_query:
document_id_list = DocumentMetadata.objects.filter(total_query).values_list('document', flat=True)
metadata_groups[group] = Document.objects.filter(Q(id__in=document_id_list)).order_by('file_filename') or []
else:
metadata_groups[group] = []
if group_obj:
return metadata_groups[group_obj], errors
return metadata_groups, errors
class DocumentGroup(models.Model):
document_type = models.ManyToManyField(DocumentType, null=True, blank=True,
verbose_name=_(u'document type'), help_text=_(u'If left blank, all document types will be matched.'))
#name = models.CharField(max_length=32, verbose_name=_(u'name'))
label = models.CharField(max_length=32, verbose_name=_(u'label'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
objects = MetadataGroupManager()
objects = DocumentGroupManager()
def __unicode__(self):
return self.label if self.label else self.name
@@ -443,10 +324,10 @@ OPERATOR_CHOICES = (
class DocumentGroupItem(models.Model):
metadata_group = models.ForeignKey(DocumentGroup, verbose_name=_(u'metadata group'))
inclusion = models.CharField(default=INCLUSION_AND, max_length=16, choices=INCLUSION_CHOICES, help_text=_(u'The inclusion is ignored for the first item.'))
foreign_metadata_type = models.ForeignKey(MetadataType, related_name='metadata_type_foreign', verbose_name=_(u'foreign metadata'), help_text=_(u'This represents the metadata of all other documents.'))
#foreign_metadata_type = models.ForeignKey(MetadataType, related_name='metadata_type_foreign', verbose_name=_(u'foreign metadata'), help_text=_(u'This represents the metadata of all other documents.'))
operator = models.CharField(max_length=16, choices=OPERATOR_CHOICES)
local_metadata_type = models.ForeignKey(MetadataType, related_name='metadata_type_local', verbose_name=_(u'local metadata'), help_text=_(u'This represents the metadata of the current document.'))
#local_metadata_type = models.ForeignKey(MetadataType, related_name='metadata_type_local', verbose_name=_(u'local metadata'), help_text=_(u'This represents the metadata of the current document.'))
expression = models.TextField(verbose_name=_(u'expression'), help_text=_(u'This expression will be evaluated against the current selected document. The document metadata is available as variables `metadata` and document properties under the variable `document`.'))
negated = models.BooleanField(default=False, verbose_name=_(u'negated'), help_text=_(u'Inverts the logic of the operator.'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
@@ -458,8 +339,7 @@ class DocumentGroupItem(models.Model):
verbose_name = _(u'group item')
verbose_name_plural = _(u'group items')
available_transformations = ([(name, data['label']) for name, data in AVAILABLE_TRANSFORMATIONS.items()]) if AVAILABLE_MODELS else []
available_transformations = ([(name, data['label']) for name, data in AVAILABLE_TRANSFORMATIONS.items()])
class DocumentPageTransformation(models.Model):

View File

@@ -21,8 +21,6 @@ urlpatterns = patterns('documents.views',
url(r'^document/(?P<document_id>\d+)/delete/$', 'document_delete', (), 'document_delete'),
url(r'^document/multiple/delete/$', 'document_multiple_delete', (), 'document_multiple_delete'),
url(r'^document/(?P<document_id>\d+)/edit/$', 'document_edit', (), 'document_edit'),
url(r'^document/(?P<document_id>\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<document_id>\d+)/print/$', 'document_print', (), 'document_print'),
url(r'^document/(?P<document_id>\d+)/hard_copy/$', 'document_hard_copy', (), 'document_hard_copy'),

View File

@@ -31,6 +31,8 @@ from converter.api import DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, \
from common.literals import PAGE_SIZE_DIMENSIONS, \
PAGE_ORIENTATION_PORTRAIT, PAGE_ORIENTATION_LANDSCAPE
from common.conf.settings import DEFAULT_PAPER_SIZE
from metadata.api import save_metadata_list, \
decode_metadata_from_url, metadata_repr_as_list
from documents.conf.settings import DELETE_STAGING_FILE_AFTER_UPLOAD
from documents.conf.settings import USE_STAGING_DIRECTORY
@@ -48,7 +50,7 @@ from documents.conf.settings import PRINT_SIZE
from documents import PERMISSION_DOCUMENT_CREATE, \
PERMISSION_DOCUMENT_PROPERTIES_EDIT, \
PERMISSION_DOCUMENT_METADATA_EDIT, PERMISSION_DOCUMENT_VIEW, \
PERMISSION_DOCUMENT_VIEW, \
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD, \
PERMISSION_DOCUMENT_TRANSFORM, \
PERMISSION_DOCUMENT_EDIT
@@ -56,14 +58,12 @@ from documents import PERMISSION_DOCUMENT_CREATE, \
from documents.forms import DocumentTypeSelectForm, DocumentCreateWizard, \
DocumentForm, DocumentForm_edit, DocumentForm_view, \
StagingDocumentForm, DocumentPreviewForm, \
MetadataFormSet, DocumentPageForm, DocumentPageTransformationForm, \
DocumentPageForm, DocumentPageTransformationForm, \
DocumentContentForm, DocumentPageForm_edit, MetaDataGroupForm, \
DocumentPageForm_text, PrintForm, MetadataSelectionForm
from documents.metadata import save_metadata_list, \
decode_metadata_from_url, metadata_repr_as_list
from documents.models import Document, DocumentType, DocumentPage, \
DocumentPageTransformation, RecentDocument, MetadataGroup
DocumentPageTransformation, RecentDocument, DocumentGroup
from documents.staging import StagingFile
from documents import metadata_group_link
from documents.literals import PICTURE_ERROR_SMALL, PICTURE_ERROR_MEDIUM, \
@@ -455,89 +455,6 @@ def document_edit(request, document_id):
}, context_instance=RequestContext(request))
def document_edit_metadata(request, document_id=None, document_id_list=None):
check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_METADATA_EDIT])
if document_id:
documents = [get_object_or_404(Document, pk=document_id)]
elif document_id_list:
documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')]
if len(set([document.document_type for document in documents])) > 1:
messages.error(request, _(u'All documents must be from the same type.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
else:
messages.error(request, _(u'Must provide at least one document.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
metadata = {}
for document in documents:
RecentDocument.objects.add_document_for_user(request.user, document)
for item in document.documentmetadata_set.all():
value = item.value
if item.metadata_type in metadata:
if value not in metadata[item.metadata_type]:
metadata[item.metadata_type].append(value)
else:
metadata[item.metadata_type] = [value]
initial = []
for key, value in metadata.items():
initial.append({
'metadata_type': key,
'value': u', '.join(value)
})
formset = MetadataFormSet(initial=initial)
if request.method == 'POST':
formset = MetadataFormSet(request.POST)
if formset.is_valid():
for document in documents:
try:
document_delete_fs_links(document)
except Exception, e:
messages.error(request, _(u'Error deleting filesystem links for document: %(document)s; %(error)s') % {
'document': document, 'error': e})
save_metadata_list(formset.cleaned_data, document)
messages.success(request, _(u'Metadata for document %s edited successfully.') % document)
try:
warnings = document_create_fs_links(document)
if request.user.is_staff or request.user.is_superuser:
for warning in warnings:
messages.warning(request, warning)
messages.success(request, _(u'Filesystem links updated successfully for document: %s.') % document)
except Exception, e:
messages.error(request, _('Error creating filesystem links for document: %(document)s; %(error)s') % {
'document': document, 'error': e})
if len(documents) == 1:
return HttpResponseRedirect(document.get_absolute_url())
elif len(documents) > 1:
return HttpResponseRedirect(reverse('document_list'))
context = {
'form_display_mode_table': True,
'form': formset,
}
if len(documents) == 1:
context['object'] = documents[0]
context['title'] = _(u'Edit metadata for document: %s') % ', '.join([unicode(d) for d in documents])
elif len(documents) > 1:
context['title'] = _(u'Edit metadata for documents: %s') % ', '.join([unicode(d) for d in documents])
return render_to_response('generic_form.html', context,
context_instance=RequestContext(request))
def document_multiple_edit_metadata(request):
return document_edit_metadata(request, document_id_list=request.GET.get('id_list', []))
def calculate_converter_arguments(document, *args, **kwargs):
size = kwargs.pop('size', PREVIEW_SIZE)
quality = kwargs.pop('quality', QUALITY_DEFAULT)

28
apps/metadata/__init__.py Normal file
View File

@@ -0,0 +1,28 @@
from django.utils.translation import ugettext_lazy as _
from navigation.api import register_links, register_menu, \
register_model_list_columns, register_multi_item_links
from main.api import register_diagnostic, register_tool
from permissions.api import register_permissions
from documents.models import Document
PERMISSION_METADATA_DOCUMENT_EDIT = u'metadata_document_edit'
PERMISSION_METADATA_DOCUMENT_ADD = u'metadata_document_add'
PERMISSION_METADATA_DOCUMENT_REMOVE = u'metadata_document_remove'
register_permissions('metadata', [
{'name': PERMISSION_METADATA_DOCUMENT_EDIT, 'label': _(u'Edit a document\'s metadata')},
{'name': PERMISSION_METADATA_DOCUMENT_ADD, 'label': _(u'Add metadata to a document')},
{'name': PERMISSION_METADATA_DOCUMENT_REMOVE, 'label': _(u'Remove metadata from a document')},
])
metadata_edit = {'text': _(u'edit metadata'), 'view': 'metadata_edit', 'args': 'object.id', 'famfam': 'xhtml_go', 'permissions': {'namespace': 'metadata', 'permissions': [PERMISSION_METADATA_DOCUMENT_EDIT]}}
metadata_multiple_edit = {'text': _(u'edit metadata'), 'view': 'metadata_multiple_edit', 'famfam': 'xhtml_go', 'permissions': {'namespace': 'metadata', 'permissions': [PERMISSION_METADATA_DOCUMENT_EDIT]}}
metadata_add = {'text': _(u'add metadata'), 'view': 'metadata_add', 'args': 'object.id', 'famfam': 'xhtml_add', 'permissions': {'namespace': 'metadata', 'permissions': [PERMISSION_METADATA_DOCUMENT_ADD]}}
metadata_multiple_add = {'text': _(u'add metadata'), 'view': 'metadata_multiple_add', 'famfam': 'xhtml_add', 'permissions': {'namespace': 'metadata', 'permissions': [PERMISSION_METADATA_DOCUMENT_ADD]}}
metadata_remove = {'text': _(u'remove metadata'), 'view': 'metadata_remove', 'args': 'object.id', 'famfam': 'xhtml_delete', 'permissions': {'namespace': 'metadata', 'permissions': [PERMISSION_METADATA_DOCUMENT_REMOVE]}}
metadata_multiple_remove = {'text': _(u'remove metadata'), 'view': 'metadata_multiple_remove', 'famfam': 'xhtml_delete', 'permissions': {'namespace': 'metadata', 'permissions': [PERMISSION_METADATA_DOCUMENT_REMOVE]}}
register_links(Document, [metadata_add, metadata_edit, metadata_remove])
register_multi_item_links(['metadatagroup_view', 'document_list', 'document_list_recent'], [metadata_multiple_add, metadata_multiple_edit, metadata_multiple_remove])

30
apps/metadata/admin.py Normal file
View File

@@ -0,0 +1,30 @@
from django.contrib import admin
from metadata.models import MetadataType, MetadataSet, MetadataSetItem, \
DocumentMetadata
class MetadataTypeAdmin(admin.ModelAdmin):
list_display = ('name', 'title', 'default', 'lookup')
class MetadataSetItemInline(admin.StackedInline):
model = MetadataSetItem
extra = 1
classes = ('collapse-open',)
allow_add = True
class DocumentMetadataInline(admin.StackedInline):
model = DocumentMetadata
extra = 0
classes = ('collapse-open',)
allow_add = False
class MetadataSetAdmin(admin.ModelAdmin):
inlines = [MetadataSetItemInline]
admin.site.register(MetadataType, MetadataTypeAdmin)
admin.site.register(MetadataSet, MetadataSetAdmin)

View File

@@ -3,10 +3,9 @@
from urllib import unquote_plus
from django.shortcuts import get_object_or_404
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _
from documents.models import DocumentMetadata, MetadataType
from metadata.models import DocumentMetadata, MetadataType
def decode_metadata_from_url(url_dict):
@@ -59,13 +58,22 @@ def save_metadata_list(metadata_list, document):
def save_metadata(metadata_dict, document):
"""save metadata_dict"""
# Use matched metadata now to create document metadata
document_metadata, created = DocumentMetadata.objects.get_or_create(
#document_metadata, created = DocumentMetadata.objects.get_or_create(
# document=document,
# metadata_type=get_object_or_404(
# MetadataType,
# pk=metadata_dict['id']
# ),
#)
document_metadata = DocumentMetadata.objects.get(
document=document,
metadata_type=get_object_or_404(
MetadataType,
pk=metadata_dict['id']
),
)
# Handle 'plus sign as space' in the url
# unquote_plus handles utf-8?!?

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,27 @@
"""Configuration options for the metadata app"""
import datetime
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from smart_settings.api import register_settings
default_available_functions = {
'current_date': datetime.datetime.now().date,
}
default_available_models = {
'User': User
}
register_settings(
namespace=u'metadata',
module=u'metadata.conf.settings',
settings=[
# Definition
{'name': u'AVAILABLE_FUNCTIONS', 'global_name': u'METADATA_AVAILABLE_FUNCTIONS', 'default': default_available_functions},
{'name': u'AVAILABLE_MODELS', 'global_name': u'METADATA_AVAILABLE_MODELS', 'default': default_available_models},
]
)

67
apps/metadata/forms.py Normal file
View File

@@ -0,0 +1,67 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.forms.formsets import formset_factory
from metadata.conf.settings import AVAILABLE_MODELS
from metadata.conf.settings import AVAILABLE_FUNCTIONS
from metadata.models import MetadataType, DocumentMetadata
class MetadataForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MetadataForm, self).__init__(*args, **kwargs)
#Set form fields initial values
if 'initial' in kwargs:
self.metadata_type = kwargs['initial'].pop('metadata_type', None)
#self.document_type = kwargs['initial'].pop('document_type', None)
# FIXME:
#required = self.document_type.documenttypemetadatatype_set.get(metadata_type=self.metadata_type).required
required = False
required_string = u''
if required:
self.fields['value'].required = True
required_string = ' (%s)' % _(u'required')
else:
#TODO: FIXME: not working correctly
self.fields['value'].required = False
self.fields['name'].initial = '%s%s' % ((self.metadata_type.title if self.metadata_type.title else self.metadata_type.name), required_string)
self.fields['id'].initial = self.metadata_type.pk
if self.metadata_type.default:
try:
self.fields['value'].initial = eval(self.metadata_type.default, AVAILABLE_FUNCTIONS)
except Exception, err:
self.fields['value'].initial = err
if self.metadata_type.lookup:
try:
choices = eval(self.metadata_type.lookup, AVAILABLE_MODELS)
self.fields['value'] = forms.ChoiceField(label=self.fields['value'].label)
choices = zip(choices, choices)
if not required:
choices.insert(0, ('', '------'))
self.fields['value'].choices = choices
self.fields['value'].required = required
except Exception, err:
self.fields['value'].initial = err
self.fields['value'].widget = forms.TextInput(attrs={'readonly': 'readonly'})
id = forms.CharField(label=_(u'id'), widget=forms.HiddenInput)
name = forms.CharField(label=_(u'Name'),
required=False, widget=forms.TextInput(attrs={'readonly': 'readonly'}))
value = forms.CharField(label=_(u'Value'), required=False)
update = forms.BooleanField(initial=True, label=_(u'Update'), required=False)
MetadataFormSet = formset_factory(MetadataForm, extra=0)
class AddMetadataForm(forms.Form):
metadata_type = forms.ModelChoiceField(queryset=MetadataType.objects.all(), label=_(u'Metadata type'))
class MetadataRemoveForm(MetadataForm):
update = forms.BooleanField(initial=False, label=_(u'Remove'), required=False)
MetadataRemoveFormSet = formset_factory(MetadataRemoveForm, extra=0)

74
apps/metadata/models.py Normal file
View File

@@ -0,0 +1,74 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from documents.models import Document
from metadata.conf.settings import AVAILABLE_MODELS
from metadata.conf.settings import AVAILABLE_FUNCTIONS
available_models_string = (_(u' Available models: %s') % u','.join([name for name, model in AVAILABLE_MODELS.items()])) if AVAILABLE_MODELS else u''
available_functions_string = (_(u' Available functions: %s') % u','.join([u'%s()' % name for name, function in AVAILABLE_FUNCTIONS.items()])) if AVAILABLE_FUNCTIONS else u''
class MetadataType(models.Model):
name = models.CharField(unique=True, max_length=48, verbose_name=_(u'name'), help_text=_(u'Do not use python reserved words, or spaces.'))
title = models.CharField(max_length=48, verbose_name=_(u'title'), blank=True, null=True)
default = models.CharField(max_length=128, blank=True, null=True,
verbose_name=_(u'default'),
help_text=_(u'Enter a string to be evaluated.%s') % available_functions_string)
lookup = models.CharField(max_length=128, blank=True, null=True,
verbose_name=_(u'lookup'),
help_text=_(u'Enter a string to be evaluated. Example: [user.get_full_name() for user in User.objects.all()].%s') % available_models_string)
#TODO: datatype?
def __unicode__(self):
return self.title if self.title else self.name
class Meta:
verbose_name = _(u'metadata type')
verbose_name_plural = _(u'metadata types')
class MetadataSet(models.Model):
title = models.CharField(max_length=48, verbose_name=_(u'title'))
def __unicode__(self):
return self.title if self.title else self.name
class Meta:
verbose_name = _(u'metadata set')
verbose_name_plural = _(u'metadata set')
class MetadataSetItem(models.Model):
"""
Define the set of metadata that relates to a set or group of
metadata fields
"""
metadata_set = models.ForeignKey(MetadataSet, verbose_name=_(u'metadata set'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'metadata type'))
#required = models.BooleanField(default=True, verbose_name=_(u'required'))
def __unicode__(self):
return unicode(self.metadata_type)
class Meta:
verbose_name = _(u'metadata set item')
verbose_name_plural = _(u'metadata set items')
class DocumentMetadata(models.Model):
"""
Link a document to a specific instance of a metadata type with it's
current value
"""
document = models.ForeignKey(Document, verbose_name=_(u'document'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'type'))
value = models.TextField(blank=True, null=True, verbose_name=_(u'value'), db_index=True)
def __unicode__(self):
return unicode(self.metadata_type)
class Meta:
verbose_name = _(u'document metadata')
verbose_name_plural = _(u'document metadata')

23
apps/metadata/tests.py Normal file
View File

@@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

10
apps/metadata/urls.py Normal file
View File

@@ -0,0 +1,10 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('metadata.views',
url(r'^(?P<document_id>\d+)/edit/$', 'metadata_edit', (), 'metadata_edit'),
url(r'^multiple/edit/$', 'metadata_multiple_edit', (), 'metadata_multiple_edit'),
url(r'^(?P<document_id>\d+)/add/$', 'metadata_add', (), 'metadata_add'),
url(r'^multiple/add/$', 'metadata_multiple_add', (), 'metadata_multiple_add'),
url(r'^(?P<document_id>\d+)/remove/$', 'metadata_remove', (), 'metadata_remove'),
url(r'^multiple/remove/$', 'metadata_multiple_remove', (), 'metadata_multiple_remove'),
)

251
apps/metadata/views.py Normal file
View File

@@ -0,0 +1,251 @@
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import get_object_or_404
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.utils.http import urlencode
from documents.models import Document, RecentDocument
from permissions.api import check_permissions
from filesystem_serving.api import document_create_fs_links, document_delete_fs_links
from metadata import PERMISSION_METADATA_DOCUMENT_EDIT, \
PERMISSION_METADATA_DOCUMENT_ADD, PERMISSION_METADATA_DOCUMENT_REMOVE
from metadata.forms import MetadataFormSet, AddMetadataForm, MetadataRemoveFormSet
from metadata.api import save_metadata_list
from metadata.models import DocumentMetadata, MetadataType
def metadata_edit(request, document_id=None, document_id_list=None):
check_permissions(request.user, 'metadata', [PERMISSION_METADATA_DOCUMENT_EDIT])
if document_id:
documents = [get_object_or_404(Document, pk=document_id)]
if documents[0].documentmetadata_set.count() == 0:
messages.warning(request, _(u'The selected document doesn\'t have any metadata.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
elif document_id_list:
documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')]
else:
messages.error(request, _(u'Must provide at least one document.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
metadata = {}
for document in documents:
RecentDocument.objects.add_document_for_user(request.user, document)
for item in document.documentmetadata_set.all():
value = item.value
if item.metadata_type in metadata:
if value not in metadata[item.metadata_type]:
metadata[item.metadata_type].append(value)
else:
metadata[item.metadata_type] = [value] if value else u''
initial = []
for key, value in metadata.items():
initial.append({
'metadata_type': key,
'value': u', '.join(value)
})
formset = MetadataFormSet(initial=initial)
if request.method == 'POST':
formset = MetadataFormSet(request.POST)
if formset.is_valid():
for document in documents:
try:
document_delete_fs_links(document)
except Exception, e:
messages.error(request, _(u'Error deleting filesystem links for document: %(document)s; %(error)s') % {
'document': document, 'error': e})
for form in formset.forms:
if form.cleaned_data['update']:
try:
save_metadata_list([form.cleaned_data], document)
messages.success(request, _(u'Metadata for document %s edited successfully.') % document)
except Exception, e:
messages.error(request, _(u'Error editing metadata for document %(document)s; %(error)s.') % {
'document': document, 'error': e})
try:
warnings = document_create_fs_links(document)
if request.user.is_staff or request.user.is_superuser:
for warning in warnings:
messages.warning(request, warning)
messages.success(request, _(u'Filesystem links updated successfully for document: %s.') % document)
except Exception, e:
messages.error(request, _('Error creating filesystem links for document: %(document)s; %(error)s') % {
'document': document, 'error': e})
if len(documents) == 1:
return HttpResponseRedirect(document.get_absolute_url())
elif len(documents) > 1:
return HttpResponseRedirect(reverse('document_list_recent'))
context = {
'form_display_mode_table': True,
'form': formset,
}
if len(documents) == 1:
context['object'] = documents[0]
context['title'] = _(u'Edit metadata for document: %s') % ', '.join([unicode(d) for d in documents])
elif len(documents) > 1:
context['title'] = _(u'Edit metadata for documents: %s') % ', '.join([unicode(d) for d in documents])
return render_to_response('generic_form.html', context,
context_instance=RequestContext(request))
def metadata_multiple_edit(request):
return metadata_edit(request, document_id_list=request.GET.get('id_list', []))
def metadata_add(request, document_id=None, document_id_list=None):
check_permissions(request.user, 'metadata', [PERMISSION_METADATA_DOCUMENT_ADD])
if document_id:
documents = [get_object_or_404(Document, pk=document_id)]
elif document_id_list:
documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')]
else:
messages.error(request, _(u'Must provide at least one document.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
metadata = {}
for document in documents:
RecentDocument.objects.add_document_for_user(request.user, document)
if request.method == 'POST':
form = AddMetadataForm(request.POST)
if form.is_valid():
metadata_type = form.cleaned_data['metadata_type']
for document in documents:
document_metadata, created = DocumentMetadata.objects.get_or_create(document=document, metadata_type=metadata_type, defaults={'value': u''})
if created:
messages.success(request, _(u'Metadata type: %(metadata_type)s successfully added to document %(document)s.') % {
'metadata_type': metadata_type, 'document': document})
else:
messages.warning(request, _(u'Metadata type: %(metadata_type)s already present in document %(document)s.') % {
'metadata_type': metadata_type, 'document': document})
if len(documents) == 1:
return HttpResponseRedirect(reverse(metadata_edit, args=[document.pk]))
elif len(documents) > 1:
return HttpResponseRedirect(u'%s?%s' % (reverse('metadata_multiple_edit'), urlencode({'id_list': document_id_list})))
else:
form = AddMetadataForm()
context = {
#'form_display_mode_table': True,
'form': form,
}
if len(documents) == 1:
context['object'] = documents[0]
context['title'] = _(u'Add metadata type to document: %s') % ', '.join([unicode(d) for d in documents])
elif len(documents) > 1:
context['title'] = _(u'Add metadata type to documents: %s') % ', '.join([unicode(d) for d in documents])
return render_to_response('generic_form.html', context,
context_instance=RequestContext(request))
def metadata_multiple_add(request):
return metadata_add(request, document_id_list=request.GET.get('id_list', []))
def metadata_remove(request, document_id):
check_permissions(request.user, 'metadata', [PERMISSION_METADATA_DOCUMENT_REMOVE])
if document_id:
documents = [get_object_or_404(Document, pk=document_id)]
if documents[0].documentmetadata_set.count() == 0:
messages.warning(request, _(u'The selected document doesn\'t have any metadata.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
elif document_id_list:
documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')]
else:
messages.error(request, _(u'Must provide at least one document.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
metadata = {}
for document in documents:
RecentDocument.objects.add_document_for_user(request.user, document)
for item in document.documentmetadata_set.all():
value = item.value
if item.metadata_type in metadata:
if value not in metadata[item.metadata_type]:
metadata[item.metadata_type].append(value)
else:
metadata[item.metadata_type] = [value] if value else u''
initial = []
for key, value in metadata.items():
initial.append({
'metadata_type': key,
'value': u', '.join(value)
})
formset = MetadataRemoveFormSet(initial=initial)
if request.method == 'POST':
formset = MetadataRemoveFormSet(request.POST)
if formset.is_valid():
for document in documents:
try:
document_delete_fs_links(document)
except Exception, e:
messages.error(request, _(u'Error deleting filesystem links for document: %(document)s; %(error)s') % {
'document': document, 'error': e})
for form in formset.forms:
if form.cleaned_data['update']:
metadata_type = get_object_or_404(MetadataType, pk=form.cleaned_data['id'])
try:
document_metadata = DocumentMetadata.objects.get(document=document, metadata_type=metadata_type)
document_metadata.delete()
messages.success(request, _(u'Successfully remove metadata type: %(metadata_type)s from document: %(document)s.') % {
'metadata_type': metadata_type, 'document': document})
except:
messages.error(request, _(u'Error removing metadata type: %(metadata_type)s from document: %(document)s.') % {
'metadata_type': metadata_type, 'document': document})
try:
warnings = document_create_fs_links(document)
if request.user.is_staff or request.user.is_superuser:
for warning in warnings:
messages.warning(request, warning)
messages.success(request, _(u'Filesystem links updated successfully for document: %s.') % document)
except Exception, e:
messages.error(request, _('Error creating filesystem links for document: %(document)s; %(error)s') % {
'document': document, 'error': e})
if len(documents) == 1:
return HttpResponseRedirect(document.get_absolute_url())
elif len(documents) > 1:
return HttpResponseRedirect(reverse('document_list_recent'))
context = {
'form_display_mode_table': True,
'form': formset,
}
if len(documents) == 1:
context['object'] = documents[0]
context['title'] = _(u'Remove metadata types to document: %s') % ', '.join([unicode(d) for d in documents])
elif len(documents) > 1:
context['title'] = _(u'Remove metadata types to documents: %s') % ', '.join([unicode(d) for d in documents])
return render_to_response('generic_form.html', context,
context_instance=RequestContext(request))
def metadata_multiple_remove(request):
return metadata_remove(request, document_id_list=request.GET.get('id_list', []))

View File

@@ -125,7 +125,7 @@ INSTALLED_APPS = (
'web_theme',
'main',
'common',
'documents',
'metadata',
'pagination',
'dynamic_search',
'filetransfers',
@@ -145,6 +145,7 @@ INSTALLED_APPS = (
'tags',
'document_comments',
'user_management',
'documents',
)
TEMPLATE_CONTEXT_PROCESSORS = (
@@ -160,7 +161,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
#--------- Pagination ------------------
#PAGINATION_DEFAULT_PAGINATION = 10
#--------- Web theme app ---------------
#WEB_THEME = 'default'
#WEB_THEME_THEME = 'default'
#-------------- Main -----------------
#MAIN_SIDE_BAR_SEARCH = False
#------------ Common --------------
@@ -176,10 +177,11 @@ TEMPLATE_CONTEXT_PROCESSORS = (
#STORAGE_GRIDFS_DATABASE_NAME = u'document_storage'
# Filebased
#STORAGE_FILESTORAGE_LOCATION = u'document_storage'
#---------- Metadata -----------------
# METADATA_AVAILABLE_FUNCTIONS = {}
# METADATA_AVAILABLE_MODELS = {}
#---------- Documents ------------------
# Definition
#DOCUMENTS_METADATA_AVAILABLE_FUNCTIONS = {}
#DOCUMENTS_METADATA_AVAILABLE_MODELS = {}
#DOCUMENTS_INDEXING_AVAILABLE_FUNCTIONS = {}
# Upload

View File

@@ -21,6 +21,7 @@ urlpatterns = patterns('',
(r'^comments/', include('document_comments.urls')),
(r'^user_management/', include('user_management.urls')),
(r'^settings/', include('smart_settings.urls')),
(r'^metadata/', include('metadata.urls')),
)