Skip to content

Commit ba985ef

Browse files
author
Leifur Halldor Asgeirsson
committed
Merge stashed changes
1 parent a1f5095 commit ba985ef

File tree

6 files changed

+171
-2
lines changed

6 files changed

+171
-2
lines changed

example/tests/test_serializers.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from django.test import TestCase
2+
from django.utils import timezone
3+
4+
from rest_framework_json_api.utils import format_relation_name
5+
from rest_framework_json_api.serializers import ResourceIdentifierObjectSerializer
6+
7+
from example.models import Blog, Entry, Author
8+
9+
10+
class TestResourceIdentifierObjectSerializer(TestCase):
11+
def setUp(self):
12+
self.blog = Blog.objects.create(name='Some Blog', tagline="It's a blog")
13+
self.entry = Entry.objects.create(
14+
blog=self.blog,
15+
headline='headline',
16+
body_text='body_text',
17+
pub_date=timezone.now(),
18+
mod_date=timezone.now(),
19+
n_comments=0,
20+
n_pingbacks=0,
21+
rating=3
22+
)
23+
for i in range(1,6):
24+
name = 'some_author{}'.format(i)
25+
self.entry.authors.add(
26+
Author.objects.create(name=name, email='{}@example.org'.format(name))
27+
)
28+
29+
def test_data_in_correct_format_when_instantiated_with_blog_object(self):
30+
serializer = ResourceIdentifierObjectSerializer(instance=self.blog)
31+
32+
expected_data = {'type': format_relation_name('Blog'), 'id': str(self.blog.id)}
33+
34+
assert serializer.data == expected_data
35+
36+
def test_data_in_correct_format_when_instantiated_with_entry_object(self):
37+
serializer = ResourceIdentifierObjectSerializer(instance=self.entry)
38+
39+
expected_data = {'type': format_relation_name('Entry'), 'id': str(self.entry.id)}
40+
41+
assert serializer.data == expected_data
42+
43+
def test_deserialize_primitive_data_blog(self):
44+
initial_data = {
45+
'type': format_relation_name('Blog'),
46+
'id': str(self.blog.id)
47+
}
48+
serializer = ResourceIdentifierObjectSerializer(data=initial_data, model_class=Blog)
49+
50+
self.assertTrue(serializer.is_valid(), msg=serializer.errors)
51+
assert serializer.validated_data == self.blog
52+
53+
def test_data_in_correct_format_when_instantiated_with_queryset(self):
54+
qs = Author.objects.all()
55+
serializer = ResourceIdentifierObjectSerializer(instance=qs, many=True)
56+
57+
type_string = format_relation_name('Author')
58+
author_pks = Author.objects.values_list('pk', flat=True)
59+
expected_data = [{'type': type_string, 'id': str(pk)} for pk in author_pks]
60+
61+
assert serializer.data == expected_data
62+
63+
def test_deserialize_many(self):
64+
type_string = format_relation_name('Author')
65+
author_pks = Author.objects.values_list('pk', flat=True)
66+
initial_data = [{'type': type_string, 'id': str(pk)} for pk in author_pks]
67+
68+
serializer = ResourceIdentifierObjectSerializer(data=initial_data, model_class=Author, many=True)
69+
70+
self.assertTrue(serializer.is_valid(), msg=serializer.errors)
71+
72+
print(serializer.data)
73+

example/tests/test_views.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from django.utils import timezone
2+
from rest_framework.test import APITestCase
3+
4+
from rest_framework_json_api.utils import format_relation_name
5+
6+
from example.models import Blog, Entry
7+
from example.views import EntryRelationshipView, BlogRelationshipView
8+
9+
10+
class TestRelationshipView(APITestCase):
11+
12+
def setUp(self):
13+
self.blog = Blog.objects.create(name='Some Blog', tagline="It's a blog")
14+
self.entry = Entry.objects.create(
15+
blog=self.blog,
16+
headline='headline',
17+
body_text='body_text',
18+
pub_date=timezone.now(),
19+
mod_date=timezone.now(),
20+
n_comments=0,
21+
n_pingbacks=0,
22+
rating=3
23+
)
24+
25+
def test_get_entry_relationship_blog(self):
26+
response = self.client.get('/entries/{}/relationships/blog'.format(self.entry.id))
27+
expected_data = {'type': format_relation_name('Blog'), 'id': str(self.entry.blog.id)}
28+
29+
assert response.data == expected_data
30+
31+
def test_get_entry_relationship_invalid_field(self):
32+
response = self.client.get('/entries/{}/relationships/invalid_field'.format(self.entry.id))
33+
34+
assert response.status_code == 404
35+
36+
def test_get_blog_relationship_entry_set(self):
37+
response = self.client.get('/blogs/{}/relationships/entry_set'.format(self.blog.id))

