Refactor metadata app API
Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
@@ -8,13 +8,14 @@ from mayan.apps.common.mixins import ContentTypeViewMixin, ExternalObjectMixin
|
|||||||
from mayan.apps.permissions.serializers import (
|
from mayan.apps.permissions.serializers import (
|
||||||
PermissionSerializer, RolePermissionAddRemoveSerializer
|
PermissionSerializer, RolePermissionAddRemoveSerializer
|
||||||
)
|
)
|
||||||
|
from mayan.apps.rest_api.mixins import ExternalObjectAPIViewSetMixin
|
||||||
from mayan.apps.rest_api.viewsets import MayanAPIModelViewSet
|
from mayan.apps.rest_api.viewsets import MayanAPIModelViewSet
|
||||||
|
|
||||||
from .permissions import permission_acl_edit, permission_acl_view
|
from .permissions import permission_acl_edit, permission_acl_view
|
||||||
from .serializers import AccessControlListSerializer
|
from .serializers import AccessControlListSerializer
|
||||||
|
|
||||||
|
|
||||||
class ObjectACLAPIViewSet(ContentTypeViewMixin, ExternalObjectMixin, MayanAPIModelViewSet):
|
class ObjectACLAPIViewSet(ContentTypeViewMixin, ExternalObjectAPIViewSetMixin, MayanAPIModelViewSet):
|
||||||
content_type_url_kw_args = {
|
content_type_url_kw_args = {
|
||||||
'app_label': 'app_label',
|
'app_label': 'app_label',
|
||||||
'model': 'model_name'
|
'model': 'model_name'
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ from rest_framework import viewsets
|
|||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from mayan.apps.common.mixins import ContentTypeViewMixin, ExternalObjectMixin
|
from mayan.apps.common.mixins import ContentTypeViewMixin
|
||||||
|
from mayan.apps.rest_api.mixins import ExternalObjectAPIViewSetMixin
|
||||||
from mayan.apps.rest_api.viewsets import MayanAPIReadOnlyModelViewSet
|
from mayan.apps.rest_api.viewsets import MayanAPIReadOnlyModelViewSet
|
||||||
|
|
||||||
from .classes import EventTypeNamespace
|
from .classes import EventTypeNamespace
|
||||||
@@ -80,7 +81,7 @@ class NotificationAPIViewSet(MayanAPIReadOnlyModelViewSet):
|
|||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class ObjectEventAPIViewSet(ContentTypeViewMixin, ExternalObjectMixin, MayanAPIReadOnlyModelViewSet):
|
class ObjectEventAPIViewSet(ContentTypeViewMixin, ExternalObjectAPIViewSetMixin, MayanAPIReadOnlyModelViewSet):
|
||||||
content_type_url_kw_args = {
|
content_type_url_kw_args = {
|
||||||
'app_label': 'app_label',
|
'app_label': 'app_label',
|
||||||
'model': 'model_name'
|
'model': 'model_name'
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from django.shortcuts import get_object_or_404
|
from rest_framework import status
|
||||||
|
from rest_framework.decorators import action
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from rest_framework import generics
|
from mayan.apps.documents.models import Document
|
||||||
|
|
||||||
from mayan.apps.acls.models import AccessControlList
|
|
||||||
from mayan.apps.documents.models import Document, DocumentType
|
|
||||||
from mayan.apps.documents.permissions import (
|
from mayan.apps.documents.permissions import (
|
||||||
permission_document_type_view, permission_document_type_edit
|
permission_document_type_view, permission_document_type_edit,
|
||||||
|
)
|
||||||
|
from mayan.apps.rest_api.mixins import ExternalObjectAPIViewSetMixin
|
||||||
|
from mayan.apps.rest_api.viewsets import (
|
||||||
|
MayanAPIModelViewSet, MayanRetrieveUpdateAPIViewSet,
|
||||||
)
|
)
|
||||||
from mayan.apps.rest_api.filters import MayanObjectPermissionsFilter
|
|
||||||
from mayan.apps.rest_api.permissions import MayanPermission
|
|
||||||
|
|
||||||
from .models import MetadataType
|
from .models import MetadataType
|
||||||
from .permissions import (
|
from .permissions import (
|
||||||
@@ -20,235 +21,140 @@ from .permissions import (
|
|||||||
permission_metadata_type_edit, permission_metadata_type_view
|
permission_metadata_type_edit, permission_metadata_type_view
|
||||||
)
|
)
|
||||||
from .serializers import (
|
from .serializers import (
|
||||||
DocumentMetadataSerializer, DocumentTypeMetadataTypeSerializer,
|
DocumentMetadataAddSerializer,
|
||||||
MetadataTypeSerializer, NewDocumentMetadataSerializer,
|
DocumentMetadataSerializer,
|
||||||
NewDocumentTypeMetadataTypeSerializer,
|
MetadataTypeSerializer,
|
||||||
WritableDocumentTypeMetadataTypeSerializer
|
MetadataTypeDocumentTypeRelationSerializer,
|
||||||
|
MetadataTypeDocumentTypeRelationAddRemoveSerializer,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class APIDocumentMetadataListView(generics.ListCreateAPIView):
|
class MetadataTypeDocumentTypeRelationAPIViewSet(ExternalObjectAPIViewSetMixin, MayanRetrieveUpdateAPIViewSet):
|
||||||
"""
|
external_object_class = MetadataType
|
||||||
get: Returns a list of selected document's metadata types and values.
|
external_object_pk_url_kwarg = 'metadata_type_id'
|
||||||
post: Add an existing metadata type and value to the selected document.
|
lookup_url_kwarg = 'metadata_type_document_type_relation_id'
|
||||||
"""
|
object_permission_map = {
|
||||||
def get_document(self):
|
'add': permission_metadata_type_edit,
|
||||||
if self.request.method == 'GET':
|
'list': permission_document_type_view,
|
||||||
permission_required = permission_metadata_view
|
'partial_update': permission_document_type_edit,
|
||||||
|
'remove': permission_metadata_type_edit,
|
||||||
|
'retrieve': permission_document_type_view,
|
||||||
|
'update': permission_document_type_edit,
|
||||||
|
}
|
||||||
|
serializer_class = MetadataTypeDocumentTypeRelationSerializer
|
||||||
|
|
||||||
|
def get_external_object_permission(self):
|
||||||
|
action = getattr(self, 'action', None)
|
||||||
|
if action is None:
|
||||||
|
return None
|
||||||
|
elif action in ['list', 'retrieve']:
|
||||||
|
return permission_metadata_type_view
|
||||||
else:
|
else:
|
||||||
permission_required = permission_metadata_add
|
return permission_metadata_type_edit
|
||||||
|
|
||||||
document = get_object_or_404(
|
|
||||||
klass=Document, pk=self.kwargs['document_pk']
|
|
||||||
)
|
|
||||||
|
|
||||||
AccessControlList.objects.check_access(
|
|
||||||
permissions=permission_required, user=self.request.user,
|
|
||||||
obj=document
|
|
||||||
)
|
|
||||||
|
|
||||||
return document
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.get_document().metadata.all()
|
action = getattr(self, 'action', None)
|
||||||
|
if action in ['add', 'remove']:
|
||||||
|
# Return metadata types
|
||||||
|
return self.get_external_object_queryset()
|
||||||
|
else:
|
||||||
|
# Return relations
|
||||||
|
return self.get_external_object().document_type_relations.all()
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
@action(
|
||||||
if not self.request:
|
detail=False, lookup_url_kwarg='metadata_type_id', methods=('post',),
|
||||||
|
serializer_class=MetadataTypeDocumentTypeRelationAddRemoveSerializer,
|
||||||
|
url_name='add', url_path='add'
|
||||||
|
)
|
||||||
|
def add(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
serializer.document_type_relations_add(instance=instance)
|
||||||
|
headers = self.get_success_headers(data=serializer.data)
|
||||||
|
return Response(
|
||||||
|
serializer.data, status=status.HTTP_200_OK, headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
@action(
|
||||||
|
detail=False, lookup_url_kwarg='metadata_type_id', methods=('post',),
|
||||||
|
serializer_class=MetadataTypeDocumentTypeRelationAddRemoveSerializer,
|
||||||
|
url_name='remove', url_path='remove'
|
||||||
|
)
|
||||||
|
def remove(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
serializer.document_type_relations_remove(instance=instance)
|
||||||
|
headers = self.get_success_headers(data=serializer.data)
|
||||||
|
return Response(
|
||||||
|
serializer.data, status=status.HTTP_200_OK, headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MetadataTypeAPIViewSet(MayanAPIModelViewSet):
|
||||||
|
lookup_url_kwarg = 'metadata_type_id'
|
||||||
|
object_permission_map = {
|
||||||
|
'destroy': permission_metadata_type_delete,
|
||||||
|
'list': permission_metadata_type_view,
|
||||||
|
'partial_update': permission_metadata_type_edit,
|
||||||
|
'retrieve': permission_metadata_type_view,
|
||||||
|
'update': permission_metadata_type_edit,
|
||||||
|
}
|
||||||
|
queryset = MetadataType.objects.all()
|
||||||
|
serializer_class = MetadataTypeSerializer
|
||||||
|
view_permission_map = {
|
||||||
|
'create': permission_metadata_type_create
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentMetadataAPIViewSet(ExternalObjectAPIViewSetMixin, MayanAPIModelViewSet):
|
||||||
|
external_object_class = Document
|
||||||
|
external_object_pk_url_kwarg = 'document_id'
|
||||||
|
lookup_url_kwarg = 'document_metadata_id'
|
||||||
|
object_permission_map = {
|
||||||
|
'list': permission_metadata_view,
|
||||||
|
'partial_update': permission_metadata_edit,
|
||||||
|
'destroy': permission_metadata_remove,
|
||||||
|
'retrieve': permission_metadata_view,
|
||||||
|
'update': permission_metadata_edit,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_external_object_permission(self):
|
||||||
|
action = getattr(self, 'action', None)
|
||||||
|
if action is None:
|
||||||
return None
|
return None
|
||||||
|
elif action == 'create':
|
||||||
|
return permission_metadata_add
|
||||||
|
elif action == 'destroy':
|
||||||
|
return permission_metadata_remove
|
||||||
|
elif action in ['partial_update', 'update']:
|
||||||
|
return permission_metadata_edit
|
||||||
|
else:
|
||||||
|
return permission_metadata_view
|
||||||
|
|
||||||
return super(APIDocumentMetadataListView, self).get_serializer(*args, **kwargs)
|
def get_queryset(self):
|
||||||
|
return self.get_external_object().metadata.all()
|
||||||
|
|
||||||
def get_serializer_class(self):
|
def get_serializer_class(self):
|
||||||
if self.request.method == 'GET':
|
action = getattr(self, 'action', None)
|
||||||
return DocumentMetadataSerializer
|
if action is None:
|
||||||
|
return None
|
||||||
|
if action == 'create':
|
||||||
|
return DocumentMetadataAddSerializer
|
||||||
else:
|
else:
|
||||||
return NewDocumentMetadataSerializer
|
return DocumentMetadataSerializer
|
||||||
|
|
||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
"""
|
"""
|
||||||
Extra context provided to the serializer class.
|
Extra context provided to the serializer class.
|
||||||
"""
|
"""
|
||||||
context = super(APIDocumentMetadataListView, self).get_serializer_context()
|
context = super(DocumentMetadataAPIViewSet, self).get_serializer_context()
|
||||||
if self.kwargs:
|
if self.kwargs:
|
||||||
context.update(
|
context.update(
|
||||||
{
|
{
|
||||||
'document': self.get_document(),
|
'document': self.get_external_object(),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class APIDocumentMetadataView(generics.RetrieveUpdateDestroyAPIView):
|
|
||||||
"""
|
|
||||||
delete: Remove this metadata entry from the selected document.
|
|
||||||
get: Return the details of the selected document metadata type and value.
|
|
||||||
patch: Edit the selected document metadata type and value.
|
|
||||||
put: Edit the selected document metadata type and value.
|
|
||||||
"""
|
|
||||||
lookup_url_kwarg = 'metadata_pk'
|
|
||||||
|
|
||||||
def get_document(self):
|
|
||||||
if self.request.method == 'GET':
|
|
||||||
permission_required = permission_metadata_view
|
|
||||||
elif self.request.method == 'PUT':
|
|
||||||
permission_required = permission_metadata_edit
|
|
||||||
elif self.request.method == 'PATCH':
|
|
||||||
permission_required = permission_metadata_edit
|
|
||||||
elif self.request.method == 'DELETE':
|
|
||||||
permission_required = permission_metadata_remove
|
|
||||||
|
|
||||||
document = get_object_or_404(
|
|
||||||
klass=Document, pk=self.kwargs['document_pk']
|
|
||||||
)
|
|
||||||
|
|
||||||
AccessControlList.objects.check_access(
|
|
||||||
permissions=permission_required, user=self.request.user,
|
|
||||||
obj=document
|
|
||||||
)
|
|
||||||
|
|
||||||
return document
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return self.get_document().metadata.all()
|
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
|
||||||
if not self.request:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return super(APIDocumentMetadataView, self).get_serializer(*args, **kwargs)
|
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
if self.request.method == 'GET':
|
|
||||||
return DocumentMetadataSerializer
|
|
||||||
else:
|
|
||||||
return DocumentMetadataSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class APIMetadataTypeListView(generics.ListCreateAPIView):
|
|
||||||
"""
|
|
||||||
get: Returns a list of all the metadata types.
|
|
||||||
post: Create a new metadata type.
|
|
||||||
"""
|
|
||||||
filter_backends = (MayanObjectPermissionsFilter,)
|
|
||||||
mayan_object_permissions = {'GET': (permission_metadata_type_view,)}
|
|
||||||
mayan_view_permissions = {'POST': (permission_metadata_type_create,)}
|
|
||||||
permission_classes = (MayanPermission,)
|
|
||||||
queryset = MetadataType.objects.all()
|
|
||||||
serializer_class = MetadataTypeSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class APIMetadataTypeView(generics.RetrieveUpdateDestroyAPIView):
|
|
||||||
"""
|
|
||||||
delete: Delete the selected metadata type.
|
|
||||||
get: Return the details of the selected metadata type.
|
|
||||||
patch: Edit the selected metadata type.
|
|
||||||
put: Edit the selected metadata type.
|
|
||||||
"""
|
|
||||||
lookup_url_kwarg = 'metadata_type_pk'
|
|
||||||
mayan_object_permissions = {
|
|
||||||
'GET': (permission_metadata_type_view,),
|
|
||||||
'PUT': (permission_metadata_type_edit,),
|
|
||||||
'PATCH': (permission_metadata_type_edit,),
|
|
||||||
'DELETE': (permission_metadata_type_delete,)
|
|
||||||
}
|
|
||||||
permission_classes = (MayanPermission,)
|
|
||||||
queryset = MetadataType.objects.all()
|
|
||||||
serializer_class = MetadataTypeSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class APIDocumentTypeMetadataTypeListView(generics.ListCreateAPIView):
|
|
||||||
"""
|
|
||||||
get: Returns a list of selected document type's metadata types.
|
|
||||||
post: Add a metadata type to the selected document type.
|
|
||||||
"""
|
|
||||||
lookup_url_kwarg = 'metadata_type_pk'
|
|
||||||
|
|
||||||
def get_document_type(self):
|
|
||||||
if self.request.method == 'GET':
|
|
||||||
permission_required = permission_document_type_view
|
|
||||||
else:
|
|
||||||
permission_required = permission_document_type_edit
|
|
||||||
|
|
||||||
document_type = get_object_or_404(
|
|
||||||
klass=DocumentType, pk=self.kwargs['document_type_pk']
|
|
||||||
)
|
|
||||||
|
|
||||||
AccessControlList.objects.check_access(
|
|
||||||
permissions=permission_required, user=self.request.user,
|
|
||||||
obj=document_type
|
|
||||||
)
|
|
||||||
|
|
||||||
return document_type
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return self.get_document_type().metadata.all()
|
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
|
||||||
if not self.request:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return super(APIDocumentTypeMetadataTypeListView, self).get_serializer(*args, **kwargs)
|
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
if self.request.method == 'GET':
|
|
||||||
return DocumentTypeMetadataTypeSerializer
|
|
||||||
else:
|
|
||||||
return NewDocumentTypeMetadataTypeSerializer
|
|
||||||
|
|
||||||
def get_serializer_context(self):
|
|
||||||
"""
|
|
||||||
Extra context provided to the serializer class.
|
|
||||||
"""
|
|
||||||
context = super(APIDocumentTypeMetadataTypeListView, self).get_serializer_context()
|
|
||||||
if self.kwargs:
|
|
||||||
context.update(
|
|
||||||
{
|
|
||||||
'document_type': self.get_document_type(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class APIDocumentTypeMetadataTypeView(generics.RetrieveUpdateDestroyAPIView):
|
|
||||||
"""
|
|
||||||
delete: Remove a metadata type from a document type.
|
|
||||||
get: Retrieve the details of a document type metadata type.
|
|
||||||
patch: Edit the selected document type metadata type.
|
|
||||||
put: Edit the selected document type metadata type.
|
|
||||||
"""
|
|
||||||
lookup_url_kwarg = 'metadata_type_pk'
|
|
||||||
serializer_class = DocumentTypeMetadataTypeSerializer
|
|
||||||
|
|
||||||
def get_document_type(self):
|
|
||||||
if self.request.method == 'GET':
|
|
||||||
permission_required = permission_document_type_view
|
|
||||||
else:
|
|
||||||
permission_required = permission_document_type_edit
|
|
||||||
|
|
||||||
document_type = get_object_or_404(
|
|
||||||
klass=DocumentType, pk=self.kwargs['document_type_pk']
|
|
||||||
)
|
|
||||||
|
|
||||||
AccessControlList.objects.check_access(
|
|
||||||
permissions=permission_required, user=self.request.user,
|
|
||||||
obj=document_type
|
|
||||||
)
|
|
||||||
|
|
||||||
return document_type
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return self.get_document_type().metadata.all()
|
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
|
||||||
if not self.request:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return super(APIDocumentTypeMetadataTypeView, self).get_serializer(*args, **kwargs)
|
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
if self.request.method == 'GET':
|
|
||||||
return DocumentTypeMetadataTypeSerializer
|
|
||||||
else:
|
|
||||||
return WritableDocumentTypeMetadataTypeSerializer
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from mayan.apps.acls.links import link_acl_list
|
|||||||
from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
|
from mayan.apps.acls.permissions import permission_acl_edit, permission_acl_view
|
||||||
from mayan.apps.common import (
|
from mayan.apps.common import (
|
||||||
MayanAppConfig, menu_facet, menu_list_facet, menu_multi_item, menu_object,
|
MayanAppConfig, menu_facet, menu_list_facet, menu_multi_item, menu_object,
|
||||||
menu_secondary, menu_setup, menu_secondary
|
menu_secondary, menu_setup
|
||||||
)
|
)
|
||||||
from mayan.apps.common.classes import ModelAttribute, ModelField
|
from mayan.apps.common.classes import ModelAttribute, ModelField
|
||||||
from mayan.apps.common.widgets import TwoStateWidget
|
from mayan.apps.common.widgets import TwoStateWidget
|
||||||
@@ -26,6 +26,8 @@ from mayan.apps.events.links import (
|
|||||||
from mayan.apps.events.permissions import permission_events_view
|
from mayan.apps.events.permissions import permission_events_view
|
||||||
from mayan.celery import app
|
from mayan.celery import app
|
||||||
from mayan.apps.navigation import SourceColumn
|
from mayan.apps.navigation import SourceColumn
|
||||||
|
from mayan.apps.rest_api.fields import HyperlinkField
|
||||||
|
from mayan.apps.rest_api.serializers import LazyExtraFieldsSerializerMixin
|
||||||
|
|
||||||
from .events import (
|
from .events import (
|
||||||
event_document_metadata_added, event_document_metadata_edited,
|
event_document_metadata_added, event_document_metadata_edited,
|
||||||
@@ -80,11 +82,9 @@ class MetadataApp(MayanAppConfig):
|
|||||||
DocumentPageSearchResult = apps.get_model(
|
DocumentPageSearchResult = apps.get_model(
|
||||||
app_label='documents', model_name='DocumentPageSearchResult'
|
app_label='documents', model_name='DocumentPageSearchResult'
|
||||||
)
|
)
|
||||||
|
|
||||||
DocumentType = apps.get_model(
|
DocumentType = apps.get_model(
|
||||||
app_label='documents', model_name='DocumentType'
|
app_label='documents', model_name='DocumentType'
|
||||||
)
|
)
|
||||||
|
|
||||||
DocumentMetadata = self.get_model('DocumentMetadata')
|
DocumentMetadata = self.get_model('DocumentMetadata')
|
||||||
DocumentTypeMetadataType = self.get_model('DocumentTypeMetadataType')
|
DocumentTypeMetadataType = self.get_model('DocumentTypeMetadataType')
|
||||||
MetadataType = self.get_model('MetadataType')
|
MetadataType = self.get_model('MetadataType')
|
||||||
@@ -93,6 +93,15 @@ class MetadataApp(MayanAppConfig):
|
|||||||
name='get_metadata', value=method_get_metadata
|
name='get_metadata', value=method_get_metadata
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LazyExtraFieldsSerializerMixin.add_field(
|
||||||
|
dotted_path='mayan.apps.documents.serializers.DocumentSerializer',
|
||||||
|
field_name='metadata_list_url',
|
||||||
|
field=HyperlinkField(
|
||||||
|
lookup_url_kwarg='document_id',
|
||||||
|
view_name='rest_api:document-metadata-list'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
ModelAttribute(model=Document, name='get_metadata')
|
ModelAttribute(model=Document, name='get_metadata')
|
||||||
|
|
||||||
ModelField(
|
ModelField(
|
||||||
@@ -140,10 +149,25 @@ class MetadataApp(MayanAppConfig):
|
|||||||
model=MetadataType, permissions=(
|
model=MetadataType, permissions=(
|
||||||
permission_acl_edit, permission_acl_view,
|
permission_acl_edit, permission_acl_view,
|
||||||
permission_events_view, permission_metadata_type_delete,
|
permission_events_view, permission_metadata_type_delete,
|
||||||
|
permission_metadata_add, permission_metadata_edit,
|
||||||
|
permission_metadata_remove, permission_metadata_view,
|
||||||
permission_metadata_type_edit, permission_metadata_type_view
|
permission_metadata_type_edit, permission_metadata_type_view
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ModelPermission.register_inheritance(
|
||||||
|
model=DocumentMetadata, related='document',
|
||||||
|
)
|
||||||
|
ModelPermission.register_inheritance(
|
||||||
|
model=DocumentMetadata, related='metadata_type',
|
||||||
|
)
|
||||||
|
ModelPermission.register_inheritance(
|
||||||
|
model=DocumentTypeMetadataType, related='document_type',
|
||||||
|
)
|
||||||
|
ModelPermission.register_inheritance(
|
||||||
|
model=DocumentTypeMetadataType, related='metadata_type',
|
||||||
|
)
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
func=widget_get_metadata_string, source=Document
|
func=widget_get_metadata_string, source=Document
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -198,12 +198,12 @@ class DocumentTypeMetadataTypeRelationshipForm(forms.Form):
|
|||||||
self.fields['relationship_type'].initial = self.initial_relationship_type
|
self.fields['relationship_type'].initial = self.initial_relationship_type
|
||||||
|
|
||||||
def get_relationship(self):
|
def get_relationship(self):
|
||||||
return self.initial['document_type'].metadata.filter(
|
return self.initial['document_type'].metadata_type_relations.filter(
|
||||||
metadata_type=self.initial['metadata_type']
|
metadata_type=self.initial['metadata_type']
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_relationship_choices(self):
|
def get_relationship_choices(self):
|
||||||
return self.initial['document_type'].metadata.filter(
|
return self.initial['document_type'].metadata_type_relations.filter(
|
||||||
metadata_type=self.initial['metadata_type']
|
metadata_type=self.initial['metadata_type']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ def handler_post_document_type_change(sender, instance, **kwargs):
|
|||||||
# First get the existing metadata types not found in the new document
|
# First get the existing metadata types not found in the new document
|
||||||
# type
|
# type
|
||||||
unneeded_metadata = instance.metadata.exclude(
|
unneeded_metadata = instance.metadata.exclude(
|
||||||
metadata_type__in=instance.document_type.metadata.values(
|
metadata_type__in=instance.document_type.metadata_type_relations.values(
|
||||||
'metadata_type'
|
'metadata_type'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -39,7 +39,7 @@ def handler_post_document_type_change(sender, instance, **kwargs):
|
|||||||
# excluding existing document metadata
|
# excluding existing document metadata
|
||||||
# get_or_create is not used to avoid a possible triggering of indexes
|
# get_or_create is not used to avoid a possible triggering of indexes
|
||||||
# or workflow on document change by metadata save signal
|
# or workflow on document change by metadata save signal
|
||||||
new_document_type_metadata_types = instance.document_type.metadata.filter(
|
new_document_type_metadata_types = instance.document_type.metadata_type_relations.filter(
|
||||||
required=True
|
required=True
|
||||||
).exclude(metadata_type__in=instance.metadata.values('metadata_type'))
|
).exclude(metadata_type__in=instance.metadata.values('metadata_type'))
|
||||||
|
|
||||||
|
|||||||
@@ -9,18 +9,10 @@ class MetadataTypeManager(models.Manager):
|
|||||||
return self.get(name=name)
|
return self.get(name=name)
|
||||||
|
|
||||||
def get_for_document(self, document):
|
def get_for_document(self, document):
|
||||||
return self.filter(
|
return self.filter(document_metadata__document=document)
|
||||||
pk__in=document.metadata.values_list(
|
|
||||||
'metadata_type', flat=True
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_for_document_type(self, document_type):
|
def get_for_document_type(self, document_type):
|
||||||
return self.filter(
|
return self.filter(document_type_relations__document_type=document_type)
|
||||||
pk__in=document_type.metadata.values_list(
|
|
||||||
'metadata_type', flat=True
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DocumentTypeMetadataTypeManager(models.Manager):
|
class DocumentTypeMetadataTypeManager(models.Manager):
|
||||||
|
|||||||
@@ -5,13 +5,15 @@ import shlex
|
|||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models, transaction
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_text, python_2_unicode_compatible
|
from django.utils.encoding import force_text, python_2_unicode_compatible
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
from django.utils.six import PY2
|
from django.utils.six import PY2
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from mayan.apps.acls.models import AccessControlList
|
||||||
|
from mayan.apps.documents.events import event_document_type_edited
|
||||||
from mayan.apps.documents.models import Document, DocumentType
|
from mayan.apps.documents.models import Document, DocumentType
|
||||||
|
|
||||||
from .classes import MetadataLookup
|
from .classes import MetadataLookup
|
||||||
@@ -126,6 +128,38 @@ class MetadataType(models.Model):
|
|||||||
template = Template(self.default)
|
template = Template(self.default)
|
||||||
return template.render()
|
return template.render()
|
||||||
|
|
||||||
|
def get_document_type_relations(self, permission, user):
|
||||||
|
return AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission, queryset=self.document_type_relations.all(),
|
||||||
|
user=user
|
||||||
|
)
|
||||||
|
|
||||||
|
def document_types_add(self, queryset, required=False, _user=None):
|
||||||
|
with transaction.atomic():
|
||||||
|
event_metadata_type_edited.commit(
|
||||||
|
actor=_user, target=self
|
||||||
|
)
|
||||||
|
for obj in queryset:
|
||||||
|
self.document_type_relations.create(
|
||||||
|
document_type=obj, required=required
|
||||||
|
)
|
||||||
|
event_document_type_edited.commit(
|
||||||
|
actor=_user, action_object=self, target=obj
|
||||||
|
)
|
||||||
|
|
||||||
|
def document_types_remove(self, queryset, _user=None):
|
||||||
|
with transaction.atomic():
|
||||||
|
event_metadata_type_edited.commit(
|
||||||
|
actor=_user, target=self
|
||||||
|
)
|
||||||
|
for obj in queryset:
|
||||||
|
self.document_type_relations.filter(
|
||||||
|
document_type=obj
|
||||||
|
).delete()
|
||||||
|
event_document_type_edited.commit(
|
||||||
|
actor=_user, action_object=self, target=obj
|
||||||
|
)
|
||||||
|
|
||||||
def get_lookup_choices(self, first_choice=None):
|
def get_lookup_choices(self, first_choice=None):
|
||||||
template = Template(self.lookup)
|
template = Template(self.lookup)
|
||||||
context = MetadataLookup.get_as_context()
|
context = MetadataLookup.get_as_context()
|
||||||
@@ -146,7 +180,7 @@ class MetadataType(models.Model):
|
|||||||
Return a queryset of metadata types that are required for the
|
Return a queryset of metadata types that are required for the
|
||||||
specified document type.
|
specified document type.
|
||||||
"""
|
"""
|
||||||
return document_type.metadata.filter(
|
return document_type.metadata_type_relations.filter(
|
||||||
required=True, metadata_type=self
|
required=True, metadata_type=self
|
||||||
).exists()
|
).exists()
|
||||||
|
|
||||||
@@ -157,6 +191,7 @@ class MetadataType(models.Model):
|
|||||||
user = kwargs.pop('_user', None)
|
user = kwargs.pop('_user', None)
|
||||||
created = not self.pk
|
created = not self.pk
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
result = super(MetadataType, self).save(*args, **kwargs)
|
result = super(MetadataType, self).save(*args, **kwargs)
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
@@ -210,7 +245,8 @@ class DocumentMetadata(models.Model):
|
|||||||
verbose_name=_('Document')
|
verbose_name=_('Document')
|
||||||
)
|
)
|
||||||
metadata_type = models.ForeignKey(
|
metadata_type = models.ForeignKey(
|
||||||
on_delete=models.CASCADE, to=MetadataType, verbose_name=_('Type')
|
on_delete=models.CASCADE, related_name='document_metadata', to=MetadataType,
|
||||||
|
verbose_name=_('Type')
|
||||||
)
|
)
|
||||||
value = models.CharField(
|
value = models.CharField(
|
||||||
blank=True, db_index=True, help_text=_(
|
blank=True, db_index=True, help_text=_(
|
||||||
@@ -242,17 +278,19 @@ class DocumentMetadata(models.Model):
|
|||||||
It used set to False when deleting document metadata on document
|
It used set to False when deleting document metadata on document
|
||||||
type change.
|
type change.
|
||||||
"""
|
"""
|
||||||
if enforce_required and self.metadata_type.pk in self.document.document_type.metadata.filter(required=True).values_list('metadata_type', flat=True):
|
if enforce_required and self.metadata_type.pk in self.document.document_type.metadata_type_relations.filter(required=True).values_list('metadata_type', flat=True):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_('Metadata type is required for this document type.')
|
_('Metadata type is required for this document type.')
|
||||||
)
|
)
|
||||||
|
|
||||||
user = kwargs.pop('_user', None)
|
user = kwargs.pop('_user', None)
|
||||||
|
with transaction.atomic():
|
||||||
result = super(DocumentMetadata, self).delete(*args, **kwargs)
|
result = super(DocumentMetadata, self).delete(*args, **kwargs)
|
||||||
|
|
||||||
event_document_metadata_removed.commit(
|
event_document_metadata_removed.commit(
|
||||||
action_object=self.metadata_type, actor=user, target=self.document,
|
action_object=self.metadata_type, actor=user, target=self.document,
|
||||||
)
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def natural_key(self):
|
def natural_key(self):
|
||||||
@@ -271,7 +309,7 @@ class DocumentMetadata(models.Model):
|
|||||||
is_required.fget.short_description = _('Required')
|
is_required.fget.short_description = _('Required')
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if self.metadata_type.pk not in self.document.document_type.metadata.values_list('metadata_type', flat=True):
|
if self.metadata_type.pk not in self.document.document_type.metadata_type_relations.values_list('metadata_type', flat=True):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_('Metadata type is not valid for this document type.')
|
_('Metadata type is not valid for this document type.')
|
||||||
)
|
)
|
||||||
@@ -279,6 +317,7 @@ class DocumentMetadata(models.Model):
|
|||||||
user = kwargs.pop('_user', None)
|
user = kwargs.pop('_user', None)
|
||||||
created = not self.pk
|
created = not self.pk
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
result = super(DocumentMetadata, self).save(*args, **kwargs)
|
result = super(DocumentMetadata, self).save(*args, **kwargs)
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
@@ -302,12 +341,12 @@ class DocumentTypeMetadataType(models.Model):
|
|||||||
document type.
|
document type.
|
||||||
"""
|
"""
|
||||||
document_type = models.ForeignKey(
|
document_type = models.ForeignKey(
|
||||||
on_delete=models.CASCADE, related_name='metadata', to=DocumentType,
|
on_delete=models.CASCADE, related_name='metadata_type_relations',
|
||||||
verbose_name=_('Document type')
|
to=DocumentType, verbose_name=_('Document type')
|
||||||
)
|
)
|
||||||
metadata_type = models.ForeignKey(
|
metadata_type = models.ForeignKey(
|
||||||
on_delete=models.CASCADE, to=MetadataType,
|
on_delete=models.CASCADE, related_name='document_type_relations',
|
||||||
verbose_name=_('Metadata type')
|
to=MetadataType, verbose_name=_('Metadata type')
|
||||||
)
|
)
|
||||||
required = models.BooleanField(default=False, verbose_name=_('Required'))
|
required = models.BooleanField(default=False, verbose_name=_('Required'))
|
||||||
|
|
||||||
@@ -325,6 +364,7 @@ class DocumentTypeMetadataType(models.Model):
|
|||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
user = kwargs.pop('_user', None)
|
user = kwargs.pop('_user', None)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
result = super(DocumentTypeMetadataType, self).delete(*args, **kwargs)
|
result = super(DocumentTypeMetadataType, self).delete(*args, **kwargs)
|
||||||
|
|
||||||
event_metadata_type_relationship.commit(
|
event_metadata_type_relationship.commit(
|
||||||
@@ -336,6 +376,7 @@ class DocumentTypeMetadataType(models.Model):
|
|||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
user = kwargs.pop('_user', None)
|
user = kwargs.pop('_user', None)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
result = super(DocumentTypeMetadataType, self).save(*args, **kwargs)
|
result = super(DocumentTypeMetadataType, self).save(*args, **kwargs)
|
||||||
|
|
||||||
event_metadata_type_relationship.commit(
|
event_metadata_type_relationship.commit(
|
||||||
|
|||||||
@@ -5,158 +5,149 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
|
from mayan.apps.documents.models import DocumentType
|
||||||
|
from mayan.apps.documents.permissions import permission_document_type_edit
|
||||||
from mayan.apps.documents.serializers import (
|
from mayan.apps.documents.serializers import (
|
||||||
DocumentSerializer, DocumentTypeSerializer
|
DocumentSerializer, DocumentTypeSerializer
|
||||||
)
|
)
|
||||||
|
from mayan.apps.rest_api.mixins import ExternalObjectListSerializerMixin
|
||||||
|
from mayan.apps.rest_api.relations import (
|
||||||
|
FilteredPrimaryKeyRelatedField, MultiKwargHyperlinkedIdentityField
|
||||||
|
)
|
||||||
|
|
||||||
from .models import DocumentMetadata, DocumentTypeMetadataType, MetadataType
|
from .models import DocumentMetadata, DocumentTypeMetadataType, MetadataType
|
||||||
|
from .permissions import permission_metadata_add
|
||||||
|
|
||||||
|
|
||||||
class MetadataTypeSerializer(serializers.HyperlinkedModelSerializer):
|
class MetadataTypeSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
document_type_relation_add_url = serializers.HyperlinkedIdentityField(
|
||||||
|
lookup_url_kwarg='metadata_type_id', view_name='rest_api:metadata_type-document_type_relation-add'
|
||||||
|
)
|
||||||
|
document_type_relation_list_url = serializers.HyperlinkedIdentityField(
|
||||||
|
lookup_url_kwarg='metadata_type_id', view_name='rest_api:metadata_type-document_type_relation-list'
|
||||||
|
)
|
||||||
|
document_type_relation_remove_url = serializers.HyperlinkedIdentityField(
|
||||||
|
lookup_url_kwarg='metadata_type_id', view_name='rest_api:metadata_type-document_type_relation-remove'
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'url': {
|
'url': {
|
||||||
'lookup_field': 'pk', 'lookup_url_kwarg': 'metadata_type_pk',
|
'lookup_url_kwarg': 'metadata_type_id',
|
||||||
'view_name': 'rest_api:metadatatype-detail'
|
'view_name': 'rest_api:metadata_type-detail'
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fields = (
|
fields = (
|
||||||
'default', 'id', 'label', 'lookup', 'name', 'parser', 'url',
|
'default', 'document_type_relation_add_url', 'document_type_relation_list_url',
|
||||||
'validation'
|
'document_type_relation_remove_url', 'id', 'label', 'lookup', 'name',
|
||||||
|
'parser', 'url', 'validation'
|
||||||
)
|
)
|
||||||
model = MetadataType
|
model = MetadataType
|
||||||
|
|
||||||
|
|
||||||
class DocumentTypeMetadataTypeSerializer(serializers.HyperlinkedModelSerializer):
|
class MetadataTypeDocumentTypeRelationSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
document_type = DocumentTypeSerializer(read_only=True)
|
document_type = DocumentTypeSerializer(read_only=True)
|
||||||
metadata_type = MetadataTypeSerializer(read_only=True)
|
url = MultiKwargHyperlinkedIdentityField(
|
||||||
url = serializers.SerializerMethodField()
|
view_kwargs=(
|
||||||
|
{
|
||||||
|
'lookup_field': 'metadata_type_id',
|
||||||
|
'lookup_url_kwarg': 'metadata_type_id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'lookup_field': 'pk',
|
||||||
|
'lookup_url_kwarg': 'metadata_type_document_type_relation_id',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
view_name='rest_api:metadata_type-document_type_relation-detail'
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ('document_type', 'id', 'metadata_type', 'required', 'url')
|
fields = ('document_type', 'id', 'required', 'url')
|
||||||
model = DocumentTypeMetadataType
|
model = DocumentTypeMetadataType
|
||||||
|
|
||||||
def get_url(self, instance):
|
|
||||||
return reverse(
|
|
||||||
viewname='rest_api:documenttypemetadatatype-detail', kwargs={
|
|
||||||
'document_type_pk': instance.document_type.pk, 'metadata_type': instance.pk
|
|
||||||
}, request=self.context['request'], format=self.context['format']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
class MetadataTypeDocumentTypeRelationAddRemoveSerializer(ExternalObjectListSerializerMixin, serializers.Serializer):
|
||||||
class NewDocumentTypeMetadataTypeSerializer(serializers.ModelSerializer):
|
document_type_id_list = serializers.CharField(
|
||||||
metadata_type_pk = serializers.IntegerField(
|
help_text=_(
|
||||||
help_text=_('Primary key of the metadata type to be added.'),
|
'Comma separated list of document type primary keys that will be '
|
||||||
write_only=True
|
'added or removed.'
|
||||||
|
), label=_('Document Type ID list'), required=False, write_only=True
|
||||||
|
)
|
||||||
|
required = serializers.BooleanField(
|
||||||
|
label=_('Required'), required=False, write_only=True
|
||||||
)
|
)
|
||||||
url = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = (
|
external_object_list_model = DocumentType
|
||||||
'id', 'metadata_type_pk', 'required', 'url'
|
external_object_list_permission = permission_document_type_edit
|
||||||
)
|
external_object_list_pk_list_field = 'document_type_id_list'
|
||||||
model = DocumentTypeMetadataType
|
|
||||||
|
|
||||||
def get_url(self, instance):
|
def document_type_relations_add(self, instance):
|
||||||
return reverse(
|
instance.document_types_add(
|
||||||
viewname='rest_api:documenttypemetadatatype-detail', kwargs={
|
queryset=self.get_external_object_list(),
|
||||||
'document_type': instance.document_type.pk, 'metadata_type': instance.pk
|
required=self.validated_data['required'],
|
||||||
}, request=self.context['request'], format=self.context['format']
|
_user=self.context['request'].user
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate(self, attrs):
|
def document_type_relations_remove(self, instance):
|
||||||
attrs['document_type'] = self.context['document_type']
|
instance.document_types_remove(
|
||||||
attrs['metadata_type'] = MetadataType.objects.get(
|
queryset=self.get_external_object_list(),
|
||||||
pk=attrs.pop('metadata_type_pk')
|
_user=self.context['request'].user
|
||||||
)
|
|
||||||
|
|
||||||
instance = DocumentTypeMetadataType(**attrs)
|
|
||||||
try:
|
|
||||||
instance.full_clean()
|
|
||||||
except DjangoValidationError as exception:
|
|
||||||
raise ValidationError(exception)
|
|
||||||
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
|
|
||||||
class WritableDocumentTypeMetadataTypeSerializer(serializers.ModelSerializer):
|
|
||||||
url = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
fields = (
|
|
||||||
'id', 'required', 'url'
|
|
||||||
)
|
|
||||||
model = DocumentTypeMetadataType
|
|
||||||
|
|
||||||
def get_url(self, instance):
|
|
||||||
return reverse(
|
|
||||||
viewname='rest_api:documenttypemetadatatype-detail', kwargs={
|
|
||||||
'document_type_pk': instance.document_type.pk,
|
|
||||||
'metadata_type': instance.pk
|
|
||||||
}, request=self.context['request'], format=self.context['format']
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DocumentMetadataSerializer(serializers.HyperlinkedModelSerializer):
|
class DocumentMetadataSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
document = DocumentSerializer(read_only=True)
|
document = DocumentSerializer(read_only=True)
|
||||||
metadata_type = MetadataTypeSerializer(read_only=True)
|
metadata_type = MetadataTypeSerializer(read_only=True)
|
||||||
url = serializers.SerializerMethodField()
|
url = MultiKwargHyperlinkedIdentityField(
|
||||||
|
view_kwargs=(
|
||||||
|
{
|
||||||
|
'lookup_field': 'document_id',
|
||||||
|
'lookup_url_kwarg': 'document_id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'lookup_field': 'pk',
|
||||||
|
'lookup_url_kwarg': 'document_metadata_id',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
view_name='rest_api:document-metadata-detail'
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ('document', 'id', 'metadata_type', 'url', 'value')
|
fields = ('document', 'id', 'metadata_type', 'url', 'value')
|
||||||
model = DocumentMetadata
|
model = DocumentMetadata
|
||||||
read_only_fields = ('document', 'metadata_type',)
|
|
||||||
|
|
||||||
def get_url(self, instance):
|
|
||||||
return reverse(
|
|
||||||
viewname='rest_api:documentmetadata-detail', kwargs={
|
|
||||||
'document_pk': instance.document.pk, 'metadata_pk': instance.pk
|
|
||||||
}, request=self.context['request'], format=self.context['format']
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate(self, attrs):
|
|
||||||
self.instance.value = attrs['value']
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.instance.full_clean()
|
|
||||||
except DjangoValidationError as exception:
|
|
||||||
raise ValidationError(exception)
|
|
||||||
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
|
|
||||||
class NewDocumentMetadataSerializer(serializers.ModelSerializer):
|
class DocumentMetadataAddSerializer(DocumentMetadataSerializer):
|
||||||
metadata_type_pk = serializers.IntegerField(
|
metadata_type = FilteredPrimaryKeyRelatedField(
|
||||||
help_text=_(
|
source_model=MetadataType, source_permission=permission_metadata_add,
|
||||||
'Primary key of the metadata type to be added to the document.'
|
|
||||||
),
|
|
||||||
write_only=True
|
write_only=True
|
||||||
)
|
)
|
||||||
url = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta(DocumentMetadataSerializer.Meta):
|
||||||
fields = ('id', 'metadata_type_pk', 'url', 'value')
|
read_only_fields = ('document',)
|
||||||
model = DocumentMetadata
|
|
||||||
|
|
||||||
def get_url(self, instance):
|
def create(self, validated_data):
|
||||||
return reverse(
|
validated_data['document'] = self.context['document']
|
||||||
viewname='rest_api:documentmetadata-detail', kwargs={
|
|
||||||
'document_pk': instance.document.pk, 'metadata_pk': instance.pk
|
return super(DocumentMetadataAddSerializer, self).create(
|
||||||
}, request=self.context['request'], format=self.context['format']
|
validated_data=validated_data
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
attrs['document'] = self.context['document']
|
attrs['document'] = self.context['document']
|
||||||
attrs['metadata_type'] = MetadataType.objects.get(
|
|
||||||
pk=attrs.pop('metadata_type_pk')
|
|
||||||
)
|
|
||||||
|
|
||||||
instance = DocumentMetadata(**attrs)
|
instance = DocumentMetadata(**attrs)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
instance.full_clean()
|
instance.full_clean()
|
||||||
except DjangoValidationError as exception:
|
except DjangoValidationError as exception:
|
||||||
raise ValidationError(exception)
|
raise ValidationError(
|
||||||
|
{
|
||||||
|
api_settings.NON_FIELD_ERRORS_KEY: exception.messages
|
||||||
|
}, code='invalid'
|
||||||
|
)
|
||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ TEST_DEFAULT_VALUE = 'test'
|
|||||||
TEST_INCORRECT_LOOKUP_VALUE = '0'
|
TEST_INCORRECT_LOOKUP_VALUE = '0'
|
||||||
TEST_INVALID_DATE = '___________'
|
TEST_INVALID_DATE = '___________'
|
||||||
TEST_LOOKUP_TEMPLATE = '1,2,3'
|
TEST_LOOKUP_TEMPLATE = '1,2,3'
|
||||||
|
TEST_METADATA_TYPE_INVALID_LOOKUP = 'invalid,lookup,values,on,purpose'
|
||||||
TEST_METADATA_TYPE_LABEL = 'test metadata type'
|
TEST_METADATA_TYPE_LABEL = 'test metadata type'
|
||||||
TEST_METADATA_TYPE_LABEL_2 = 'test metadata type label 2'
|
TEST_METADATA_TYPE_LABEL_2 = 'test metadata type label 2'
|
||||||
TEST_METADATA_TYPE_LABEL_EDITED = 'test metadata type label edited'
|
TEST_METADATA_TYPE_LABEL_EDITED = 'test metadata type label edited'
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,9 @@ from .mixins import MetadataTypeTestMixin
|
|||||||
class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
|
class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(MetadataTestCase, self).setUp()
|
super(MetadataTestCase, self).setUp()
|
||||||
self.document_type.metadata.create(metadata_type=self.metadata_type)
|
self.document_type.metadata_type_relations.create(
|
||||||
|
metadata_type=self.metadata_type
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_default(self):
|
def test_no_default(self):
|
||||||
document_metadata = DocumentMetadata(
|
document_metadata = DocumentMetadata(
|
||||||
@@ -146,13 +148,13 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_required_metadata(self):
|
def test_required_metadata(self):
|
||||||
self.document_type.metadata.all().delete()
|
self.document_type.metadata_type_relations.all().delete()
|
||||||
|
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.metadata_type.get_required_for(self.document_type)
|
self.metadata_type.get_required_for(self.document_type)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.document_type.metadata.create(
|
self.document_type.metadata_type_relations.create(
|
||||||
metadata_type=self.metadata_type, required=False
|
metadata_type=self.metadata_type, required=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -160,9 +162,9 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
|
|||||||
self.metadata_type.get_required_for(self.document_type)
|
self.metadata_type.get_required_for(self.document_type)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.document_type.metadata.all().delete()
|
self.document_type.metadata_type_relations.all().delete()
|
||||||
|
|
||||||
self.document_type.metadata.create(
|
self.document_type.metadata_type_relations.create(
|
||||||
metadata_type=self.metadata_type, required=True
|
metadata_type=self.metadata_type, required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -198,7 +200,7 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
|
|||||||
label=TEST_DOCUMENT_TYPE_2_LABEL
|
label=TEST_DOCUMENT_TYPE_2_LABEL
|
||||||
)
|
)
|
||||||
|
|
||||||
self.document_type_2.metadata.create(
|
self.document_type_2.metadata_type_relations.create(
|
||||||
metadata_type=self.metadata_type, required=True
|
metadata_type=self.metadata_type, required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -226,7 +228,9 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
|
|||||||
label=TEST_DOCUMENT_TYPE_2_LABEL
|
label=TEST_DOCUMENT_TYPE_2_LABEL
|
||||||
)
|
)
|
||||||
|
|
||||||
self.document_type_2.metadata.create(metadata_type=self.metadata_type)
|
self.document_type_2.metadata_type_relations.create(
|
||||||
|
metadata_type=self.metadata_type
|
||||||
|
)
|
||||||
|
|
||||||
self.document.set_document_type(document_type=self.document_type_2)
|
self.document.set_document_type(document_type=self.document_type_2)
|
||||||
|
|
||||||
@@ -276,7 +280,7 @@ class MetadataTestCase(DocumentTestMixin, MetadataTypeTestMixin, BaseTestCase):
|
|||||||
label=TEST_DOCUMENT_TYPE_2_LABEL
|
label=TEST_DOCUMENT_TYPE_2_LABEL
|
||||||
)
|
)
|
||||||
|
|
||||||
self.document_type_2.metadata.create(
|
self.document_type_2.metadata_type_relations.create(
|
||||||
metadata_type=self.metadata_type, required=True
|
metadata_type=self.metadata_type, required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,9 @@ class DocumentMetadataViewTestCase(MetadataTestsMixin, GenericDocumentViewTestCa
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(DocumentMetadataViewTestCase, self).setUp()
|
super(DocumentMetadataViewTestCase, self).setUp()
|
||||||
self._create_metadata_type()
|
self._create_metadata_type()
|
||||||
self.document_type.metadata.create(metadata_type=self.metadata_type)
|
self.document_type.metadata_type_relations.create(
|
||||||
|
metadata_type=self.metadata_type
|
||||||
|
)
|
||||||
|
|
||||||
def _request_document_metadata_add_get_view(self):
|
def _request_document_metadata_add_get_view(self):
|
||||||
return self.get(
|
return self.get(
|
||||||
@@ -76,7 +78,9 @@ class DocumentMetadataViewTestCase(MetadataTestsMixin, GenericDocumentViewTestCa
|
|||||||
)
|
)
|
||||||
|
|
||||||
self._create_document_type_random()
|
self._create_document_type_random()
|
||||||
self.test_document_type.metadata.create(metadata_type=self.metadata_type)
|
self.test_document_type.metadata_type_relations.create(
|
||||||
|
metadata_type=self.metadata_type
|
||||||
|
)
|
||||||
self._create_document()
|
self._create_document()
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
obj=self.test_document, permission=permission_metadata_add
|
obj=self.test_document, permission=permission_metadata_add
|
||||||
@@ -94,7 +98,9 @@ class DocumentMetadataViewTestCase(MetadataTestsMixin, GenericDocumentViewTestCa
|
|||||||
)
|
)
|
||||||
|
|
||||||
self._create_document_type_random()
|
self._create_document_type_random()
|
||||||
self.test_document_type.metadata.create(metadata_type=self.metadata_type)
|
self.test_document_type.metadata_type_relations.create(
|
||||||
|
metadata_type=self.metadata_type
|
||||||
|
)
|
||||||
self._create_document()
|
self._create_document()
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
obj=self.test_document, permission=permission_metadata_add
|
obj=self.test_document, permission=permission_metadata_add
|
||||||
@@ -112,7 +118,9 @@ class DocumentMetadataViewTestCase(MetadataTestsMixin, GenericDocumentViewTestCa
|
|||||||
)
|
)
|
||||||
|
|
||||||
self._create_document_type_random()
|
self._create_document_type_random()
|
||||||
self.test_document_type.metadata.create(metadata_type=self.metadata_type)
|
self.test_document_type.metadata_type_relations.create(
|
||||||
|
metadata_type=self.metadata_type
|
||||||
|
)
|
||||||
self._create_document()
|
self._create_document()
|
||||||
self.id_list.append(self.test_document.pk)
|
self.id_list.append(self.test_document.pk)
|
||||||
self.grant_access(
|
self.grant_access(
|
||||||
@@ -159,7 +167,7 @@ class DocumentMetadataViewTestCase(MetadataTestsMixin, GenericDocumentViewTestCa
|
|||||||
name=TEST_METADATA_TYPE_NAME_2, label=TEST_METADATA_TYPE_LABEL_2
|
name=TEST_METADATA_TYPE_NAME_2, label=TEST_METADATA_TYPE_LABEL_2
|
||||||
)
|
)
|
||||||
|
|
||||||
document_metadata_2 = document_type_2.metadata.create(
|
document_metadata_2 = document_type_2.metadata_type_relations.create(
|
||||||
metadata_type=metadata_type_2, required=True
|
metadata_type=metadata_type_2, required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -400,7 +408,7 @@ class DocumentMetadataViewTestCase(MetadataTestsMixin, GenericDocumentViewTestCa
|
|||||||
name=TEST_METADATA_TYPE_NAME_2, label=TEST_METADATA_TYPE_LABEL_2
|
name=TEST_METADATA_TYPE_NAME_2, label=TEST_METADATA_TYPE_LABEL_2
|
||||||
)
|
)
|
||||||
|
|
||||||
self.document_type.metadata.create(
|
self.document_type.metadata_type_relations.create(
|
||||||
metadata_type=metadata_type_2
|
metadata_type=metadata_type_2
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -540,7 +548,7 @@ class MetadataTypeViewViewTestCase(DocumentTestMixin, MetadataTestsMixin, Generi
|
|||||||
|
|
||||||
self.document_type.refresh_from_db()
|
self.document_type.refresh_from_db()
|
||||||
|
|
||||||
self.assertEqual(self.document_type.metadata.count(), 0)
|
self.assertEqual(self.document_type.metadata_type_relations.count(), 0)
|
||||||
|
|
||||||
def test_metadata_type_relationship_view_with_document_type_access(self):
|
def test_metadata_type_relationship_view_with_document_type_access(self):
|
||||||
self._create_metadata_type()
|
self._create_metadata_type()
|
||||||
@@ -556,7 +564,7 @@ class MetadataTypeViewViewTestCase(DocumentTestMixin, MetadataTestsMixin, Generi
|
|||||||
|
|
||||||
self.document_type.refresh_from_db()
|
self.document_type.refresh_from_db()
|
||||||
|
|
||||||
self.assertEqual(self.document_type.metadata.count(), 0)
|
self.assertEqual(self.document_type.metadata_type_relations.count(), 0)
|
||||||
|
|
||||||
def test_metadata_type_relationship_view_with_metadata_type_access(self):
|
def test_metadata_type_relationship_view_with_metadata_type_access(self):
|
||||||
self._create_metadata_type()
|
self._create_metadata_type()
|
||||||
@@ -573,7 +581,7 @@ class MetadataTypeViewViewTestCase(DocumentTestMixin, MetadataTestsMixin, Generi
|
|||||||
|
|
||||||
self.document_type.refresh_from_db()
|
self.document_type.refresh_from_db()
|
||||||
|
|
||||||
self.assertEqual(self.document_type.metadata.count(), 0)
|
self.assertEqual(self.document_type.metadata_type_relations.count(), 0)
|
||||||
|
|
||||||
def test_metadata_type_relationship_view_with_metadata_type_and_document_type_access(self):
|
def test_metadata_type_relationship_view_with_metadata_type_and_document_type_access(self):
|
||||||
self._create_metadata_type()
|
self._create_metadata_type()
|
||||||
@@ -594,8 +602,9 @@ class MetadataTypeViewViewTestCase(DocumentTestMixin, MetadataTestsMixin, Generi
|
|||||||
self.document_type.refresh_from_db()
|
self.document_type.refresh_from_db()
|
||||||
|
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
qs=self.document_type.metadata.values('metadata_type', 'required'),
|
qs=self.document_type.metadata_type_relations.values(
|
||||||
values=[
|
'metadata_type', 'required'
|
||||||
|
), values=[
|
||||||
{
|
{
|
||||||
'metadata_type': self.metadata_type.pk,
|
'metadata_type': self.metadata_type.pk,
|
||||||
'required': True,
|
'required': True,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class DocumentUploadMetadataTestCase(MetadataTypeTestMixin, GenericDocumentViewT
|
|||||||
|
|
||||||
self.document.delete()
|
self.document.delete()
|
||||||
|
|
||||||
self.document_type.metadata.create(
|
self.document_type.metadata_type_relations.create(
|
||||||
metadata_type=self.metadata_type, required=True
|
metadata_type=self.metadata_type, required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,14 @@ from __future__ import unicode_literals
|
|||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from .api_views import (
|
from .api_views import (
|
||||||
APIDocumentMetadataListView, APIDocumentMetadataView,
|
DocumentMetadataAPIViewSet, MetadataTypeAPIViewSet,
|
||||||
APIDocumentTypeMetadataTypeListView, APIDocumentTypeMetadataTypeView,
|
MetadataTypeDocumentTypeRelationAPIViewSet
|
||||||
APIMetadataTypeListView, APIMetadataTypeView
|
|
||||||
)
|
)
|
||||||
from .views import (
|
from .views import (
|
||||||
DocumentMetadataAddView, DocumentMetadataEditView,
|
DocumentMetadataAddView, DocumentMetadataEditView,
|
||||||
DocumentMetadataListView, DocumentMetadataRemoveView,
|
DocumentMetadataListView, DocumentMetadataRemoveView,
|
||||||
MetadataTypeCreateView, MetadataTypeDeleteView, MetadataTypeEditView,
|
DocumentTypeMetadataTypes, MetadataTypeCreateView, MetadataTypeDeleteView,
|
||||||
MetadataTypeListView, SetupDocumentTypeMetadataTypes,
|
MetadataTypesDocumentTypes, MetadataTypeEditView, MetadataTypeListView
|
||||||
SetupMetadataTypesDocumentTypes
|
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@@ -35,12 +33,12 @@ urlpatterns = [
|
|||||||
url(
|
url(
|
||||||
regex=r'^metadata_types/(?P<metadata_type_id>\d+)/document_types/$',
|
regex=r'^metadata_types/(?P<metadata_type_id>\d+)/document_types/$',
|
||||||
name='metadata_type_document_types',
|
name='metadata_type_document_types',
|
||||||
view=SetupMetadataTypesDocumentTypes.as_view()
|
view=MetadataTypesDocumentTypes.as_view()
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
regex=r'^document_types/(?P<document_type_id>\d+)/metadata_types/$',
|
regex=r'^document_types/(?P<document_type_id>\d+)/metadata_types/$',
|
||||||
name='document_type_metadata_types',
|
name='document_type_metadata_types',
|
||||||
view=SetupDocumentTypeMetadataTypes.as_view()
|
view=DocumentTypeMetadataTypes.as_view()
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
regex=r'^documents/(?P<document_id>\d+)/edit/$',
|
regex=r'^documents/(?P<document_id>\d+)/edit/$',
|
||||||
@@ -77,34 +75,18 @@ urlpatterns = [
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
api_urls = [
|
api_router_entries = (
|
||||||
url(
|
{
|
||||||
regex=r'^metadata_types/$', name='metadatatype-list',
|
'prefix': r'metadata_types', 'viewset': MetadataTypeAPIViewSet,
|
||||||
view=APIMetadataTypeListView.as_view()
|
'basename': 'metadata_type'
|
||||||
),
|
},
|
||||||
url(
|
{
|
||||||
regex=r'^metadata_types/(?P<metadata_type_id>\d+)/$',
|
'prefix': r'metadata_types/(?P<metadata_type_id>[^/.]+)/document_type_relations',
|
||||||
name='metadatatype-detail',
|
'viewset': MetadataTypeDocumentTypeRelationAPIViewSet,
|
||||||
view=APIMetadataTypeView.as_view()
|
'basename': 'metadata_type-document_type_relation'
|
||||||
),
|
},
|
||||||
url(
|
{
|
||||||
regex=r'^document_types/(?P<document_type_id>\d+)/metadata_types/$',
|
'prefix': r'documents/(?P<document_id>[^/.]+)/metadata',
|
||||||
name='documenttypemetadatatype-list',
|
'viewset': DocumentMetadataAPIViewSet, 'basename': 'document-metadata'
|
||||||
view=APIDocumentTypeMetadataTypeListView.as_view()
|
}
|
||||||
),
|
)
|
||||||
url(
|
|
||||||
regex=r'^document_types/(?P<document_type_id>\d+)/metadata_types/(?P<metadata_type_id>\d+)/$',
|
|
||||||
name='documenttypemetadatatype-detail',
|
|
||||||
view=APIDocumentTypeMetadataTypeView.as_view()
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
regex=r'^documents/(?P<document_id>\d+)/metadata/$',
|
|
||||||
name='documentmetadata-list',
|
|
||||||
view=APIDocumentMetadataListView.as_view()
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
regex=r'^documents/(?P<document_id>\d+)/metadata/(?P<metadata_id>\d+)/$',
|
|
||||||
name='documentmetadata-detail',
|
|
||||||
view=APIDocumentMetadataView.as_view()
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -564,7 +564,7 @@ class MetadataTypeListView(SingleObjectListView):
|
|||||||
return MetadataType.objects.all()
|
return MetadataType.objects.all()
|
||||||
|
|
||||||
|
|
||||||
class SetupDocumentTypeMetadataTypes(ExternalObjectMixin, FormView):
|
class DocumentTypeMetadataTypes(ExternalObjectMixin, FormView):
|
||||||
external_object_class = DocumentType
|
external_object_class = DocumentType
|
||||||
external_object_permission = permission_metadata_type_edit
|
external_object_permission = permission_metadata_type_edit
|
||||||
external_object_pk_url_kwarg = 'document_type_id'
|
external_object_pk_url_kwarg = 'document_type_id'
|
||||||
@@ -590,7 +590,7 @@ class SetupDocumentTypeMetadataTypes(ExternalObjectMixin, FormView):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return super(
|
return super(
|
||||||
SetupDocumentTypeMetadataTypes, self
|
DocumentTypeMetadataTypes, self
|
||||||
).form_valid(form=form)
|
).form_valid(form=form)
|
||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
@@ -640,7 +640,7 @@ class SetupDocumentTypeMetadataTypes(ExternalObjectMixin, FormView):
|
|||||||
return reverse(viewname='documents:document_type_list')
|
return reverse(viewname='documents:document_type_list')
|
||||||
|
|
||||||
|
|
||||||
class SetupMetadataTypesDocumentTypes(SetupDocumentTypeMetadataTypes):
|
class MetadataTypesDocumentTypes(DocumentTypeMetadataTypes):
|
||||||
external_object_class = MetadataType
|
external_object_class = MetadataType
|
||||||
external_object_permission = permission_metadata_type_edit
|
external_object_permission = permission_metadata_type_edit
|
||||||
external_object_pk_url_kwarg = 'metadata_type_id'
|
external_object_pk_url_kwarg = 'metadata_type_id'
|
||||||
@@ -651,10 +651,10 @@ class SetupMetadataTypesDocumentTypes(SetupDocumentTypeMetadataTypes):
|
|||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
return {
|
return {
|
||||||
'form_display_mode_table': True,
|
'form_display_mode_table': True,
|
||||||
'object': self.get_object(),
|
'object': self.external_object,
|
||||||
'title': _(
|
'title': _(
|
||||||
'Document types for metadata type: %s'
|
'Document types for metadata type: %s'
|
||||||
) % self.get_object()
|
) % self.external_object,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
|
|||||||
@@ -3,9 +3,23 @@ from __future__ import absolute_import, unicode_literals
|
|||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
from mayan.apps.acls.models import AccessControlList
|
from mayan.apps.acls.models import AccessControlList
|
||||||
|
from mayan.apps.common.mixins import ExternalObjectMixin
|
||||||
|
|
||||||
|
|
||||||
|
class ExternalObjectAPIViewSetMixin(ExternalObjectMixin):
|
||||||
|
"""Override get_external_object to use REST API get_object_or_404"""
|
||||||
|
def dispatch(self, *args, **kwargs):
|
||||||
|
return super(ExternalObjectMixin, self).dispatch(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_external_object(self):
|
||||||
|
return get_object_or_404(
|
||||||
|
queryset=self.get_external_object_queryset_filtered(),
|
||||||
|
**self.get_pk_url_kwargs()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ExternalObjectListSerializerMixin(object):
|
class ExternalObjectListSerializerMixin(object):
|
||||||
@@ -127,6 +141,7 @@ class ExternalObjectSerializerMixin(object):
|
|||||||
external_object_permission
|
external_object_permission
|
||||||
external_object_queryset
|
external_object_queryset
|
||||||
external_object_pk_field
|
external_object_pk_field
|
||||||
|
external_object_pk_type
|
||||||
The source queryset can also be provided overriding the
|
The source queryset can also be provided overriding the
|
||||||
.get_external_object_queryset() method.
|
.get_external_object_queryset() method.
|
||||||
"""
|
"""
|
||||||
@@ -157,7 +172,19 @@ class ExternalObjectSerializerMixin(object):
|
|||||||
else:
|
else:
|
||||||
pk_field_value = None
|
pk_field_value = None
|
||||||
|
|
||||||
|
pk_type = self.get_external_object_option('pk_type')
|
||||||
|
|
||||||
if pk_field_value:
|
if pk_field_value:
|
||||||
|
if pk_type:
|
||||||
|
try:
|
||||||
|
pk_field_value = pk_type(pk_field_value)
|
||||||
|
except Exception as exception:
|
||||||
|
raise ValidationError(
|
||||||
|
{
|
||||||
|
pk_field: [exception]
|
||||||
|
}, code='invalid'
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return queryset.get(pk=pk_field_value)
|
return queryset.get(pk=pk_field_value)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals
|
|||||||
|
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
|
||||||
from rest_framework.permissions import BasePermission, IsAuthenticated
|
from rest_framework.permissions import BasePermission
|
||||||
|
|
||||||
from mayan.apps.permissions import Permission
|
from mayan.apps.permissions import Permission
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.generics import get_object_or_404
|
|
||||||
from rest_framework.reverse import reverse
|
|
||||||
|
|
||||||
|
|
||||||
class LazyExtraFieldsSerializerMixin(object):
|
class LazyExtraFieldsSerializerMixin(object):
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from rest_framework import viewsets
|
from rest_framework import mixins, viewsets
|
||||||
from rest_framework.settings import api_settings
|
|
||||||
|
|
||||||
from .filters import MayanViewSetObjectPermissionsFilter
|
from .filters import MayanViewSetObjectPermissionsFilter
|
||||||
from .mixins import SuccessHeadersMixin
|
from .mixins import SuccessHeadersMixin
|
||||||
@@ -26,3 +25,13 @@ class MayanAPIReadOnlyModelViewSet(SuccessHeadersMixin, viewsets.ReadOnlyModelVi
|
|||||||
class MayanAPIViewSet(SuccessHeadersMixin, viewsets.GenericViewSet):
|
class MayanAPIViewSet(SuccessHeadersMixin, viewsets.GenericViewSet):
|
||||||
filter_backends = (MayanViewSetObjectPermissionsFilter,)
|
filter_backends = (MayanViewSetObjectPermissionsFilter,)
|
||||||
permission_classes = (MayanViewSetPermission,)
|
permission_classes = (MayanViewSetPermission,)
|
||||||
|
|
||||||
|
|
||||||
|
class MayanRetrieveUpdateAPIViewSet(SuccessHeadersMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet):
|
||||||
|
filter_backends = (MayanViewSetObjectPermissionsFilter,)
|
||||||
|
permission_classes = (MayanViewSetPermission,)
|
||||||
|
|
||||||
|
|
||||||
|
class MayanRetrieveUpdateDestroyAPIViewSet(mixins.DestroyModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet):
|
||||||
|
filter_backends = (MayanViewSetObjectPermissionsFilter,)
|
||||||
|
permission_classes = (MayanViewSetPermission,)
|
||||||
|
|||||||
Reference in New Issue
Block a user