diff --git a/CHANGELOG.md b/CHANGELOG.md index b4f22a50..2dc4e307 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,8 +26,9 @@ any parts of the framework not mentioned in the documentation should generally b * Don't swallow `filter[]` params when there are several * Fix DeprecationWarning regarding collections.abc import in Python 3.7 * Allow OPTIONS request to be used on RelationshipView -* Avoid raising validation error for missing fields on a PATCH - request for polymorphic serializers +* Remove non-JSONAPI methods (PUT and TRACE) from ModelViewSet and RelationshipView. + This fix might be a **BREAKING CHANGE** if your clients are incorrectly using PUT instead of PATCH. +* Avoid validation error for missing fields on a PATCH request using polymorphic serializers ### Deprecated diff --git a/docs/usage.md b/docs/usage.md index c06d276c..a655687a 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -322,7 +322,7 @@ Possible values: * underscore Note: due to the way the inflector works `address_1` can camelize to `address1` -on output but it cannot convert `address1` back to `address_1` on POST or PUT. Keep +on output but it cannot convert `address1` back to `address_1` on POST or PATCH. Keep this in mind when naming fields with numbers in them. diff --git a/example/tests/integration/test_polymorphism.py b/example/tests/integration/test_polymorphism.py index 56687161..5c64776a 100644 --- a/example/tests/integration/test_polymorphism.py +++ b/example/tests/integration/test_polymorphism.py @@ -185,8 +185,8 @@ def test_polymorphism_relations_update(single_company, research_project_factory, "type": "researchProjects", "id": research_project.pk } - response = client.put(reverse("company-detail", kwargs={'pk': single_company.pk}), - data=content) + response = client.patch(reverse("company-detail", kwargs={'pk': single_company.pk}), + data=content) assert response.status_code == 200 content = response.json() assert content["data"]["relationships"]["currentProject"]["data"]["type"] == "researchProjects" @@ -194,18 +194,33 @@ def test_polymorphism_relations_update(single_company, research_project_factory, research_project.pk -def test_invalid_type_on_polymorphic_relation(single_company, research_project_factory, client): +def test_polymorphism_relations_put_405(single_company, research_project_factory, client): response = client.get(reverse("company-detail", kwargs={'pk': single_company.pk})) content = response.json() assert content["data"]["relationships"]["currentProject"]["data"]["type"] == "artProjects" research_project = research_project_factory() content["data"]["relationships"]["currentProject"]["data"] = { - "type": "invalidProjects", + "type": "researchProjects", "id": research_project.pk } response = client.put(reverse("company-detail", kwargs={'pk': single_company.pk}), data=content) + assert response.status_code == 405 + + +def test_invalid_type_on_polymorphic_relation(single_company, research_project_factory, client): + response = client.get(reverse("company-detail", kwargs={'pk': single_company.pk})) + content = response.json() + assert content["data"]["relationships"]["currentProject"]["data"]["type"] == "artProjects" + + research_project = research_project_factory() + content["data"]["relationships"]["currentProject"]["data"] = { + "type": "invalidProjects", + "id": research_project.pk + } + response = client.patch(reverse("company-detail", kwargs={'pk': single_company.pk}), + data=content) assert response.status_code == 409 content = response.json() assert len(content["errors"]) == 1 diff --git a/example/views.py b/example/views.py index 4d363032..8112b4ff 100644 --- a/example/views.py +++ b/example/views.py @@ -2,7 +2,6 @@ import rest_framework.parsers import rest_framework.renderers from django_filters import rest_framework as filters -from rest_framework import viewsets from rest_framework.filters import SearchFilter import rest_framework_json_api.metadata @@ -42,7 +41,7 @@ def get_object(self): return super(BlogViewSet, self).get_object() -class DRFBlogViewSet(viewsets.ModelViewSet): +class DRFBlogViewSet(ModelViewSet): queryset = Blog.objects.all() serializer_class = BlogDRFSerializer lookup_url_kwarg = 'entry_pk' @@ -105,7 +104,7 @@ def get_object(self): return super(EntryViewSet, self).get_object() -class DRFEntryViewSet(viewsets.ModelViewSet): +class DRFEntryViewSet(ModelViewSet): queryset = Entry.objects.all() serializer_class = EntryDRFSerializers lookup_url_kwarg = 'entry_pk' diff --git a/rest_framework_json_api/views.py b/rest_framework_json_api/views.py index 48c4f43e..bdc08c70 100644 --- a/rest_framework_json_api/views.py +++ b/rest_framework_json_api/views.py @@ -243,13 +243,13 @@ class ModelViewSet(AutoPrefetchMixin, PreloadIncludesMixin, RelatedMixin, viewsets.ModelViewSet): - pass + http_method_names = ['get', 'post', 'patch', 'delete', 'head', 'options'] class ReadOnlyModelViewSet(AutoPrefetchMixin, RelatedMixin, viewsets.ReadOnlyModelViewSet): - pass + http_method_names = ['get', 'head', 'options'] class RelationshipView(generics.GenericAPIView): @@ -257,6 +257,7 @@ class RelationshipView(generics.GenericAPIView): self_link_view_name = None related_link_view_name = None field_name_mapping = {} + http_method_names = ['get', 'post', 'patch', 'delete', 'head', 'options'] def get_serializer_class(self): if getattr(self, 'action', False) is None: