Added changes to expand the scope of the document grouping functionality

This commit is contained in:
Roberto Rosario
2011-05-09 23:57:23 -04:00
parent 94134bc83e
commit b6d2654cc7
5 changed files with 59 additions and 39 deletions

View File

@@ -2,8 +2,8 @@ from django.contrib import admin
from documents.models import MetadataType, DocumentType, Document, \ from documents.models import MetadataType, DocumentType, Document, \
MetadataSet, MetadataSetItem, DocumentMetadata, \ MetadataSet, MetadataSetItem, DocumentMetadata, \
DocumentTypeFilename, MetadataIndex, DocumentPage, MetadataGroup, \ DocumentTypeFilename, MetadataIndex, DocumentPage, DocumentGroup, \
MetadataGroupItem, DocumentPageTransformation, RecentDocument DocumentGroupItem, DocumentPageTransformation, RecentDocument
from filesystem_serving.admin import DocumentMetadataIndexInline from filesystem_serving.admin import DocumentMetadataIndexInline
@@ -65,15 +65,15 @@ class DocumentAdmin(admin.ModelAdmin):
list_display = ('uuid', 'file_filename', 'file_extension') list_display = ('uuid', 'file_filename', 'file_extension')
class MetadataGroupItemInline(admin.StackedInline): class DocumentGroupItemInline(admin.StackedInline):
model = MetadataGroupItem model = DocumentGroupItem
extra = 1 extra = 1
classes = ('collapse-open',) classes = ('collapse-open',)
allow_add = True allow_add = True
class MetadataGroupAdmin(admin.ModelAdmin): class DocumentGroupAdmin(admin.ModelAdmin):
inlines = [MetadataGroupItemInline] inlines = [DocumentGroupItemInline]
filter_horizontal = ['document_type'] filter_horizontal = ['document_type']
@@ -87,7 +87,6 @@ class RecentDocumentAdmin(admin.ModelAdmin):
class MetadataSetAdmin(admin.ModelAdmin): class MetadataSetAdmin(admin.ModelAdmin):
inlines = [MetadataSetItemInline] inlines = [MetadataSetItemInline]
#filter_horizontal = ['document_type']
admin.site.register(MetadataType, MetadataTypeAdmin) admin.site.register(MetadataType, MetadataTypeAdmin)

12
apps/documents/classes.py Normal file
View File

@@ -0,0 +1,12 @@
from django.utils.translation import ugettext_lazy as _
class MetadataObject(object):
def __init__(self, dictionary):
self.dictionary = dictionary
def __getattr__(self, name):
if name in self.dictionary:
return self.dictionary.get(name)
else:
raise AttributeError(_(u'\'metadata\' object has no attribute \'%s\'') % name)

View File

