Add document_indexing API endpoints
This commit is contained in:
@@ -9,6 +9,7 @@ from main.api import register_maintenance_links
|
||||
from metadata.models import DocumentMetadata
|
||||
from navigation.api import register_links, register_top_menu
|
||||
from project_setup.api import register_setup
|
||||
from rest_api.classes import APIEndPoint
|
||||
|
||||
from .api import update_indexes, delete_indexes
|
||||
from .links import (document_index_list, document_index_main_menu_link,
|
||||
@@ -18,6 +19,7 @@ from .links import (document_index_list, document_index_main_menu_link,
|
||||
rebuild_index_instances, template_node_create,
|
||||
template_node_delete, template_node_edit)
|
||||
from .models import Index, IndexTemplateNode, IndexInstanceNode
|
||||
from .urls import api_urls
|
||||
|
||||
|
||||
@receiver(pre_delete, dispatch_uid='document_index_delete', sender=Document)
|
||||
@@ -52,3 +54,7 @@ register_links(IndexTemplateNode, [template_node_create, template_node_edit, tem
|
||||
register_setup(index_setup)
|
||||
|
||||
register_top_menu('indexes', document_index_main_menu_link)
|
||||
|
||||
endpoint = APIEndPoint('indexes')
|
||||
endpoint.register_urls(api_urls)
|
||||
endpoint.add_endpoint('indexes-list', _(u'Returns a list of all the indexes.'))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from django.db.models import Q
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.utils.translation import ugettext
|
||||
@@ -15,6 +17,7 @@ from .models import Index, IndexInstanceNode, DocumentRenameCount
|
||||
from .settings import (AVAILABLE_INDEXING_FUNCTIONS, MAX_SUFFIX_COUNT,
|
||||
SLUGIFY_PATHS)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
if SLUGIFY_PATHS:
|
||||
SLUGIFY_FUNCTION = slugify
|
||||
else:
|
||||
@@ -52,7 +55,7 @@ def delete_indexes(document):
|
||||
|
||||
warnings = []
|
||||
|
||||
for index_instance in document.indexinstancenode_set.all():
|
||||
for index_instance in document.index_instance_nodes.all():
|
||||
index_warnings = cascade_document_remove(document, index_instance)
|
||||
warnings.extend(index_warnings)
|
||||
|
||||
@@ -85,8 +88,10 @@ def cascade_eval(eval_dict, document, template_node, parent_index_instance=None)
|
||||
try:
|
||||
result = eval(template_node.expression, eval_dict, AVAILABLE_INDEXING_FUNCTIONS)
|
||||
except Exception as exception:
|
||||
warnings.append(_(u'Error in document indexing update expression: %(expression)s; %(exception)s') % {
|
||||
'expression': template_node.expression, 'exception': exception})
|
||||
error_message = _(u'Error in document indexing update expression: %(expression)s; %(exception)s') % {
|
||||
'expression': template_node.expression, 'exception': exception}
|
||||
warnings.append(error_message)
|
||||
logger.debug(error_message)
|
||||
else:
|
||||
if result:
|
||||
index_instance, created = IndexInstanceNode.objects.get_or_create(index_template_node=template_node, value=result, parent=parent_index_instance)
|
||||
@@ -109,8 +114,10 @@ def cascade_eval(eval_dict, document, template_node, parent_index_instance=None)
|
||||
try:
|
||||
fs_create_document_link(index_instance, document, suffix)
|
||||
except Exception as exception:
|
||||
warnings.append(_(u'Error updating document index, expression: %(expression)s; %(exception)s') % {
|
||||
'expression': template_node.expression, 'exception': exception})
|
||||
error_message = _(u'Error updating document index, expression: %(expression)s; %(exception)s') % {
|
||||
'expression': template_node.expression, 'exception': exception}
|
||||
warnings.append(error_message)
|
||||
logger.debug(error_message)
|
||||
|
||||
index_instance.documents.add(document)
|
||||
|
||||
|
||||
64
mayan/apps/document_indexing/api_views.py
Normal file
64
mayan/apps/document_indexing/api_views.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from rest_framework import generics
|
||||
|
||||
from acls.models import AccessEntry
|
||||
from documents.models import Document
|
||||
from documents.permissions import PERMISSION_DOCUMENT_VIEW
|
||||
from permissions.models import Permission
|
||||
from rest_api.filters import MayanObjectPermissionsFilter
|
||||
from rest_api.permissions import MayanPermission
|
||||
|
||||
from .models import Index, IndexInstanceNode
|
||||
from .permissions import (PERMISSION_DOCUMENT_INDEXING_CREATE,
|
||||
PERMISSION_DOCUMENT_INDEXING_VIEW)
|
||||
from .serializers import IndexSerializer
|
||||
|
||||
|
||||
class APIIndexView(generics.RetrieveAPIView):
|
||||
"""
|
||||
Details of the selected index.
|
||||
"""
|
||||
serializer_class = IndexSerializer
|
||||
queryset = Index.objects.all()
|
||||
|
||||
permission_classes = (MayanPermission,)
|
||||
mayan_object_permissions = {'GET': [PERMISSION_DOCUMENT_INDEXING_VIEW]}
|
||||
|
||||
|
||||
class APIIndexListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
Returns a list of all the defined indexes.
|
||||
"""
|
||||
|
||||
serializer_class = IndexSerializer
|
||||
queryset = Index.objects.all()
|
||||
|
||||
filter_backends = (MayanObjectPermissionsFilter,)
|
||||
mayan_object_permissions = {'GET': [PERMISSION_DOCUMENT_INDEXING_VIEW]}
|
||||
mayan_view_permissions = {'POST': [PERMISSION_DOCUMENT_INDEXING_CREATE]}
|
||||
|
||||
|
||||
class APIIndexNodeInstanceDocumentListView(generics.ListAPIView):
|
||||
"""
|
||||
Returns a list of all the documents contained by a particular index node instance.
|
||||
"""
|
||||
|
||||
filter_backends = (MayanObjectPermissionsFilter,)
|
||||
mayan_object_permissions = {'GET': [PERMISSION_DOCUMENT_VIEW]}
|
||||
|
||||
def get_serializer_class(self):
|
||||
from documents.serializers import DocumentSerializer
|
||||
return DocumentSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
index_node_instance = get_object_or_404(IndexInstanceNode, pk=self.kwargs['pk'])
|
||||
try:
|
||||
Permission.objects.check_permissions(self.request.user, [PERMISSION_DOCUMENT_INDEXING_VIEW])
|
||||
except PermissionDenied:
|
||||
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_INDEXING_VIEW, self.request.user, index_node_instance.index)
|
||||
|
||||
return index_node_instance.documents.all()
|
||||
@@ -24,11 +24,11 @@ class Index(models.Model):
|
||||
|
||||
@property
|
||||
def template_root(self):
|
||||
return self.indextemplatenode_set.get(parent=None)
|
||||
return self.template_nodes.get(parent=None)
|
||||
|
||||
@property
|
||||
def instance_root(self):
|
||||
return self.template_root.node_instance
|
||||
return self.template_root.node_instance.get()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
@@ -41,6 +41,7 @@ class Index(models.Model):
|
||||
return DocumentType.objects.exclude(pk__in=self.document_types.all())
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""Automatically create the root index template node"""
|
||||
super(Index, self).save(*args, **kwargs)
|
||||
index_template_node_root, created = IndexTemplateNode.objects.get_or_create(parent=None, index=self)
|
||||
|
||||
@@ -56,14 +57,18 @@ class Index(models.Model):
|
||||
except IndexInstanceNode.DoesNotExist:
|
||||
return 0
|
||||
|
||||
@property
|
||||
def node_instances(self):
|
||||
return [template_node.node_instance.get() for template_node in self.template_nodes.all()]
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'Index')
|
||||
verbose_name_plural = _(u'Indexes')
|
||||
|
||||
|
||||
class IndexTemplateNode(MPTTModel):
|
||||
parent = TreeForeignKey('self', null=True, blank=True, related_name='index_template_node')
|
||||
index = models.ForeignKey(Index, verbose_name=_(u'Index'))
|
||||
parent = TreeForeignKey('self', null=True, blank=True)
|
||||
index = models.ForeignKey(Index, verbose_name=_(u'Index'), related_name='template_nodes')
|
||||
expression = models.CharField(max_length=128, verbose_name=_(u'Indexing expression'), help_text=_(u'Enter a python string expression to be evaluated.'))
|
||||
# % available_indexing_functions_string)
|
||||
enabled = models.BooleanField(default=True, verbose_name=_(u'Enabled'), help_text=_(u'Causes this node to be visible and updated when document data changes.'))
|
||||
@@ -72,24 +77,23 @@ class IndexTemplateNode(MPTTModel):
|
||||
def __unicode__(self):
|
||||
return self.expression
|
||||
|
||||
@property
|
||||
def node_instance(self):
|
||||
return self.indexinstancenode_set.get()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'Index template node')
|
||||
verbose_name_plural = _(u'Indexes template nodes')
|
||||
|
||||
|
||||
class IndexInstanceNode(MPTTModel):
|
||||
parent = TreeForeignKey('self', null=True, blank=True, related_name='index_instance_node')
|
||||
index_template_node = models.ForeignKey(IndexTemplateNode, verbose_name=_(u'Index template node'))
|
||||
parent = TreeForeignKey('self', null=True, blank=True)
|
||||
index_template_node = models.ForeignKey(IndexTemplateNode, related_name='node_instance', verbose_name=_(u'Index template node'))
|
||||
value = models.CharField(max_length=128, blank=True, verbose_name=_(u'Value'))
|
||||
documents = models.ManyToManyField(Document, verbose_name=_(u'Documents'))
|
||||
documents = models.ManyToManyField(Document, related_name='index_instance_nodes', verbose_name=_(u'Documents'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.value
|
||||
|
||||
def index(self):
|
||||
return self.index_template_node.index
|
||||
|
||||
@models.permalink
|
||||
def get_absolute_url(self):
|
||||
return ('indexing:index_instance_node_view', [self.pk])
|
||||
|
||||
27
mayan/apps/document_indexing/serializers.py
Normal file
27
mayan/apps/document_indexing/serializers.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import Index, IndexInstanceNode, IndexTemplateNode
|
||||
|
||||
|
||||
|
||||
class IndexInstanceNodeSerializer(serializers.ModelSerializer):
|
||||
documents = serializers.HyperlinkedIdentityField(view_name='index-node-documents')
|
||||
|
||||
class Meta:
|
||||
fields = ('id', 'parent', 'index_template_node', 'value', 'level', 'documents')
|
||||
model = IndexInstanceNode
|
||||
|
||||
|
||||
class IndexTemplateNodeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = IndexTemplateNode
|
||||
|
||||
|
||||
class IndexSerializer(serializers.ModelSerializer):
|
||||
template_nodes = IndexTemplateNodeSerializer(read_only=True, many=True)
|
||||
node_instances = IndexInstanceNodeSerializer(read_only=True, many=True)
|
||||
|
||||
class Meta:
|
||||
model = Index
|
||||
@@ -1,5 +1,8 @@
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from .api_views import (APIIndexView, APIIndexListView,
|
||||
APIIndexNodeInstanceDocumentListView)
|
||||
|
||||
urlpatterns = patterns('document_indexing.views',
|
||||
url(r'^setup/index/list/$', 'index_setup_list', (), 'index_setup_list'),
|
||||
url(r'^setup/index/create/$', 'index_setup_create', (), 'index_setup_create'),
|
||||
@@ -18,3 +21,10 @@ urlpatterns = patterns('document_indexing.views',
|
||||
url(r'^rebuild/all/$', 'rebuild_index_instances', (), 'rebuild_index_instances'),
|
||||
url(r'^list/for/document/(?P<document_id>\d+)/$', 'document_index_list', (), 'document_index_list'),
|
||||
)
|
||||
|
||||
api_urls = patterns('',
|
||||
url(r'^index/node/(?P<pk>[0-9]+)/documents/$', APIIndexNodeInstanceDocumentListView.as_view(), name='index-node-documents'),
|
||||
url(r'^indexes/(?P<pk>[0-9]+)/$', APIIndexView.as_view(), name='index-detail'),
|
||||
url(r'^indexes/$', APIIndexListView.as_view(), name='index-list'),
|
||||
#url(r'^document/(?P<pk>[0-9]+)/folders/$', APIDocumentFolderListView.as_view(), name='document-folder-list'),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user