Commited new metadata/document_type paradirm

This commit is contained in:
Roberto Rosario
2011-05-09 02:25:09 -04:00
parent 1b511574d9
commit e03a90883a
8 changed files with 128 additions and 86 deletions

View File

@@ -15,8 +15,8 @@ def password_change_done(request):
def multi_object_action_view(request):
"""
Proxy view called first when usuing a multi object action, which
then redirects to the appropiate specialized view
Proxy view called first when usuing a multi object action, which
then redirects to the appropiate specialized view
"""
action = request.GET.get('action', None)

View File

@@ -1,8 +1,8 @@
from django.contrib import admin
from documents.models import MetadataType, DocumentType, Document, \
DocumentTypeMetadataType, DocumentMetadata, DocumentTypeFilename, \
MetadataIndex, DocumentPage, MetadataGroup, \
MetadataSet, MetadataSetItem, DocumentMetadata, \
DocumentTypeFilename, MetadataIndex, DocumentPage, MetadataGroup, \
MetadataGroupItem, DocumentPageTransformation, RecentDocument
from filesystem_serving.admin import DocumentMetadataIndexInline
@@ -19,8 +19,8 @@ class MetadataIndexInline(admin.StackedInline):
allow_add = True
class DocumentTypeMetadataTypeInline(admin.StackedInline):
model = DocumentTypeMetadataType
class MetadataSetItemInline(admin.StackedInline):
model = MetadataSetItem
extra = 1
classes = ('collapse-open',)
allow_add = True
@@ -35,8 +35,7 @@ class DocumentTypeFilenameInline(admin.StackedInline):
class DocumentTypeAdmin(admin.ModelAdmin):
inlines = [
DocumentTypeFilenameInline, DocumentTypeMetadataTypeInline,
MetadataIndexInline
DocumentTypeFilenameInline, MetadataIndexInline
]
@@ -86,6 +85,11 @@ class RecentDocumentAdmin(admin.ModelAdmin):
date_hierarchy = 'datetime_accessed'
class MetadataSetAdmin(admin.ModelAdmin):
inlines = [MetadataSetItemInline]
#filter_horizontal = ['document_type']
admin.site.register(MetadataType, MetadataTypeAdmin)
admin.site.register(DocumentType, DocumentTypeAdmin)
admin.site.register(Document, DocumentAdmin)
@@ -93,3 +97,4 @@ admin.site.register(MetadataGroup, MetadataGroupAdmin)
admin.site.register(DocumentPageTransformation,
DocumentPageTransformationAdmin)
admin.site.register(RecentDocument, RecentDocumentAdmin)
admin.site.register(MetadataSet, MetadataSetAdmin)

View File

