From ea63eb5a2882b02c680fa0eed446ff65d3918159 Mon Sep 17 00:00:00 2001 From: Rohith PR Date: Thu, 14 May 2020 18:01:15 +0530 Subject: [PATCH 1/7] Fix #784 Clear m2m relationships instead of deleting them during PATCH Calling PATCH on an M2M RelationshipView when there were already some relationships was breaking. This was because the related objects were being deleted instead of just clearing the relationship and starting afresh. --- rest_framework_json_api/views.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rest_framework_json_api/views.py b/rest_framework_json_api/views.py index a5836759..ba919f32 100644 --- a/rest_framework_json_api/views.py +++ b/rest_framework_json_api/views.py @@ -286,6 +286,8 @@ def remove_relationships(self, instance_manager, field): for obj in instance_manager.all(): setattr(obj, field_object.name, None) obj.save() + elif hasattr(instance_manager, 'clear'): + instance_manager.clear() else: instance_manager.all().delete() From dc5a0a532ab3f0f087a0c763b69bd3cf131a5694 Mon Sep 17 00:00:00 2001 From: Rohith PR Date: Thu, 14 May 2020 18:16:58 +0530 Subject: [PATCH 2/7] Added Rohith PR to AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index c58a4b87..452317e2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -17,6 +17,7 @@ Ola Tarkowska Oliver Sauder Raphael Cohen Roberto Barreda +Rohith PR santiavenda Tim Selman Yaniv Peer From a6ec41eade1967c4c135d0d33533a332e12f83e7 Mon Sep 17 00:00:00 2001 From: Rohith PR Date: Thu, 14 May 2020 18:24:16 +0530 Subject: [PATCH 3/7] Update m2m test to call PATCH twice and verify that everything looks good --- example/tests/test_views.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/example/tests/test_views.py b/example/tests/test_views.py index ad7e5d4d..80c908c7 100644 --- a/example/tests/test_views.py +++ b/example/tests/test_views.py @@ -152,6 +152,13 @@ def test_patch_many_to_many_relationship(self): response = self.client.get(url) assert response.data == request_data['data'] + response = self.client.patch(url, data=request_data) + assert response.status_code == 200, response.content.decode() + assert response.data == request_data['data'] + + response = self.client.get(url) + assert response.data == request_data['data'] + def test_post_to_one_relationship_should_fail(self): url = '/entries/{}/relationships/blog'.format(self.first_entry.id) request_data = { From a642d1635762071f0ae1fce3272179fdf5ceb2e6 Mon Sep 17 00:00:00 2001 From: Rohith PR Date: Thu, 14 May 2020 18:35:54 +0530 Subject: [PATCH 4/7] Update o2m test to call PATCH twice and verify that its behavior isn't broken --- example/tests/test_views.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/example/tests/test_views.py b/example/tests/test_views.py index 80c908c7..6c93658a 100644 --- a/example/tests/test_views.py +++ b/example/tests/test_views.py @@ -135,6 +135,13 @@ def test_patch_one_to_many_relationship(self): response = self.client.get(url) assert response.data == request_data['data'] + response = self.client.patch(url, data=request_data) + assert response.status_code == 200, response.content.decode() + assert response.data == request_data['data'] + + response = self.client.get(url) + assert response.data == request_data['data'] + def test_patch_many_to_many_relationship(self): url = '/entries/{}/relationships/authors'.format(self.first_entry.id) request_data = { From f16d881e5147225c7992f88c465835d6d42ed379 Mon Sep 17 00:00:00 2001 From: Oliver Sauder Date: Sat, 13 Jun 2020 14:16:01 +0200 Subject: [PATCH 5/7] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06b6fe91..95d7905b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ any parts of the framework not mentioned in the documentation should generally b ### Fixed * Avoid `AttributeError` for PUT and PATCH methods when using `APIView` +* Clear many-to-many relationships instead of deleting related objects during PATCH on `RelationshipView` ### Changed From 977e70bc44f1f7dd52d29281aef24bb9d4ab46cf Mon Sep 17 00:00:00 2001 From: Oliver Sauder Date: Sat, 13 Jun 2020 14:33:14 +0200 Subject: [PATCH 6/7] Clarify test code --- example/tests/test_views.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/example/tests/test_views.py b/example/tests/test_views.py index 6c93658a..8e98e588 100644 --- a/example/tests/test_views.py +++ b/example/tests/test_views.py @@ -135,6 +135,7 @@ def test_patch_one_to_many_relationship(self): response = self.client.get(url) assert response.data == request_data['data'] + # retry a second time should end up with same result response = self.client.patch(url, data=request_data) assert response.status_code == 200, response.content.decode() assert response.data == request_data['data'] @@ -159,6 +160,7 @@ def test_patch_many_to_many_relationship(self): response = self.client.get(url) assert response.data == request_data['data'] + # retry a second time should end up with same result response = self.client.patch(url, data=request_data) assert response.status_code == 200, response.content.decode() assert response.data == request_data['data'] From 3b6c12d953cbeff509d15f3fe22c8d0b1f64b5f8 Mon Sep 17 00:00:00 2001 From: Oliver Sauder Date: Sat, 13 Jun 2020 14:41:31 +0200 Subject: [PATCH 7/7] Add test to verify empty patch on RelationshipView --- example/tests/test_views.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/example/tests/test_views.py b/example/tests/test_views.py index 8e98e588..e18511fa 100644 --- a/example/tests/test_views.py +++ b/example/tests/test_views.py @@ -143,6 +143,18 @@ def test_patch_one_to_many_relationship(self): response = self.client.get(url) assert response.data == request_data['data'] + def test_patch_one_to_many_relaitonship_with_none(self): + url = '/blogs/{}/relationships/entry_set'.format(self.first_entry.id) + request_data = { + 'data': None + } + response = self.client.patch(url, data=request_data) + assert response.status_code == 200, response.content.decode() + assert response.data == [] + + response = self.client.get(url) + assert response.data == [] + def test_patch_many_to_many_relationship(self): url = '/entries/{}/relationships/authors'.format(self.first_entry.id) request_data = {