diff --git a/CHANGELOG.md b/CHANGELOG.md index 49114a36..c60329ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ any parts of the framework not mentioned in the documentation should generally b ### Fixed * Pass context from `PolymorphicModelSerializer` to child serializers to support fields which require a `request` context such as `url`. +* Avoid patch on `RelationshipView` deleting relationship instance when constraint would allow null ([#242](https://github.com/django-json-api/django-rest-framework-json-api/issues/242)) ## [2.6.0] - 2018-09-20 diff --git a/example/tests/test_views.py b/example/tests/test_views.py index e4bf700f..5b778b90 100644 --- a/example/tests/test_views.py +++ b/example/tests/test_views.py @@ -11,7 +11,7 @@ from . import TestBase from .. import views -from example.factories import AuthorFactory, EntryFactory, CommentFactory +from example.factories import AuthorFactory, CommentFactory, EntryFactory from example.models import Author, Blog, Comment, Entry from example.serializers import AuthorBioSerializer, AuthorTypeSerializer, EntrySerializer from example.views import AuthorViewSet @@ -240,10 +240,14 @@ def test_new_comment_data_patch_to_many_relationship(self): previous_response = { 'data': [ {'type': 'comments', - 'id': f'{self.second_comment.id}' + 'id': str(self.second_comment.id) } ], - 'links': {'self': f'http://testserver/authors/{self.author.id}/relationships/comment_set'} + 'links': { + 'self': 'http://testserver/authors/{}/relationships/comment_set'.format( + self.author.id + ) + } } response = self.client.get(url) @@ -253,17 +257,21 @@ def test_new_comment_data_patch_to_many_relationship(self): new_patched_response = { 'data': [ {'type': 'comments', - 'id': f'{comment.id}' + 'id': str(comment.id) } ], - 'links': {'self': f'http://testserver/authors/{self.author.id}/relationships/comment_set'} + 'links': { + 'self': 'http://testserver/authors/{}/relationships/comment_set'.format( + self.author.id + ) + } } response = self.client.patch(url, data=request_data) assert response.status_code == 200 assert response.json() == new_patched_response - assert Comment.objects.filter(id=self.second_comment.id).exists + assert Comment.objects.filter(id=self.second_comment.id).exists() class TestRelatedMixin(APITestCase): diff --git a/rest_framework_json_api/views.py b/rest_framework_json_api/views.py index 224e4d8b..9f3178a1 100644 --- a/rest_framework_json_api/views.py +++ b/rest_framework_json_api/views.py @@ -254,7 +254,7 @@ def get(self, request, *args, **kwargs): def remove_relationships(self, instance_manager, field): field_object = getattr(instance_manager, field) - if getattr(field_object, "null"): + if field_object.null: for obj in instance_manager.all(): setattr(obj, field_object.name, None) obj.save() @@ -273,16 +273,15 @@ def patch(self, request, *args, **kwargs): data=request.data, model_class=related_model_class, many=True ) serializer.is_valid(raise_exception=True) - # related_instance_or_manager.all().delete() # for to one if hasattr(related_instance_or_manager, "field"): - related_instance_or_manager = self.remove_relationships(instance_manager=related_instance_or_manager, - field="field") + related_instance_or_manager = self.remove_relationships( + instance_manager=related_instance_or_manager, field="field") # for to many else: - related_instance_or_manager = self.remove_relationships(instance_manager=related_instance_or_manager, - field="target_field") + related_instance_or_manager = self.remove_relationships( + instance_manager=related_instance_or_manager, field="target_field") # have to set bulk to False since data isn't saved yet class_name = related_instance_or_manager.__class__.__name__