Skip to content

Commit 03e3a40

Browse files
stassliverc
authored andcommitted
Avoid exception when trying to include skipped relationship (#453)
1 parent fe3ed18 commit 03e3a40

File tree

5 files changed

+38
-4
lines changed

5 files changed

+38
-4
lines changed

‎AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ Yaniv Peer <yanivpeer@gmail.com>
2222
Mohammed Ali Zubair <mazg1493@gmail.com>
2323
Jason Housley <housleyjk@gmail.com>
2424
Beni Keller <beni@matraxi.ch>
25+
Stas S. <stas@nerd.ro>

‎CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
Note that in line with [Django REST Framework policy](http://www.django-rest-framework.org/topics/release-notes/),
99
any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.
1010

11+
## [Unreleased]
12+
13+
### Fixed
14+
15+
* Avoid exception when trying to include skipped relationship
1116

1217
## [2.7.0] - 2019-01-14
1318

‎example/serializers.py

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from datetime import datetime
22

3-
from rest_framework import serializers as drf_serilazers
3+
from rest_framework import serializers as drf_serilazers, fields as drf_fields
44

55
from rest_framework_json_api import relations, serializers
66

@@ -318,15 +318,40 @@ class Meta:
318318
exclude = ('polymorphic_ctype',)
319319

320320

321+
class CurrentProjectRelatedField(relations.PolymorphicResourceRelatedField):
322+
def get_attribute(self, instance):
323+
obj = super(CurrentProjectRelatedField, self).get_attribute(instance)
324+
325+
is_art = (
326+
self.field_name == 'current_art_project' and
327+
isinstance(obj, ArtProject)
328+
)
329+
is_res = (
330+
self.field_name == 'current_research_project' and
331+
isinstance(obj, ResearchProject)
332+
)
333+
334+
if is_art or is_res:
335+
return obj
336+
337+
raise drf_fields.SkipField()
338+
339+
321340
class CompanySerializer(serializers.ModelSerializer):
322341
current_project = relations.PolymorphicResourceRelatedField(
323342
ProjectSerializer, queryset=Project.objects.all())
343+
current_art_project = CurrentProjectRelatedField(
344+
ProjectSerializer, source='current_project', read_only=True)
345+
current_research_project = CurrentProjectRelatedField(
346+
ProjectSerializer, source='current_project', read_only=True)
324347
future_projects = relations.PolymorphicResourceRelatedField(
325348
ProjectSerializer, queryset=Project.objects.all(), many=True)
326349

327350
included_serializers = {
328351
'current_project': ProjectSerializer,
329352
'future_projects': ProjectSerializer,
353+
'current_art_project': ProjectSerializer,
354+
'current_research_project': ProjectSerializer
330355
}
331356

332357
class Meta:

‎example/tests/integration/test_polymorphism.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ def test_polymorphism_on_detail_relations(single_company, client):
2525

2626

2727
def test_polymorphism_on_included_relations(single_company, client):
28-
response = client.get(reverse("company-detail", kwargs={'pk': single_company.pk}) +
29-
'?include=current_project,future_projects')
28+
response = client.get(
29+
reverse("company-detail", kwargs={'pk': single_company.pk}) +
30+
'?include=current_project,future_projects,current_art_project,current_research_project')
3031
content = response.json()
3132
assert content["data"]["relationships"]["currentProject"]["data"]["type"] == "artProjects"
33+
assert content["data"]["relationships"]["currentArtProject"]["data"]["type"] == "artProjects"
34+
assert content["data"]["relationships"]["currentResearchProject"]["data"] is None
3235
assert (
3336
set([rel["type"] for rel in content["data"]["relationships"]["futureProjects"]["data"]]) ==
3437
set(["researchProjects", "artProjects"])

‎rest_framework_json_api/renderers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ def extract_included(cls, fields, resource, resource_instance, included_resource
375375
serializer_data = field.data
376376

377377
if isinstance(field, relations.RelatedField):
378-
if relation_instance is None:
378+
if relation_instance is None or not serializer_data:
379379
continue
380380

381381
many = field._kwargs.get('child_relation', None) is not None

0 commit comments

Comments
 (0)