@@ -15,10 +15,11 @@ from common.forms import DetailForm
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 documents.staging import StagingFile
from documents.models import Document, DocumentType, DocumentTypeMetadataType, \
DocumentPage, DocumentPageTransformation
from documents.models import Document, DocumentType, \
DocumentPage, DocumentPageTransformation, MetadataSet, MetadataType
from documents.conf.settings import AVAILABLE_FUNCTIONS
from documents.conf.settings import AVAILABLE_MODELS
@@ -154,7 +155,8 @@ class DocumentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DocumentForm, self).__init__(*args, **kwargs)
if 'initial' in kwargs:
if 'document_type' in kwargs['initial']:
document_type = kwargs['initial'].get('document_type', None)
if document_type:
if 'document_type' in self.fields:
#To allow merging with DocumentForm_edit
self.fields['document_type'].widget = forms.HiddenInput()
@@ -167,7 +169,7 @@ class DocumentForm(forms.ModelForm):
class Meta:
model = Document
exclude = ('description', 'tags')
exclude = ('description', 'tags', 'document_type')
new_filename = forms.CharField(
label=_('New document filename'), required=False
@@ -228,7 +230,8 @@ class StagingDocumentForm(forms.Form):
pass
if 'initial' in kwargs:
if 'document_type' in kwargs['initial']:
document_type = kwargs['initial'].get('document_type', None)
if document_type:
filenames_qs = kwargs['initial']['document_type'].documenttypefilename_set.filter(enabled=True)
if filenames_qs.count() > 0:
self.fields['document_type_available_filenames'] = forms.ModelChoiceField(
@@ -243,7 +246,7 @@ class StagingDocumentForm(forms.Form):
class DocumentTypeSelectForm(forms.Form):
document_type = forms.ModelChoiceField(queryset=DocumentType.objects.all())
document_type = forms.ModelChoiceField(queryset=DocumentType.objects.all(), label=(u'Document type'), required=False)
class MetadataForm(forms.Form):
@@ -253,9 +256,11 @@ class MetadataForm(forms.Form):
#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)
#self.document_type = kwargs['initial'].pop('document_type', None)
required = self.document_type.documenttypemetadatatype_set.get(metadata_type=self.metadata_type).required
# 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
@@ -295,19 +300,28 @@ MetadataFormSet = formset_factory(MetadataForm, extra=0)
class DocumentCreateWizard(BoundFormWizard):
def generate_metadata_initial_values(self):
initial = []
for item in DocumentTypeMetadataType.objects.filter(document_type=self.document_type):
for metadata_type in self.metadata_types:
initial.append({
'metadata_type': item.metadata_type,
'document_type': self.document_type,
'metadata_type': metadata_type,
})
for metadata_set in self.metadata_sets:
for metadata_set_item in metadata_set.metadatasetitem_set.all():
data = {
'metadata_type': metadata_set_item.metadata_type,
}
if data not in initial:
initial.append(data)
return initial
def __init__(self, *args, **kwargs):
self.urldata = []
self.query_dict = {}
self.multiple = kwargs.pop('multiple', True)
self.step_titles = kwargs.pop('step_titles', [
_(u'step 1 of 2: Document type'),
_(u'step 2 of 2: Document metadata'),
_(u'step 1 of 3: Document type'),
_(u'step 2 of 3: Metadata selection'),
_(u'step 3 of 3: Document metadata'),
])
self.document_type = kwargs.pop('document_type', None)
@@ -328,25 +342,31 @@ class DocumentCreateWizard(BoundFormWizard):
def process_step(self, request, form, step):
if isinstance(form, DocumentTypeSelectForm):
self.document_type = form.cleaned_data['document_type']
self.initial = {1: self.generate_metadata_initial_values()}
if isinstance(form, MetadataSelectionForm):
self.metadata_sets = form.cleaned_data['metadata_sets']
self.metadata_types = form.cleaned_data['metadata_types']
self.initial = {2: self.generate_metadata_initial_values()}
if isinstance(form, MetadataFormSet):
for identifier, metadata in enumerate(form.cleaned_data):
if metadata['value']:
self.urldata.append(('metadata%s_id' % identifier, metadata['id']))
self.urldata.append(('metadata%s_value' % identifier, metadata['value']))
self.query_dict['metadata%s_id' % identifier] = metadata['id']
self.query_dict['metadata%s_value' % identifier] = metadata['value']
def get_template(self, step):
return 'generic_wizard.html'
def done(self, request, form_list):
if self.multiple:
view = 'upload_multiple_documents_with_type'
view = 'upload_document_multiple'
else:
view = 'upload_document_with_type'
url = reverse(view, args=[self.document_type.id])
return HttpResponseRedirect('%s?%s' % (url, urlencode(self.urldata)))
view = 'upload_document'
if self.document_type:
self.query_dict['document_type_id'] = self.document_type.pk
url = urlquote(reverse(view), self.query_dict)
return HttpResponseRedirect(url)
class MetaDataImageWidget(forms.widgets.Widget):
@@ -434,3 +454,8 @@ class PrintForm(forms.Form):
custom_page_height = forms.CharField(label=_(u'Custom page height'), required=False)
page_orientation = forms.ChoiceField(choices=PAGE_ORIENTATION_CHOICES, initial=DEFAULT_PAGE_ORIENTATION, label=_(u'Page orientation'), required=True)
page_range = forms.CharField(label=_(u'Page range'), required=False)
class MetadataSelectionForm(forms.Form):
metadata_sets = forms.ModelMultipleChoiceField(queryset=MetadataSet.objects.all(), label=_(u'Metadata sets'), required=False)
metadata_types = forms.ModelMultipleChoiceField(queryset=MetadataType.objects.all(), label=_(u'Metadata'), required=False)

View File

@@ -38,20 +38,22 @@ def save_metadata_list(metadata_list, document):
'''Takes a list of metadata values and associates a document to it
'''
for item in metadata_list:
if item['value']:
save_metadata(item, document)
else:
#If there is no metadata value, delete the metadata entry
#completely from the document
try:
metadata_type = MetadataType.objects.get(id=item['id'])
document_metadata = DocumentMetadata.objects.get(
document=document,
metadata_type=metadata_type
)
document_metadata.delete()
except ObjectDoesNotExist:
pass
save_metadata(item, document)
#if item['value']:
# save_metadata(item, document)
#else:
# #If there is no metadata value, delete the metadata entry
# #completely from the document
# try:
# metadata_type = MetadataType.objects.get(id=item['id'])
# document_metadata = DocumentMetadata.objects.get(
# document=document,
# metadata_type=metadata_type
# )
# document_metadata.delete()
# except ObjectDoesNotExist:
# pass
def save_metadata(metadata_dict, document):

View File

@@ -52,7 +52,7 @@ class Document(models.Model):
"""
Defines a single document with it's fields and properties
"""
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'), null=True, blank=True)
file = models.FileField(upload_to=get_filename_from_uuid, storage=STORAGE_BACKEND(), verbose_name=_(u'file'))
uuid = models.CharField(max_length=48, default=UUID_FUNCTION(), blank=True, editable=False)
file_mimetype = models.CharField(max_length=64, default='', editable=False)
@@ -211,7 +211,7 @@ available_models_string = (_(u' Available models: %s') % u','.join([name for nam
class MetadataType(models.Model):
name = models.CharField(max_length=48, verbose_name=_(u'name'), help_text=_(u'Do not use python reserved words.'))
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'),
@@ -229,21 +229,32 @@ class MetadataType(models.Model):
verbose_name_plural = _(u'metadata types')
class DocumentTypeMetadataType(models.Model):
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 single document type
Define the set of metadata that relates to a set or group of
metadata fields
"""
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
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'))
#TODO: override default for this document type
#required = models.BooleanField(default=True, verbose_name=_(u'required'))
def __unicode__(self):
return unicode(self.metadata_type)
class Meta:
verbose_name = _(u'document type metadata type connector')
verbose_name_plural = _(u'document type metadata type connectors')
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''

View File

@@ -14,8 +14,8 @@ urlpatterns = patterns('documents.views',
url(r'^document/list/recent/$', 'document_list_recent', (), 'document_list_recent'),
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<document_type_id>\d+)/upload/single/$', 'upload_document_with_type', {'multiple': False}, 'upload_document_with_type'),
url(r'^document/type/(?P<document_type_id>\d+)/upload/multiple/$', 'upload_document_with_type', {'multiple': True}, 'upload_multiple_documents_with_type'),
url(r'^document/type/upload/single/$', 'upload_document_with_type', {'multiple': False}, 'upload_document'),
url(r'^document/type/upload/multiple/$', 'upload_document_with_type', {'multiple': True}, 'upload_document_multiple'),
url(r'^document/(?P<document_id>\d+)/$', 'document_view', (), 'document_view'),
url(r'^document/(?P<document_id>\d+)/simple/$', 'document_view_simple', (), 'document_view_simple'),
url(r'^document/(?P<document_id>\d+)/delete/$', 'document_delete', (), 'document_delete'),

View File

@@ -1,7 +1,6 @@
import os
import zipfile
import urlparse
import urllib
from django.utils.translation import ugettext_lazy as _
from django.http import HttpResponseRedirect
@@ -56,10 +55,10 @@ from documents import PERMISSION_DOCUMENT_CREATE, \
from documents.forms import DocumentTypeSelectForm, DocumentCreateWizard, \
DocumentForm, DocumentForm_edit, DocumentForm_view, \
StagingDocumentForm, DocumentTypeMetadataType, DocumentPreviewForm, \
StagingDocumentForm, DocumentPreviewForm, \
MetadataFormSet, DocumentPageForm, DocumentPageTransformationForm, \
DocumentContentForm, DocumentPageForm_edit, MetaDataGroupForm, \
DocumentPageForm_text, PrintForm
DocumentPageForm_text, PrintForm, MetadataSelectionForm
from documents.metadata import save_metadata_list, \
decode_metadata_from_url, metadata_repr_as_list
@@ -85,15 +84,7 @@ def document_list(request, object_list=None, title=None):
def document_create(request, multiple=True):
check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_CREATE])
if DocumentType.objects.all().count() == 1:
wizard = DocumentCreateWizard(
document_type=DocumentType.objects.all()[0],
form_list=[MetadataFormSet], multiple=multiple,
step_titles=[
_(u'document metadata'),
])
else:
wizard = DocumentCreateWizard(form_list=[DocumentTypeSelectForm, MetadataFormSet], multiple=multiple)
wizard = DocumentCreateWizard(form_list=[DocumentTypeSelectForm, MetadataSelectionForm, MetadataFormSet], multiple=multiple)
return wizard(request)
@@ -102,19 +93,21 @@ def document_create_sibling(request, document_id, multiple=True):
check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_CREATE])
document = get_object_or_404(Document, pk=document_id)
urldata = []
query_dict = {}
for pk, metadata in enumerate(document.documentmetadata_set.all()):
if hasattr(metadata, 'value'):
urldata.append(('metadata%s_id' % pk, metadata.metadata_type_id))
urldata.append(('metadata%s_value' % pk, metadata.value))
query_dict['metadata%s_id' % pk] = metadata.metadata_type_id
query_dict['metadata%s_value' % pk] = metadata.value
if multiple:
view = 'upload_multiple_documents_with_type'
view = 'upload_document_multiple'
else:
view = 'upload_document_with_type'
view = 'upload_document'
url = reverse(view, args=[document.document_type_id])
return HttpResponseRedirect('%s?%s' % (url, urlencode(urldata)))
if document.document_type_id:
query_dict['document_type_id'] = document.document_type_id
url = reverse(view)
return HttpResponseRedirect('%s?%s' % (url, urlencode(query_dict)))
def _handle_save_document(request, document, form=None):
@@ -157,10 +150,15 @@ def _handle_zip_file(request, uploaded_file, document_type):
return False
def upload_document_with_type(request, document_type_id, multiple=True):
def upload_document_with_type(request, multiple=True):
check_permissions(request.user, 'documents', [PERMISSION_DOCUMENT_CREATE])
document_type = get_object_or_404(DocumentType, pk=document_type_id)
document_type_id = request.GET.get('document_type_id', None)
if document_type_id:
document_type = get_object_or_404(DocumentType, pk=document_type_id)
else:
document_type = None
local_form = DocumentForm(prefix='local', initial={'document_type': document_type})
if USE_STAGING_DIRECTORY:
staging_form = StagingDocumentForm(prefix='staging',
@@ -475,8 +473,9 @@ def document_edit_metadata(request, document_id=None, document_id_list=None):
for document in documents:
RecentDocument.objects.add_document_for_user(request.user, document)
for item in DocumentTypeMetadataType.objects.filter(document_type=document.document_type):
value = document.documentmetadata_set.get(metadata_type=item.metadata_type).value if document.documentmetadata_set.filter(metadata_type=item.metadata_type) else u''
for item in document.documentmetadata_set.all():
value = item.value
print item
if item.metadata_type in metadata:
if value not in metadata[item.metadata_type]:
metadata[item.metadata_type].append(value)
@@ -487,7 +486,6 @@ def document_edit_metadata(request, document_id=None, document_id_list=None):
for key, value in metadata.items():
initial.append({
'metadata_type': key,
'document_type': document.document_type,
'value': u', '.join(value)
})
@@ -496,13 +494,14 @@ def document_edit_metadata(request, document_id=None, document_id_list=None):
formset = MetadataFormSet(request.POST)
if formset.is_valid():
for document in documents:
save_metadata_list(formset.cleaned_data, document)
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:
@@ -1089,7 +1088,7 @@ def transform_page(request, document_page_id, zoom_function=None, rotation_funct
return HttpResponseRedirect(
u'?'.join([
reverse(view, args=[document_page.pk]),
urllib.urlencode({'zoom': zoom, 'rotation': rotation})
urlencode({'zoom': zoom, 'rotation': rotation})
])
)

View File

@@ -26,7 +26,7 @@ def document_create_fs_links(document):
if not document.exists():
raise Exception(_(u'Not creating metadata indexing, document not found in document storage'))
metadata_dict = {'document': document}
metadata_dict.update(dict([(metadata.metadata_type.name, SLUGIFY_FUNCTION(metadata.value)) for metadata in document.documentmetadata_set.all()]))
metadata_dict.update(dict([(metadata.metadata_type.name, SLUGIFY_FUNCTION(metadata.value)) for metadata in document.documentmetadata_set.all() if metadata.value]))
for metadata_index in document.document_type.metadataindex_set.all():
if metadata_index.enabled: