Skip to content

Commit 7979db0

Browse files
author
Leifur Halldor Asgeirsson
committed
WIP RelationshipView
1 parent 16d4fa5 commit 7979db0

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed

example/tests/test_views.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from django.utils import timezone
22
from rest_framework.reverse import reverse
3-
from rest_framework.test import APITestCase
3+
from rest_framework.test import APITestCase, APIRequestFactory
4+
import json
45

56
from rest_framework_json_api.utils import format_relation_name
67

@@ -11,6 +12,7 @@
1112
class TestRelationshipView(APITestCase):
1213
def setUp(self):
1314
self.blog = Blog.objects.create(name='Some Blog', tagline="It's a blog")
15+
self.other_blog = Blog.objects.create(name='Other blog', tagline="It's another blog")
1416
self.entry = Entry.objects.create(
1517
blog=self.blog,
1618
headline='headline',
@@ -36,3 +38,19 @@ def test_get_entry_relationship_invalid_field(self):
3638

3739
def test_get_blog_relationship_entry_set(self):
3840
response = self.client.get('/blogs/{}/relationships/entry_set'.format(self.blog.id))
41+
42+
def test_put_entry_relationship_blog_returns_405(self):
43+
url = '/entries/{}/relationships/blog'.format(self.entry.id)
44+
response = self.client.put(url, data={})
45+
assert response.status_code == 405
46+
47+
def test_patch_to_one_relationship(self):
48+
url = '/entries/{}/relationships/blog'.format(self.entry.id)
49+
request_data = {
50+
'data': {'type': format_relation_name('Blog'), 'id': str(self.other_blog.id)}
51+
}
52+
response = self.client.patch(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
53+
assert response.status_code == 200, response.content.decode()
54+
55+
response = self.client.get(url)
56+
assert response.data == request_data['data']

rest_framework_json_api/parsers.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ def parse(self, stream, media_type=None, parser_context=None):
3434
data = result.get('data', {})
3535

3636
if data:
37+
from rest_framework_json_api.views import RelationshipView
38+
if isinstance(parser_context['view'], RelationshipView):
39+
return data # temporary workaround
3740
# Check for inconsistencies
3841
resource_name = utils.get_resource_name(parser_context)
3942
if data.get('type') != resource_name:

rest_framework_json_api/views.py

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from rest_framework.response import Response
55
from rest_framework.renderers import JSONRenderer
66
from rest_framework_json_api.serializers import ResourceIdentifierObjectSerializer
7+
from rest_framework_json_api.utils import format_relation_name, get_resource_type_from_instance
78
from rest_framework.exceptions import NotFound
89

910

@@ -12,36 +13,48 @@ class RelationshipView(generics.GenericAPIView):
1213
renderer_classes = (JSONRenderer, )
1314

1415
def get(self, request, *args, **kwargs):
15-
related_instance = self.get_related_instance(kwargs)
16-
serializer_instance = self.instantiate_serializer(related_instance)
16+
related_instance = self.get_related_instance()
17+
serializer_instance = self._instantiate_serializer(related_instance)
1718
return Response(serializer_instance.data)
1819

19-
def put(self, request, *args, **kwargs):
20-
return Response()
21-
2220
def patch(self, request, *args, **kwargs):
23-
return Response()
21+
parent_obj = self.get_object()
22+
if hasattr(parent_obj, kwargs['related_field']):
23+
related_model_class = self.get_related_instance().__class__
24+
serializer = self.get_serializer(data=request.data, model_class=related_model_class)
25+
serializer.is_valid(raise_exception=True)
26+
setattr(parent_obj, kwargs['related_field'], serializer.validated_data)
27+
parent_obj.save()
28+
return Response(serializer.data)
2429

2530
def post(self, request, *args, **kwargs):
2631
return Response()
2732

2833
def delete(self, request, *args, **kwargs):
2934
return Response()
3035

31-
def get_related_instance(self, kwargs):
36+
def get_related_instance(self):
3237
try:
33-
return getattr(self.get_object(), kwargs['related_field'])
38+
return getattr(self.get_object(), self.kwargs['related_field'])
3439
except AttributeError:
3540
raise NotFound
3641

37-
def instantiate_serializer(self, instance):
38-
serializer_class = self.get_serializer_class()
42+
def _instantiate_serializer(self, instance):
3943
if isinstance(instance, Model):
40-
return serializer_class(instance=instance)
44+
return self.get_serializer(instance=instance)
4145
else:
4246
if isinstance(instance, (QuerySet, BaseManager)):
4347
instance = instance.all()
4448

45-
return serializer_class(instance=instance, many=True)
49+
return self.get_serializer(instance=instance, many=True)
50+
51+
def get_resource_name(self):
52+
if not hasattr(self, '_resource_name'):
53+
instance = getattr(self.get_object(), self.kwargs['related_field'])
54+
self._resource_name = format_relation_name(get_resource_type_from_instance(instance))
55+
return self._resource_name
4656

57+
def set_resource_name(self, value):
58+
self._resource_name = value
4759

60+
resource_name = property(get_resource_name, set_resource_name)

0 commit comments

Comments
 (0)