example/urls.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from django.conf.urls import include, url
22
from rest_framework import routers
33

4-
from example.views import BlogViewSet, EntryViewSet, AuthorViewSet
4+
from example.views import BlogViewSet, EntryViewSet, AuthorViewSet, EntryRelationshipView, BlogRelationshipView
5+
56

67
router = routers.DefaultRouter(trailing_slash=False)
78

@@ -11,4 +12,8 @@
1112

1213
urlpatterns = [
1314
url(r'^', include(router.urls)),
15+
16+
url(r'^entries/(?P<pk>[^/.]+)/relationships/(?P<related_field>\w+)', EntryRelationshipView.as_view()),
17+
url(r'^blogs/(?P<pk>[^/.]+)/relationships/(?P<related_field>\w+)', BlogRelationshipView.as_view())
18+
1419
]

example/views.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from rest_framework import viewsets
2+
from rest_framework_json_api.views import RelationshipView
23
from example.models import Blog, Entry, Author
34
from example.serializers import BlogSerializer, EntrySerializer, AuthorSerializer
45

@@ -19,3 +20,10 @@ class AuthorViewSet(viewsets.ModelViewSet):
1920
queryset = Author.objects.all()
2021
serializer_class = AuthorSerializer
2122

23+
24+
25+
class EntryRelationshipView(RelationshipView):
26+
queryset = Entry.objects
27+
28+
class BlogRelationshipView(RelationshipView):
29+
queryset = Blog.objects

rest_framework_json_api/serializers.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
from django.utils.translation import ugettext_lazy as _
12
from rest_framework.serializers import *
3+
from rest_framework_json_api.utils import format_relation_name, get_resource_type_from_instance
24

35
from rest_framework_json_api.relations import HyperlinkedRelatedField
46

@@ -13,3 +15,34 @@ class HyperlinkedModelSerializer(HyperlinkedModelSerializer):
1315
* Uses django-rest-framework-json-api HyperlinkedRelatedField instead of the default HyperlinkedRelatedField
1416
"""
1517
serializer_related_field = HyperlinkedRelatedField
18+
19+
20+
class ResourceIdentifierObjectSerializer(BaseSerializer):
21+
default_error_messages = {
22+
'incorrect_model_type': _('Incorrect model type. Expected {model_type}, received {received_type}.'),
23+
'does_not_exist': _('Invalid pk "{pk_value}" - object does not exist.'),
24+
'incorrect_type': _('Incorrect type. Expected pk value, received {data_type}.'),
25+
}
26+
27+
def __init__(self, *args, **kwargs):
28+
self.model_class = kwargs.pop('model_class', None)
29+
if 'instance' not in kwargs and not self.model_class:
30+
raise RuntimeError('ResourceIdentifierObjectsSerializer must be initialized with a model class.')
31+
super(ResourceIdentifierObjectSerializer, self).__init__(*args, **kwargs)
32+
33+
def to_representation(self, instance):
34+
return {
35+
'type': format_relation_name(get_resource_type_from_instance(instance)),
36+
'id': str(instance.pk)
37+
}
38+
39+
def to_internal_value(self, data):
40+
if data['type'] != format_relation_name(self.model_class.__name__):
41+
self.fail('incorrect_model_type', model_type=self.model_class, received_type=data['type'])
42+
pk = data['id']
43+
try:
44+
return self.model_class.objects.get(pk=pk)
45+
except ObjectDoesNotExist:
46+
self.fail('does_not_exist', pk_value=pk)
47+
except (TypeError, ValueError):
48+
self.fail('incorrect_type', data_type=type(data['pk']).__name__)

rest_framework_json_api/views.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
from rest_framework import generics
22
from rest_framework.response import Response
3+
from rest_framework_json_api.serializers import ResourceIdentifierObjectSerializer
4+
from rest_framework.exceptions import NotFound
35

46

57
class RelationshipView(generics.GenericAPIView):
8+
serializer_class = ResourceIdentifierObjectSerializer
9+
610
def get(self, request, *args, **kwargs):
7-
return Response()
11+
related_instance = self.get_related_instance(kwargs)
12+
serializer_class = self.get_serializer_class()
13+
serializer = serializer_class(instance=related_instance)
14+
return Response(serializer.data)
815

916
def put(self, request, *args, **kwargs):
1017
return Response()
@@ -17,3 +24,9 @@ def post(self, request, *args, **kwargs):
1724

1825
def delete(self, request, *args, **kwargs):
1926
return Response()
27+
28+
def get_related_instance(self, kwargs):
29+
try:
30+
return getattr(self.get_object(), kwargs['related_field'])
31+
except AttributeError:
32+
raise NotFound

0 commit comments

Comments
 (0)