Improve the document tag serializer. Add document tag detail view.
Add more API tests. Tweak URLs to conform with API design best practices.
This commit is contained in:
@@ -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())
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -61,11 +61,11 @@ api_urls = patterns(
|
||||
url(r'^tags/(?P<pk>[0-9]+)/$', APITagView.as_view(), name='tag-detail'),
|
||||
url(r'^tags/$', APITagListView.as_view(), name='tag-list'),
|
||||
url(
|
||||
r'^document/(?P<pk>[0-9]+)/tags/$', APIDocumentTagListView.as_view(),
|
||||
name='document-tag-list'
|
||||
r'^documents/(?P<document_pk>[0-9]+)/tags/$',
|
||||
APIDocumentTagListView.as_view(), name='document-tag-list'
|
||||
),
|
||||
url(
|
||||
r'^document/(?P<document_pk>[0-9]+)/tags/(?P<pk>[0-9]+)/$',
|
||||
APIDocumentTagView.as_view(), name='document-tag'
|
||||
r'^documents/(?P<document_pk>[0-9]+)/tags/(?P<pk>[0-9]+)/$',
|
||||
APIDocumentTagView.as_view(), name='document-tag-detail'
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user