Improve tag serializer adding bulk document tagging on creation and editing.

Improve and add additiona tag API tests.
This commit is contained in:
Roberto Rosario
2017-02-07 22:06:03 -04:00
parent 7340989dc5
commit 10e106ba83
3 changed files with 131 additions and 57 deletions

View File

@@ -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.

View File

@@ -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(

View File

@@ -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(