Commited new metadata/document_type paradirm
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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''
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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})
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user