@@ -1,17 +1,16 @@
'''Metadata handling commonalities """Metadata handling commonalities"""
'''
from urllib import unquote_plus from urllib import unquote_plus
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _
from documents.models import DocumentMetadata, MetadataType from documents.models import DocumentMetadata, MetadataType
def decode_metadata_from_url(url_dict): def decode_metadata_from_url(url_dict):
'''Parses a URL query string to a list of metadata """Parse a URL query string to a list of metadata"""
'''
metadata_dict = { metadata_dict = {
'id': {}, 'id': {},
'value': {} 'value': {}
@@ -35,8 +34,9 @@ def decode_metadata_from_url(url_dict):
def save_metadata_list(metadata_list, document): def save_metadata_list(metadata_list, document):
'''Takes a list of metadata values and associates a document to it """
''' Take a list of metadata values and associate a document to it
"""
for item in metadata_list: for item in metadata_list:
save_metadata(item, document) save_metadata(item, document)
@@ -57,8 +57,7 @@ def save_metadata_list(metadata_list, document):
def save_metadata(metadata_dict, document): def save_metadata(metadata_dict, document):
'''save metadata_dict """save metadata_dict"""
'''
# Use matched metadata now to create document metadata # 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, document=document,
@@ -77,14 +76,14 @@ def save_metadata(metadata_dict, document):
def metadata_repr(metadata_list): def metadata_repr(metadata_list):
'''Return a printable representation of a metadata list """Return a printable representation of a metadata list"""
''' return u', '.join(metadata_repr_as_list(metadata_list))
return ', '.join(metadata_repr_as_list(metadata_list))
def metadata_repr_as_list(metadata_list): def metadata_repr_as_list(metadata_list):
'''Turn a list of metadata into a list of printable representations """
''' Turn a list of metadata into a list of printable representations
"""
output = [] output = []
for metadata_dict in metadata_list: for metadata_dict in metadata_list:
try: try:

View File

@@ -25,6 +25,7 @@ from documents.conf.settings import STORAGE_BACKEND
from documents.conf.settings import AVAILABLE_TRANSFORMATIONS from documents.conf.settings import AVAILABLE_TRANSFORMATIONS
from documents.conf.settings import DEFAULT_TRANSFORMATIONS from documents.conf.settings import DEFAULT_TRANSFORMATIONS
from documents.conf.settings import RECENT_COUNT from documents.conf.settings import RECENT_COUNT
from documents.classes import MetadataObject
def get_filename_from_uuid(instance, filename): def get_filename_from_uuid(instance, filename):
@@ -352,7 +353,10 @@ class MetadataGroupManager(models.Manager):
metadata_groups = {} metadata_groups = {}
metadata_dict = {} metadata_dict = {}
for document_metadata in document.documentmetadata_set.all(): for document_metadata in document.documentmetadata_set.all():
metadata_dict['metadata_%s' % document_metadata.metadata_type.name] = document_metadata.value 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: 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)) groups_qs = MetadataGroup.objects.filter((Q(document_type=document.document_type) | Q(document_type=None)) & Q(enabled=True) & Q(pk=group_obj.pk))
@@ -363,7 +367,7 @@ class MetadataGroupManager(models.Manager):
total_query = Q() total_query = Q()
for item in group.metadatagroupitem_set.filter(enabled=True): for item in group.metadatagroupitem_set.filter(enabled=True):
try: try:
value_query = Q(**{'value__%s' % item.operator: eval(item.expression, metadata_dict)}) value_query = Q(**{'value__%s' % item.operator: eval(item.expression, eval_dict)})
if item.negated: if item.negated:
query = (Q(metadata_type__id=item.metadata_type_id) & ~value_query) query = (Q(metadata_type__id=item.metadata_type_id) & ~value_query)
else: else:
@@ -390,10 +394,10 @@ class MetadataGroupManager(models.Manager):
return metadata_groups, errors return metadata_groups, errors
class MetadataGroup(models.Model): class DocumentGroup(models.Model):
document_type = models.ManyToManyField(DocumentType, null=True, blank=True, 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.')) 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')) #name = models.CharField(max_length=32, verbose_name=_(u'name'))
label = models.CharField(max_length=32, verbose_name=_(u'label')) label = models.CharField(max_length=32, verbose_name=_(u'label'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled')) enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
@@ -433,14 +437,17 @@ OPERATOR_CHOICES = (
(u'iregex', _(u'is in regular expression (case insensitive)')), (u'iregex', _(u'is in regular expression (case insensitive)')),
) )
#LOCAL_SOURCE_CHOICES = (
# (u'
class MetadataGroupItem(models.Model): class DocumentGroupItem(models.Model):
metadata_group = models.ForeignKey(MetadataGroup, verbose_name=_(u'metadata group')) 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.')) inclusion = models.CharField(default=INCLUSION_AND, max_length=16, choices=INCLUSION_CHOICES, help_text=_(u'The inclusion is ignored for the first item.'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'metadata type'), 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) operator = models.CharField(max_length=16, choices=OPERATOR_CHOICES)
expression = models.CharField(max_length=128,
verbose_name=_(u'expression'), help_text=_(u'This expression will be evaluated against the current selected document. The document metadata is available as variables of the same name but with the "metadata_" prefix added their name.')) 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.')) 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')) enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))

View File

@@ -5,6 +5,7 @@ from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from documents.conf.settings import AVAILABLE_INDEXING_FUNCTIONS from documents.conf.settings import AVAILABLE_INDEXING_FUNCTIONS
from documents.classes import MetadataObject
from filesystem_serving.conf.settings import FILESERVING_ENABLE from filesystem_serving.conf.settings import FILESERVING_ENABLE
from filesystem_serving.conf.settings import FILESERVING_PATH from filesystem_serving.conf.settings import FILESERVING_PATH
@@ -25,13 +26,15 @@ def document_create_fs_links(document):
if FILESERVING_ENABLE: if FILESERVING_ENABLE:
if not document.exists(): if not document.exists():
raise Exception(_(u'Not creating metadata indexing, document not found in document storage')) raise Exception(_(u'Not creating metadata indexing, document not found in document storage'))
metadata_dict = {'document': document} eval_dict = {}
metadata_dict.update(dict([(metadata.metadata_type.name, SLUGIFY_FUNCTION(metadata.value)) for metadata in document.documentmetadata_set.all() if metadata.value])) eval_dict['document'] = document
metadata_dict = dict([(metadata.metadata_type.name, SLUGIFY_FUNCTION(metadata.value)) for metadata in document.documentmetadata_set.all() if metadata.value])
eval_dict['metadata'] = MetadataObject(metadata_dict)
for metadata_index in document.document_type.metadataindex_set.all(): for metadata_index in document.document_type.metadataindex_set.all():
if metadata_index.enabled: if metadata_index.enabled:
try: try:
fabricated_directory = eval(metadata_index.expression, metadata_dict, AVAILABLE_INDEXING_FUNCTIONS) fabricated_directory = eval(metadata_index.expression, eval_dict, AVAILABLE_INDEXING_FUNCTIONS)
target_directory = os.path.join(FILESERVING_PATH, fabricated_directory) target_directory = os.path.join(FILESERVING_PATH, fabricated_directory)
try: try:
os.makedirs(target_directory) os.makedirs(target_directory)
@@ -48,7 +51,7 @@ def document_create_fs_links(document):
#This should be a warning not an error #This should be a warning not an error
#pass #pass
except Exception, exc: except Exception, exc:
raise Exception(_(u'Unable to create metadata indexing directory: %s') % exc) warnings.append(_(u'Unable to create metadata indexing directory: %s') % exc)
return warnings return warnings