From 955b28c6548fcbff1991322b1d09807843e186ae Mon Sep 17 00:00:00 2001 From: Oliver Sauder Date: Fri, 16 Apr 2021 17:32:41 +0400 Subject: [PATCH] Avoided error when using include query parameter on related urls This is a regression from version 4.1.0. --- CHANGELOG.md | 4 ++++ example/tests/integration/test_browsable_api.py | 11 +++++++++++ example/tests/test_views.py | 11 +++++++++-- rest_framework_json_api/renderers.py | 5 ++++- rest_framework_json_api/serializers.py | 5 ++++- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b816f47d..3351004c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ any parts of the framework not mentioned in the documentation should generally b * Added support for Django 3.2. +### Fixed + +* Avoided error when using `include` query parameter on related urls (a regression since 4.1.0) + ## [4.1.0] - 2021-03-08 ### Added diff --git a/example/tests/integration/test_browsable_api.py b/example/tests/integration/test_browsable_api.py index 9156eb92..14ebe3fb 100644 --- a/example/tests/integration/test_browsable_api.py +++ b/example/tests/integration/test_browsable_api.py @@ -18,6 +18,17 @@ def test_browsable_api_with_included_serializers(single_entry, client): ) +def test_browsable_api_on_related_url(author, client): + url = reverse("author-related", kwargs={"pk": author.pk, "related_field": "bio"}) + response = client.get(url, data={"format": "api"}) + content = str(response.content) + assert response.status_code == 200 + assert re.search(r"JSON:API includes", content) + assert re.search( + r']* value="metadata"', content + ) + + def test_browsable_api_with_no_included_serializers(client): response = client.get(reverse("projecttype-list", kwargs={"format": "api"})) content = str(response.content) diff --git a/example/tests/test_views.py b/example/tests/test_views.py index 4b494b52..3b8584d0 100644 --- a/example/tests/test_views.py +++ b/example/tests/test_views.py @@ -433,7 +433,7 @@ def test_retrieve_related_single_reverse_lookup(self): url = reverse( "author-related", kwargs={"pk": self.author.pk, "related_field": "bio"} ) - resp = self.client.get(url) + resp = self.client.get(url, data={"include": "metadata"}) expected = { "data": { "type": "authorBios", @@ -448,7 +448,14 @@ def test_retrieve_related_single_reverse_lookup(self): }, }, "attributes": {"body": str(self.author.bio.body)}, - } + }, + "included": [ + { + "attributes": {"body": str(self.author.bio.metadata.body)}, + "id": str(self.author.bio.metadata.id), + "type": "authorBioMetadata", + } + ], } self.assertEqual(resp.status_code, 200) self.assertEqual(resp.json(), expected) diff --git a/rest_framework_json_api/renderers.py b/rest_framework_json_api/renderers.py index e84c562b..b50c2b1a 100644 --- a/rest_framework_json_api/renderers.py +++ b/rest_framework_json_api/renderers.py @@ -708,7 +708,10 @@ def _get_included_serializers(cls, serializer, prefix="", already_seen=None): def get_includes_form(self, view): try: - serializer_class = view.get_serializer_class() + if "related_field" in view.kwargs: + serializer_class = view.get_related_serializer_class() + else: + serializer_class = view.get_serializer_class() except AttributeError: return diff --git a/rest_framework_json_api/serializers.py b/rest_framework_json_api/serializers.py index 56949818..a73a5d47 100644 --- a/rest_framework_json_api/serializers.py +++ b/rest_framework_json_api/serializers.py @@ -140,7 +140,10 @@ def validate_path(serializer_class, field_path, path): included_resources = get_included_resources(request) for included_field_name in included_resources: included_field_path = included_field_name.split(".") - this_serializer_class = view.get_serializer_class() + if "related_field" in view.kwargs: + this_serializer_class = view.get_related_serializer_class() + else: + this_serializer_class = view.get_serializer_class() # lets validate the current path validate_path( this_serializer_class, included_field_path, included_field_name