diff --git a/mayan/apps/tags/api_views.py b/mayan/apps/tags/api_views.py index 87c37c49e1..41555a758c 100644 --- a/mayan/apps/tags/api_views.py +++ b/mayan/apps/tags/api_views.py @@ -17,8 +17,8 @@ from rest_api.permissions import MayanPermission from .models import Tag from .permissions import ( - permission_tag_create, permission_tag_delete, permission_tag_edit, - permission_tag_remove, permission_tag_view + permission_tag_attach, permission_tag_create, permission_tag_delete, + permission_tag_edit, permission_tag_remove, permission_tag_view ) from .serializers import ( DocumentTagSerializer, NewDocumentTagSerializer, TagSerializer, @@ -123,15 +123,21 @@ class APITagDocumentListView(generics.ListAPIView): class APIDocumentTagListView(generics.ListCreateAPIView): - """ - Returns a list of all the tags attached to a document. - """ - filter_backends = (MayanObjectPermissionsFilter,) - mayan_object_permissions = {'GET': (permission_tag_view,)} + mayan_object_permissions = { + 'GET': (permission_tag_view,), + 'POST': (permission_tag_attach,) + } + + def get(self, *args, **kwargs): + """ + Returns a list of all the tags attached to a document. + """ + + return super(APIDocumentTagListView, self).get(*args, **kwargs) def get_document(self): - return get_object_or_404(Document, pk=self.kwargs['pk']) + return get_object_or_404(Document, pk=self.kwargs['document_pk']) def get_queryset(self): document = self.get_document() @@ -146,6 +152,12 @@ class APIDocumentTagListView(generics.ListCreateAPIView): return document.attached_tags().all() + def get_serializer_class(self): + if self.request.method == 'GET': + return DocumentTagSerializer + elif self.request.method == 'POST': + return NewDocumentTagSerializer + def get_serializer_context(self): """ Extra context provided to the serializer class. @@ -157,12 +169,6 @@ class APIDocumentTagListView(generics.ListCreateAPIView): 'view': self } - def get_serializer_class(self): - if self.request.method == 'GET': - return DocumentTagSerializer - elif self.request.method == 'POST': - return NewDocumentTagSerializer - def perform_create(self, serializer): serializer.save(document=self.get_document()) diff --git a/mayan/apps/tags/serializers.py b/mayan/apps/tags/serializers.py index 2d78f5e9bb..da9265ff3e 100644 --- a/mayan/apps/tags/serializers.py +++ b/mayan/apps/tags/serializers.py @@ -81,14 +81,35 @@ class WritableTagSerializer(serializers.ModelSerializer): return instance +class DocumentTagSerializer(TagSerializer): + document_tag_url = serializers.SerializerMethodField( + help_text=_( + 'API URL pointing to a tag in relation to the document ' + 'attached to it. This URL is different than the canonical ' + 'tag URL.' + ) + ) + + class Meta(TagSerializer.Meta): + fields = TagSerializer.Meta.fields + ('document_tag_url',) + read_only_fields = TagSerializer.Meta.fields + + def get_document_tag_url(self, instance): + return reverse( + 'rest_api:document-tag-detail', args=( + self.context['document'].pk, instance.pk + ), request=self.context['request'], format=self.context['format'] + ) + + class NewDocumentTagSerializer(serializers.Serializer): - tag = serializers.IntegerField( + tag_pk = serializers.IntegerField( help_text=_('Primary key of the tag to be added.') ) def create(self, validated_data): try: - tag = Tag.objects.get(pk=validated_data['tag']) + tag = Tag.objects.get(pk=validated_data['tag_pk']) try: Permission.check_permissions( @@ -103,19 +124,4 @@ class NewDocumentTagSerializer(serializers.Serializer): except Exception as exception: raise ValidationError(exception) - return {'tag': tag.pk} - - -class DocumentTagSerializer(TagSerializer): - remove = serializers.SerializerMethodField() - - def get_remove(self, instance): - return reverse( - 'rest_api:document-tag', args=( - self.context['document'].pk, instance.pk, - ), request=self.context['request'], format=self.context['format'] - ) - - class Meta(TagSerializer.Meta): - fields = TagSerializer.Meta.fields + ('remove',) - read_only_fields = TagSerializer.Meta.fields + return {'tag_pk': tag.pk} diff --git a/mayan/apps/tags/tests/test_api.py b/mayan/apps/tags/tests/test_api.py index 072ab962f4..1beb3441b7 100644 --- a/mayan/apps/tags/tests/test_api.py +++ b/mayan/apps/tags/tests/test_api.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from django.contrib.auth import get_user_model from django.core.urlresolvers import reverse from django.test import override_settings +from django.utils.encoding import force_text from rest_framework.test import APITestCase @@ -92,6 +93,19 @@ class TagAPITestCase(APITestCase): self.assertEqual(Tag.objects.count(), 0) + def test_tag_document_list_view(self): + tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL) + document = self._document_create() + tag.documents.add(document) + + response = self.client.get( + reverse('rest_api:tag-document-list', args=(tag.pk,)) + ) + + self.assertEqual( + response.data['results'][0]['uuid'], force_text(document.uuid) + ) + def test_tag_edit_via_patch(self): tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL) @@ -124,26 +138,46 @@ class TagAPITestCase(APITestCase): self.assertEqual(tag.label, TEST_TAG_LABEL_EDITED) self.assertEqual(tag.color, TEST_TAG_COLOR_EDITED) - def test_tag_document_add(self): + def test_document_attach_tag_view(self): tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL) - document = self._document_create() - self.client.post( + response = self.client.post( reverse('rest_api:document-tag-list', args=(document.pk,)), - {'tag': tag.pk} + {'tag_pk': tag.pk} + ) + self.assertQuerysetEqual(document.tags.all(), (repr(tag),)) + + def test_document_tag_detail_view(self): + tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL) + document = self._document_create() + tag.documents.add(document) + + response = self.client.get( + reverse('rest_api:document-tag-detail', args=(document.pk, tag.pk)) ) - self.assertEqual(tag.documents.count(), 1) + self.assertEqual(response.data['label'], tag.label) - def test_tag_document_remove(self): + def test_document_tag_list_view(self): tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL) + document = self._document_create() + tag.documents.add(document) + response = self.client.get( + reverse('rest_api:document-tag-list', args=(document.pk,)) + ) + self.assertEqual(response.data['results'][0]['label'], tag.label) + + def test_document_tag_remove_view(self): + tag = Tag.objects.create(color=TEST_TAG_COLOR, label=TEST_TAG_LABEL) document = self._document_create() tag.documents.add(document) self.client.delete( - reverse('rest_api:document-tag', args=(document.pk, tag.pk)), + reverse( + 'rest_api:document-tag-detail', args=(document.pk, tag.pk) + ), ) self.assertEqual(tag.documents.count(), 0) diff --git a/mayan/apps/tags/urls.py b/mayan/apps/tags/urls.py index 0ee9d5f19f..83223389e0 100644 --- a/mayan/apps/tags/urls.py +++ b/mayan/apps/tags/urls.py @@ -61,11 +61,11 @@ api_urls = patterns( url(r'^tags/(?P[0-9]+)/$', APITagView.as_view(), name='tag-detail'), url(r'^tags/$', APITagListView.as_view(), name='tag-list'), url( - r'^document/(?P[0-9]+)/tags/$', APIDocumentTagListView.as_view(), - name='document-tag-list' + r'^documents/(?P[0-9]+)/tags/$', + APIDocumentTagListView.as_view(), name='document-tag-list' ), url( - r'^document/(?P[0-9]+)/tags/(?P[0-9]+)/$', - APIDocumentTagView.as_view(), name='document-tag' + r'^documents/(?P[0-9]+)/tags/(?P[0-9]+)/$', + APIDocumentTagView.as_view(), name='document-tag-detail' ), )