Add document_indexing API endpoints

This commit is contained in:
Roberto Rosario
2014-10-13 19:12:16 -04:00
parent 32974f035d
commit 28a7c9789c
6 changed files with 134 additions and 16 deletions

View File

@@ -9,6 +9,7 @@ from main.api import register_maintenance_links
from metadata.models import DocumentMetadata from metadata.models import DocumentMetadata
from navigation.api import register_links, register_top_menu from navigation.api import register_links, register_top_menu
from project_setup.api import register_setup from project_setup.api import register_setup
from rest_api.classes import APIEndPoint
from .api import update_indexes, delete_indexes from .api import update_indexes, delete_indexes
from .links import (document_index_list, document_index_main_menu_link, 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, rebuild_index_instances, template_node_create,
template_node_delete, template_node_edit) template_node_delete, template_node_edit)
from .models import Index, IndexTemplateNode, IndexInstanceNode from .models import Index, IndexTemplateNode, IndexInstanceNode
from .urls import api_urls
@receiver(pre_delete, dispatch_uid='document_index_delete', sender=Document) @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_setup(index_setup)
register_top_menu('indexes', document_index_main_menu_link) 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.'))

View File

@@ -1,5 +1,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import logging
from django.db.models import Q from django.db.models import Q
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.utils.translation import ugettext 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, from .settings import (AVAILABLE_INDEXING_FUNCTIONS, MAX_SUFFIX_COUNT,
SLUGIFY_PATHS) SLUGIFY_PATHS)
logger = logging.getLogger(__name__)
if SLUGIFY_PATHS: if SLUGIFY_PATHS:
SLUGIFY_FUNCTION = slugify SLUGIFY_FUNCTION = slugify
else: else:
@@ -52,7 +55,7 @@ def delete_indexes(document):
warnings = [] 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) index_warnings = cascade_document_remove(document, index_instance)
warnings.extend(index_warnings) warnings.extend(index_warnings)
@@ -85,8 +88,10 @@ def cascade_eval(eval_dict, document, template_node, parent_index_instance=None)
try: try:
result = eval(template_node.expression, eval_dict, AVAILABLE_INDEXING_FUNCTIONS) result = eval(template_node.expression, eval_dict, AVAILABLE_INDEXING_FUNCTIONS)
except Exception as exception: except Exception as exception:
warnings.append(_(u'Error in document indexing update expression: %(expression)s; %(exception)s') % { error_message = _(u'Error in document indexing update expression: %(expression)s; %(exception)s') % {
'expression': template_node.expression, 'exception': exception}) 'expression': template_node.expression, 'exception': exception}
warnings.append(error_message)
logger.debug(error_message)
else: else:
if result: if result:
index_instance, created = IndexInstanceNode.objects.get_or_create(index_template_node=template_node, value=result, parent=parent_index_instance) 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: try:
fs_create_document_link(index_instance, document, suffix) fs_create_document_link(index_instance, document, suffix)
except Exception as exception: except Exception as exception:
warnings.append(_(u'Error updating document index, expression: %(expression)s; %(exception)s') % { error_message = _(u'Error updating document index, expression: %(expression)s; %(exception)s') % {
'expression': template_node.expression, 'exception': exception}) 'expression': template_node.expression, 'exception': exception}
warnings.append(error_message)
logger.debug(error_message)
index_instance.documents.add(document) index_instance.documents.add(document)

View 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()

View File

@@ -24,11 +24,11 @@ class Index(models.Model):
@property @property
def template_root(self): def template_root(self):
return self.indextemplatenode_set.get(parent=None) return self.template_nodes.get(parent=None)
@property @property
def instance_root(self): def instance_root(self):
return self.template_root.node_instance return self.template_root.node_instance.get()
def __unicode__(self): def __unicode__(self):
return self.title return self.title
@@ -41,6 +41,7 @@ class Index(models.Model):
return DocumentType.objects.exclude(pk__in=self.document_types.all()) return DocumentType.objects.exclude(pk__in=self.document_types.all())
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
"""Automatically create the root index template node"""
super(Index, self).save(*args, **kwargs) super(Index, self).save(*args, **kwargs)
index_template_node_root, created = IndexTemplateNode.objects.get_or_create(parent=None, index=self) 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: except IndexInstanceNode.DoesNotExist:
return 0 return 0
@property
def node_instances(self):
return [template_node.node_instance.get() for template_node in self.template_nodes.all()]
class Meta: class Meta:
verbose_name = _(u'Index') verbose_name = _(u'Index')
verbose_name_plural = _(u'Indexes') verbose_name_plural = _(u'Indexes')
class IndexTemplateNode(MPTTModel): class IndexTemplateNode(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='index_template_node') parent = TreeForeignKey('self', null=True, blank=True)
index = models.ForeignKey(Index, verbose_name=_(u'Index')) 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.')) 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) # % 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.')) 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): def __unicode__(self):
return self.expression return self.expression
@property
def node_instance(self):
return self.indexinstancenode_set.get()
class Meta: class Meta:
verbose_name = _(u'Index template node') verbose_name = _(u'Index template node')
verbose_name_plural = _(u'Indexes template nodes') verbose_name_plural = _(u'Indexes template nodes')
class IndexInstanceNode(MPTTModel): class IndexInstanceNode(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='index_instance_node') parent = TreeForeignKey('self', null=True, blank=True)
index_template_node = models.ForeignKey(IndexTemplateNode, verbose_name=_(u'Index template node')) 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')) 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): def __unicode__(self):
return self.value return self.value
def index(self):
return self.index_template_node.index
@models.permalink @models.permalink
def get_absolute_url(self): def get_absolute_url(self):
return ('indexing:index_instance_node_view', [self.pk]) return ('indexing:index_instance_node_view', [self.pk])

View 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

View File

@@ -1,5 +1,8 @@
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from .api_views import (APIIndexView, APIIndexListView,
APIIndexNodeInstanceDocumentListView)
urlpatterns = patterns('document_indexing.views', urlpatterns = patterns('document_indexing.views',
url(r'^setup/index/list/$', 'index_setup_list', (), 'index_setup_list'), url(r'^setup/index/list/$', 'index_setup_list', (), 'index_setup_list'),
url(r'^setup/index/create/$', 'index_setup_create', (), 'index_setup_create'), 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'^rebuild/all/$', 'rebuild_index_instances', (), 'rebuild_index_instances'),
url(r'^list/for/document/(?P<document_id>\d+)/$', 'document_index_list', (), 'document_index_list'), 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'),
)