Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b3eed32

Browse files
Alig1493sliverc
authored andcommitted
Avoid patch on RelationshipView deleting relationship instance when constraint would allow null (#499)
1 parent 00fb5dc commit b3eed32

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

‎CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ any parts of the framework not mentioned in the documentation should generally b
2323
### Fixed
2424

2525
* Pass context from `PolymorphicModelSerializer` to child serializers to support fields which require a `request` context such as `url`.
26+
* 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))
2627

2728

2829
## [2.6.0] - 2018年09月20日

‎example/tests/test_views.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from . import TestBase
1313
from .. import views
14-
from example.factories import AuthorFactory, EntryFactory
14+
from example.factories import AuthorFactory, CommentFactory, EntryFactory
1515
from example.models import Author, Blog, Comment, Entry
1616
from example.serializers import AuthorBioSerializer, AuthorTypeSerializer, EntrySerializer
1717
from example.views import AuthorViewSet
@@ -229,6 +229,50 @@ def test_delete_to_many_relationship_with_change(self):
229229
response = self.client.delete(url, data=request_data)
230230
assert response.status_code == 200, response.content.decode()
231231

232+
def test_new_comment_data_patch_to_many_relationship(self):
233+
entry = EntryFactory(blog=self.blog, authors=(self.author,))
234+
comment = CommentFactory(entry=entry)
235+
236+
url = '/authors/{}/relationships/comment_set'.format(self.author.id)
237+
request_data = {
238+
'data': [{'type': format_resource_type('Comment'), 'id': str(comment.id)}, ]
239+
}
240+
previous_response = {
241+
'data': [
242+
{'type': 'comments',
243+
'id': str(self.second_comment.id)
244+
}
245+
],
246+
'links': {
247+
'self': 'http://testserver/authors/{}/relationships/comment_set'.format(
248+
self.author.id
249+
)
250+
}
251+
}
252+
253+
response = self.client.get(url)
254+
assert response.status_code == 200
255+
assert response.json() == previous_response
256+
257+
new_patched_response = {
258+
'data': [
259+
{'type': 'comments',
260+
'id': str(comment.id)
261+
}
262+
],
263+
'links': {
264+
'self': 'http://testserver/authors/{}/relationships/comment_set'.format(
265+
self.author.id
266+
)
267+
}
268+
}
269+
270+
response = self.client.patch(url, data=request_data)
271+
assert response.status_code == 200
272+
assert response.json() == new_patched_response
273+
274+
assert Comment.objects.filter(id=self.second_comment.id).exists()
275+
232276

233277
class TestRelatedMixin(APITestCase):
234278

‎rest_framework_json_api/views.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,18 @@ def get(self, request, *args, **kwargs):
251251
serializer_instance = self._instantiate_serializer(related_instance)
252252
return Response(serializer_instance.data)
253253

254+
def remove_relationships(self, instance_manager, field):
255+
field_object = getattr(instance_manager, field)
256+
257+
if field_object.null:
258+
for obj in instance_manager.all():
259+
setattr(obj, field_object.name, None)
260+
obj.save()
261+
else:
262+
instance_manager.all().delete()
263+
264+
return instance_manager
265+
254266
def patch(self, request, *args, **kwargs):
255267
parent_obj = self.get_object()
256268
related_instance_or_manager = self.get_related_instance()
@@ -261,7 +273,16 @@ def patch(self, request, *args, **kwargs):
261273
data=request.data, model_class=related_model_class, many=True
262274
)
263275
serializer.is_valid(raise_exception=True)
264-
related_instance_or_manager.all().delete()
276+
277+
# for to one
278+
if hasattr(related_instance_or_manager, "field"):
279+
related_instance_or_manager = self.remove_relationships(
280+
instance_manager=related_instance_or_manager, field="field")
281+
# for to many
282+
else:
283+
related_instance_or_manager = self.remove_relationships(
284+
instance_manager=related_instance_or_manager, field="target_field")
285+
265286
# have to set bulk to False since data isn't saved yet
266287
class_name = related_instance_or_manager.__class__.__name__
267288
if class_name != 'ManyRelatedManager':

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /