Improve tag serializer adding bulk document tagging on creation and editing.
Improve and add additiona tag API tests.
This commit is contained in:
@@ -21,11 +21,39 @@ from .permissions import (
|
||||
permission_tag_remove, permission_tag_view
|
||||
)
|
||||
from .serializers import (
|
||||
DocumentTagSerializer, NewDocumentTagSerializer, NewTagSerializer,
|
||||
TagSerializer
|
||||
DocumentTagSerializer, NewDocumentTagSerializer, TagSerializer,
|
||||
WritableTagSerializer
|
||||
)
|
||||
|
||||
|
||||
class APITagListView(generics.ListCreateAPIView):
|
||||
filter_backends = (MayanObjectPermissionsFilter,)
|
||||
mayan_object_permissions = {'GET': (permission_tag_view,)}
|
||||
mayan_view_permissions = {'POST': (permission_tag_create,)}
|
||||
permission_classes = (MayanPermission,)
|
||||
queryset = Tag.objects.all()
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.request.method == 'GET':
|
||||
return TagSerializer
|
||||
elif self.request.method == 'POST':
|
||||
return WritableTagSerializer
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
"""
|
||||
Returns a list of all the tags.
|
||||
"""
|
||||
|
||||
return super(APITagListView, self).get(*args, **kwargs)
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
"""
|
||||
Create a new tag.
|
||||
"""
|
||||
|
||||
return super(APITagListView, self).post(*args, **kwargs)
|
||||
|
||||
|
||||
class APITagView(generics.RetrieveUpdateDestroyAPIView):
|
||||
filter_backends = (MayanObjectPermissionsFilter,)
|
||||
mayan_object_permissions = {
|
||||
@@ -35,7 +63,6 @@ class APITagView(generics.RetrieveUpdateDestroyAPIView):
|
||||
'PUT': (permission_tag_edit,)
|
||||
}
|
||||
queryset = Tag.objects.all()
|
||||
serializer_class = TagSerializer
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
"""
|
||||
@@ -51,6 +78,12 @@ class APITagView(generics.RetrieveUpdateDestroyAPIView):
|
||||
|
||||
return super(APITagView, self).get(*args, **kwargs)
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.request.method == 'GET':
|
||||
return TagSerializer
|
||||
else:
|
||||
return WritableTagSerializer
|
||||
|
||||
def patch(self, *args, **kwargs):
|
||||
"""
|
||||
Edit the selected tag.
|
||||
@@ -66,34 +99,6 @@ class APITagView(generics.RetrieveUpdateDestroyAPIView):
|
||||
return super(APITagView, self).put(*args, **kwargs)
|
||||
|
||||
|
||||
class APITagListView(generics.ListCreateAPIView):
|
||||
filter_backends = (MayanObjectPermissionsFilter,)
|
||||
mayan_object_permissions = {'GET': (permission_tag_view,)}
|
||||
mayan_view_permissions = {'POST': (permission_tag_create,)}
|
||||
permission_classes = (MayanPermission,)
|
||||
queryset = Tag.objects.all()
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.request.method == 'GET':
|
||||
return TagSerializer
|
||||
elif self.request.method == 'POST':
|
||||
return NewTagSerializer
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
"""
|
||||
Returns a list of all the tags.
|
||||
"""
|
||||
|
||||
return super(APITagListView, self).get(*args, **kwargs)
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
"""
|
||||
Create a new tag.
|
||||
"""
|
||||
|
||||
return super(APITagListView, self).post(*args, **kwargs)
|
||||
|
||||
|
||||
class APITagDocumentListView(generics.ListAPIView):
|
||||
"""
|
||||
Returns a list of all the documents tagged by a particular tag.
|
||||
|
||||
@@ -8,6 +8,7 @@ from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from acls.models import AccessControlList
|
||||
from documents.models import Document
|
||||
from permissions import Permission
|
||||
|
||||
from .models import Tag
|
||||
@@ -15,7 +16,7 @@ from .permissions import permission_tag_attach
|
||||
|
||||
|
||||
class TagSerializer(serializers.HyperlinkedModelSerializer):
|
||||
documents = serializers.HyperlinkedIdentityField(
|
||||
documents_url = serializers.HyperlinkedIdentityField(
|
||||
view_name='rest_api:tag-document-list'
|
||||
)
|
||||
documents_count = serializers.SerializerMethodField()
|
||||
@@ -25,7 +26,7 @@ class TagSerializer(serializers.HyperlinkedModelSerializer):
|
||||
'url': {'view_name': 'rest_api:tag-detail'},
|
||||
}
|
||||
fields = (
|
||||
'color', 'documents', 'documents_count', 'id', 'label', 'url'
|
||||
'color', 'documents_count', 'documents_url', 'id', 'label', 'url'
|
||||
)
|
||||
model = Tag
|
||||
|
||||
@@ -33,13 +34,52 @@ class TagSerializer(serializers.HyperlinkedModelSerializer):
|
||||
return instance.documents.count()
|
||||
|
||||
|
||||
class NewTagSerializer(serializers.ModelSerializer):
|
||||
class WritableTagSerializer(serializers.ModelSerializer):
|
||||
documents_pk_list = serializers.CharField(
|
||||
help_text=_(
|
||||
'Comma separated list of document primary keys to which this tag '
|
||||
'will be attached.'
|
||||
), required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
fields = (
|
||||
'color', 'label', 'id'
|
||||
'color', 'documents_pk_list', 'id', 'label',
|
||||
)
|
||||
model = Tag
|
||||
|
||||
def _add_documents(self, documents_pk_list, instance):
|
||||
instance.documents.add(
|
||||
*Document.objects.filter(pk__in=documents_pk_list.split(','))
|
||||
)
|
||||
|
||||
def create(self, validated_data):
|
||||
documents_pk_list = validated_data.pop('documents_pk_list', '')
|
||||
|
||||
instance = super(WritableTagSerializer, self).create(validated_data)
|
||||
|
||||
if documents_pk_list:
|
||||
self._add_documents(
|
||||
documents_pk_list=documents_pk_list, instance=instance
|
||||
)
|
||||
|
||||
return instance
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
documents_pk_list = validated_data.pop('documents_pk_list', '')
|
||||
|
||||
instance = super(WritableTagSerializer, self).update(
|
||||
instance, validated_data
|
||||
)
|
||||
|
||||
if documents_pk_list:
|
||||
instance.documents.clear()
|
||||
self._add_documents(
|
||||
documents_pk_list=documents_pk_list, instance=instance
|
||||
)
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class NewDocumentTagSerializer(serializers.Serializer):
|
||||
tag = serializers.IntegerField(
|
||||
|
||||
@@ -20,6 +20,7 @@ from .literals import (
|
||||
)
|
||||
|
||||
|
||||
@override_settings(OCR_AUTO_OCR=False)
|
||||
class TagAPITestCase(APITestCase):
|
||||
"""
|
||||
Test the tag API endpoints
|
||||
@@ -37,6 +38,20 @@ class TagAPITestCase(APITestCase):
|
||||
|
||||
def tearDown(self):
|
||||
self.admin_user.delete()
|
||||
if hasattr(self, 'document_type'):
|
||||
self.document_type.delete()
|
||||
|
||||
def _document_create(self):
|
||||
self.document_type = DocumentType.objects.create(
|
||||
label=TEST_DOCUMENT_TYPE
|
||||
)
|
||||
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
|
||||
document = self.document_type.new_document(
|
||||
file_object=file_object,
|
||||
)
|
||||
|
||||
return document
|
||||
|
||||
def test_tag_create(self):
|
||||
response = self.client.post(
|
||||
@@ -46,7 +61,22 @@ class TagAPITestCase(APITestCase):
|
||||
)
|
||||
|
||||
tag = Tag.objects.first()
|
||||
self.assertEqual(response.data['id'], tag.pk)
|
||||
self.assertEqual(response.data['label'], TEST_TAG_LABEL)
|
||||
self.assertEqual(response.data['color'], TEST_TAG_COLOR)
|
||||
|
||||
self.assertEqual(Tag.objects.count(), 1)
|
||||
self.assertEqual(tag.label, TEST_TAG_LABEL)
|
||||
self.assertEqual(tag.color, TEST_TAG_COLOR)
|
||||
|
||||
def test_tag_create_with_documents(self):
|
||||
response = self.client.post(
|
||||
reverse('rest_api:tag-list'), {
|
||||
'label': TEST_TAG_LABEL, 'color': TEST_TAG_COLOR
|
||||
}
|
||||
)
|
||||
|
||||
tag = Tag.objects.first()
|
||||
self.assertEqual(response.data['id'], tag.pk)
|
||||
self.assertEqual(response.data['label'], TEST_TAG_LABEL)
|
||||
self.assertEqual(response.data['color'], TEST_TAG_COLOR)
|
||||
@@ -62,7 +92,23 @@ class TagAPITestCase(APITestCase):
|
||||
|
||||
self.assertEqual(Tag.objects.count(), 0)
|
||||
|
||||
def test_tag_edit(self):
|
||||
def test_tag_edit_via_patch(self):
|
||||
tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL)
|
||||
|
||||
self.client.patch(
|
||||
reverse('rest_api:tag-detail', args=(tag.pk,)),
|
||||
{
|
||||
'label': TEST_TAG_LABEL_EDITED,
|
||||
'color': TEST_TAG_COLOR_EDITED
|
||||
}
|
||||
)
|
||||
|
||||
tag = Tag.objects.first()
|
||||
|
||||
self.assertEqual(tag.label, TEST_TAG_LABEL_EDITED)
|
||||
self.assertEqual(tag.color, TEST_TAG_COLOR_EDITED)
|
||||
|
||||
def test_tag_edit_via_put(self):
|
||||
tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL)
|
||||
|
||||
self.client.put(
|
||||
@@ -78,18 +124,10 @@ class TagAPITestCase(APITestCase):
|
||||
self.assertEqual(tag.label, TEST_TAG_LABEL_EDITED)
|
||||
self.assertEqual(tag.color, TEST_TAG_COLOR_EDITED)
|
||||
|
||||
@override_settings(OCR_AUTO_OCR=False)
|
||||
def test_tag_add_document(self):
|
||||
def test_tag_document_add(self):
|
||||
tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL)
|
||||
|
||||
document_type = DocumentType.objects.create(
|
||||
label=TEST_DOCUMENT_TYPE
|
||||
)
|
||||
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
|
||||
document = document_type.new_document(
|
||||
file_object=file_object,
|
||||
)
|
||||
document = self._document_create()
|
||||
|
||||
self.client.post(
|
||||
reverse('rest_api:document-tag-list', args=(document.pk,)),
|
||||
@@ -98,19 +136,10 @@ class TagAPITestCase(APITestCase):
|
||||
|
||||
self.assertEqual(tag.documents.count(), 1)
|
||||
|
||||
@override_settings(OCR_AUTO_OCR=False)
|
||||
def test_tag_remove_document(self):
|
||||
def test_tag_document_remove(self):
|
||||
tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL)
|
||||
|
||||
document_type = DocumentType.objects.create(
|
||||
label=TEST_DOCUMENT_TYPE
|
||||
)
|
||||
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
|
||||
document = document_type.new_document(
|
||||
file_object=file_object,
|
||||
)
|
||||
|
||||
document = self._document_create()
|
||||
tag.documents.add(document)
|
||||
|
||||
self.client.delete(
|
||||
|
||||
Reference in New Issue
Block a user