Skip to content

Commit 54cbdaa

Browse files
committed
default DRF HyperLinkedIdentity Relationship fails for related fields.
1 parent 1ce84f8 commit 54cbdaa

File tree

4 files changed

+98
-2
lines changed

4 files changed

+98
-2
lines changed

example/serializers.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Meta:
3737

3838
class BlogSerializer(serializers.ModelSerializer):
3939
copyright = serializers.SerializerMethodField()
40-
tags = TaggedItemSerializer(many=True, read_only=True)
40+
tags = TaggedItemDRFSerializer(many=True, read_only=True)
4141

4242
include_serializers = {
4343
'tags': 'example.serializers.TaggedItemSerializer',
@@ -173,6 +173,22 @@ class JSONAPIMeta:
173173
included_resources = ['comments']
174174

175175

176+
class EntryDRFSerializers(drf_serilazers.ModelSerializer):
177+
178+
tags = TaggedItemDRFSerializer(many=True, read_only=True)
179+
blog_hyperlinked = drf_serilazers.HyperlinkedIdentityField(
180+
view_name='drf-entry-blog-detail',
181+
lookup_url_kwarg='entry_pk',
182+
read_only=True,
183+
source='blog'
184+
)
185+
186+
class Meta:
187+
model = Entry
188+
fields = ('tags', 'blog', 'blog_hyperlinked',)
189+
read_only_fields = ('tags',)
190+
191+
176192
class AuthorTypeSerializer(serializers.ModelSerializer):
177193
class Meta:
178194
model = AuthorType

example/tests/unit/test_default_drf_serializers.py

+58
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,61 @@ def test_get_object_deletes_correct_blog(client, entry):
184184
resp = client.delete(url)
185185

186186
assert resp.status_code == 204
187+
188+
189+
@pytest.mark.django_db
190+
def test_get_entry_list_with_blogs(client, entry):
191+
url = reverse('drf-entry-suggested', kwargs={'entry_pk': entry.id})
192+
resp = client.get(url)
193+
194+
got = resp.json()
195+
196+
expected = {
197+
'links': {
198+
'first': 'http://testserver/drf-entries/1/suggested/?page=1',
199+
'last': 'http://testserver/drf-entries/1/suggested/?page=1',
200+
'next': None,
201+
'prev': None
202+
},
203+
'data': [
204+
{
205+
'type': 'entries',
206+
'id': '1',
207+
'attributes': {
208+
209+
},
210+
'relationships': {
211+
'tags': {
212+
'data': [
213+
214+
]
215+
},
216+
'blog': {
217+
'data': {
218+
'type': 'blogs',
219+
'id': '1'
220+
}
221+
},
222+
'blogHyperlinked': {
223+
'data': {
224+
'type': 'blogs',
225+
'id': '1'
226+
},
227+
'links': {
228+
'related': 'http://testserver/drf-blogs/1'
229+
}
230+
}
231+
}
232+
}
233+
],
234+
'meta': {
235+
'pagination': {
236+
'page': 1,
237+
'pages': 1,
238+
'count': 1
239+
}
240+
}
241+
}
242+
243+
assert resp.status_code == 200
244+
assert got == expected

example/urls_test.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
CommentViewSet,
1212
CompanyViewset,
1313
DRFBlogViewSet,
14+
DRFEntryViewSet,
1415
EntryRelationshipView,
1516
EntryViewSet,
1617
FiltersetEntryViewSet,
@@ -23,7 +24,7 @@
2324
router = routers.DefaultRouter(trailing_slash=False)
2425

2526
router.register(r'blogs', BlogViewSet)
26-
# router to test default DRF functionalities
27+
# router to test default DRF blog functionalities
2728
router.register(r'drf-blogs', DRFBlogViewSet, 'drf-entry-blog')
2829
router.register(r'entries', EntryViewSet)
2930
# these "flavors" of entries are used for various tests:
@@ -59,6 +60,10 @@
5960
EntryViewSet.as_view({'get': 'list'}),
6061
name='entry-suggested'
6162
),
63+
url(r'^drf-entries/(?P<entry_pk>[^/.]+)/suggested/',
64+
DRFEntryViewSet.as_view({'get': 'list'}),
65+
name='drf-entry-suggested'
66+
),
6267
url(r'entries/(?P<entry_pk>[^/.]+)/authors',
6368
AuthorViewSet.as_view({'get': 'list'}),
6469
name='entry-authors'),

example/views.py

+17
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
BlogSerializer,
2222
CommentSerializer,
2323
CompanySerializer,
24+
EntryDRFSerializers,
2425
EntrySerializer,
2526
ProjectSerializer,
2627
ProjectTypeSerializer
@@ -104,6 +105,22 @@ def get_object(self):
104105
return super(EntryViewSet, self).get_object()
105106

106107

108+
class DRFEntryViewSet(viewsets.ModelViewSet):
109+
queryset = Entry.objects.all()
110+
lookup_url_kwarg = 'entry_pk'
111+
112+
def get_serializer_class(self):
113+
return EntryDRFSerializers
114+
115+
def get_object(self):
116+
# Handle featured
117+
entry_pk = self.kwargs.get(self.lookup_url_kwarg, None)
118+
if entry_pk is not None:
119+
return Entry.objects.exclude(pk=entry_pk).first()
120+
121+
return super(DRFEntryViewSet, self).get_object()
122+
123+
107124
class NoPagination(PageNumberPagination):
108125
page_size = None
109126

0 commit comments

Comments
 (0)