From 85eb3eb23f94226124cd7d40950c8b221d817963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stas=20SU=C8=98COV?= Date: Sat, 2 Feb 2019 15:15:05 +0000 Subject: [PATCH 1/5] Resource related fields can return blank. It can happen when `rest_framework.fields.SkipField` is called. --- rest_framework_json_api/renderers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework_json_api/renderers.py b/rest_framework_json_api/renderers.py index 9aa16212..d83fcdf0 100644 --- a/rest_framework_json_api/renderers.py +++ b/rest_framework_json_api/renderers.py @@ -375,7 +375,7 @@ def extract_included(cls, fields, resource, resource_instance, included_resource serializer_data = field.data if isinstance(field, relations.RelatedField): - if relation_instance is None: + if relation_instance is None or not serializer_data: continue many = field._kwargs.get('child_relation', None) is not None From 00af0487ab14aa7470cc0864df7c35e49330167c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stas=20SU=C8=98COV?= Date: Sat, 2 Feb 2019 15:41:20 +0000 Subject: [PATCH 2/5] Added a test where `fields.SkipField` is used. --- example/serializers.py | 27 ++++++++++++++++++- .../tests/integration/test_polymorphism.py | 7 +++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/example/serializers.py b/example/serializers.py index 7917062e..9be6d4d7 100644 --- a/example/serializers.py +++ b/example/serializers.py @@ -1,6 +1,6 @@ from datetime import datetime -from rest_framework import serializers as drf_serilazers +from rest_framework import serializers as drf_serilazers, fields as drf_fields from rest_framework_json_api import relations, serializers @@ -318,15 +318,40 @@ class Meta: exclude = ('polymorphic_ctype',) +class CurrentProjectRelatedField(relations.PolymorphicResourceRelatedField): + def get_attribute(self, instance): + obj = super(CurrentProjectRelatedField, self).get_attribute(instance) + + is_art = ( + self.field_name == 'current_art_project' and + isinstance(obj, ArtProject) + ) + is_res = ( + self.field_name == 'current_research_project' and + isinstance(obj, ResearchProject) + ) + + if is_art or is_res: + return obj + + raise drf_fields.SkipField() + + class CompanySerializer(serializers.ModelSerializer): current_project = relations.PolymorphicResourceRelatedField( ProjectSerializer, queryset=Project.objects.all()) + current_art_project = CurrentProjectRelatedField( + ProjectSerializer, source='current_project', read_only=True) + current_research_project = CurrentProjectRelatedField( + ProjectSerializer, source='current_project', read_only=True) future_projects = relations.PolymorphicResourceRelatedField( ProjectSerializer, queryset=Project.objects.all(), many=True) included_serializers = { 'current_project': ProjectSerializer, 'future_projects': ProjectSerializer, + 'current_art_project': ProjectSerializer, + 'current_research_project': ProjectSerializer } class Meta: diff --git a/example/tests/integration/test_polymorphism.py b/example/tests/integration/test_polymorphism.py index bc80599a..48ee80f3 100644 --- a/example/tests/integration/test_polymorphism.py +++ b/example/tests/integration/test_polymorphism.py @@ -25,10 +25,13 @@ def test_polymorphism_on_detail_relations(single_company, client): def test_polymorphism_on_included_relations(single_company, client): - response = client.get(reverse("company-detail", kwargs={'pk': single_company.pk}) + - '?include=current_project,future_projects') + response = client.get( + reverse("company-detail", kwargs={'pk': single_company.pk}) + + '?include=current_project,future_projects,current_art_project,current_research_project') content = response.json() assert content["data"]["relationships"]["currentProject"]["data"]["type"] == "artProjects" + assert content["data"]["relationships"]["currentArtProject"]["data"]["type"] == "artProjects" + assert content["data"]["relationships"]["currentResearchProject"]["data"] is None assert ( set([rel["type"] for rel in content["data"]["relationships"]["futureProjects"]["data"]]) == set(["researchProjects", "artProjects"]) From c026e8ed50630342d175e8a5236922da84c37d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stas=20SU=C8=98COV?= Date: Sun, 10 Feb 2019 16:59:58 +0000 Subject: [PATCH 3/5] Added myself to authors file. --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index f3e3d2b2..0f4c5167 100644 --- a/AUTHORS +++ b/AUTHORS @@ -22,3 +22,4 @@ Yaniv Peer Mohammed Ali Zubair Jason Housley Beni Keller +Stas S. From c69e0bff6876a8a76af72f71b2a626817417681f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stas=20SU=C8=98COV?= Date: Sun, 10 Feb 2019 17:03:09 +0000 Subject: [PATCH 4/5] Updated the changelog. --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d193884b..0f92a93a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Note that in line with [Django REST Framework policy](http://www.django-rest-framework.org/topics/release-notes/), any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change. +## [Unreleased] + +### Fixed + +* Resource related fields can be blank, serializer/renderer should skip these. ## [2.7.0] - 2019-01-14 From b05f10c8a0b29b8325014981b05279c89777f9fe Mon Sep 17 00:00:00 2001 From: Oliver Sauder Date: Mon, 11 Feb 2019 09:22:30 +0100 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f92a93a..19ce7f65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ any parts of the framework not mentioned in the documentation should generally b ### Fixed -* Resource related fields can be blank, serializer/renderer should skip these. +* Avoid exception when trying to include skipped relationship ## [2.7.0] - 2019-01-14