mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-27 03:54:01 +03:00
ManyPrimaryKeyRelatedField now supports create for one-to-many rel
This commit is contained in:
parent
1d24d1fc59
commit
008dafce17
|
@ -496,12 +496,19 @@ class ModelSerializer(Serializer):
|
||||||
Restore the model instance.
|
Restore the model instance.
|
||||||
"""
|
"""
|
||||||
self.m2m_data = {}
|
self.m2m_data = {}
|
||||||
|
self.related_data = {}
|
||||||
|
|
||||||
if instance is not None:
|
if instance is not None:
|
||||||
for key, val in attrs.items():
|
for key, val in attrs.items():
|
||||||
setattr(instance, key, val)
|
setattr(instance, key, val)
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
# Related relations
|
||||||
|
for (obj, model) in self.opts.model._meta.get_all_related_objects_with_model():
|
||||||
|
field_name = obj.field.related_query_name()
|
||||||
|
if field_name in attrs:
|
||||||
|
self.related_data[field_name] = attrs.pop(field_name)
|
||||||
|
|
||||||
# Reverse relations
|
# Reverse relations
|
||||||
for (obj, model) in self.opts.model._meta.get_all_related_m2m_objects_with_model():
|
for (obj, model) in self.opts.model._meta.get_all_related_m2m_objects_with_model():
|
||||||
field_name = obj.field.related_query_name()
|
field_name = obj.field.related_query_name()
|
||||||
|
@ -532,6 +539,11 @@ class ModelSerializer(Serializer):
|
||||||
setattr(self.object, accessor_name, object_list)
|
setattr(self.object, accessor_name, object_list)
|
||||||
self.m2m_data = {}
|
self.m2m_data = {}
|
||||||
|
|
||||||
|
if getattr(self, 'related_data', None):
|
||||||
|
for accessor_name, object_list in self.related_data.items():
|
||||||
|
setattr(self.object, accessor_name, object_list)
|
||||||
|
self.related_data = {}
|
||||||
|
|
||||||
return self.object
|
return self.object
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,11 @@ class BlogPostComment(RESTFrameworkModel):
|
||||||
blog_post = models.ForeignKey(BlogPost)
|
blog_post = models.ForeignKey(BlogPost)
|
||||||
|
|
||||||
|
|
||||||
|
class BlogPostRelatedComment(RESTFrameworkModel):
|
||||||
|
text = models.TextField()
|
||||||
|
blog_post = models.ForeignKey(BlogPost, related_name="comments")
|
||||||
|
|
||||||
|
|
||||||
class Album(RESTFrameworkModel):
|
class Album(RESTFrameworkModel):
|
||||||
title = models.CharField(max_length=100, unique=True)
|
title = models.CharField(max_length=100, unique=True)
|
||||||
|
|
||||||
|
|
|
@ -816,3 +816,82 @@ class NestedSerializerContextTests(TestCase):
|
||||||
|
|
||||||
# This will raise RuntimeError if context doesn't get passed correctly to the nested Serializers
|
# This will raise RuntimeError if context doesn't get passed correctly to the nested Serializers
|
||||||
AlbumCollectionSerializer(album_collection, context={'context_item': 'album context'}).data
|
AlbumCollectionSerializer(album_collection, context={'context_item': 'album context'}).data
|
||||||
|
|
||||||
|
|
||||||
|
class ManyPrimaryKeyRelatedCreateTest(TestCase):
|
||||||
|
|
||||||
|
def test_create_is_valid_with_title_and_empty_comments_list(self):
|
||||||
|
data = {'title': 'foobar', 'comments': []}
|
||||||
|
serializer = self.build_model_serializer(data)
|
||||||
|
self.assertEquals(serializer.is_valid(), True)
|
||||||
|
|
||||||
|
def test_create_is_valid_with_title_and_comment(self):
|
||||||
|
data = {'title': 'foobar', 'comments': [self.comment.pk]}
|
||||||
|
serializer = self.build_model_serializer(data)
|
||||||
|
self.assertEquals(serializer.is_valid(), True)
|
||||||
|
|
||||||
|
def test_create_is_not_valid_when_title_is_empty_string(self):
|
||||||
|
data = {'title': '', 'comments': [self.comment.pk]}
|
||||||
|
serializer = self.build_model_serializer(data)
|
||||||
|
self.assertEquals(serializer.is_valid(), False)
|
||||||
|
self.assertEquals(serializer.errors, {'title': [u'This field is required.']})
|
||||||
|
|
||||||
|
def test_create_is_not_valid_when_title_present_but_no_comments(self):
|
||||||
|
data = {'title': 'foobar'}
|
||||||
|
serializer = self.build_model_serializer(data)
|
||||||
|
try:
|
||||||
|
self.assertEquals(serializer.is_valid(), False)
|
||||||
|
except TypeError as e:
|
||||||
|
self.assertEqual(e.message, "'NoneType' object is not iterable")
|
||||||
|
|
||||||
|
def test_create_without_comment_returns_expected_json_result(self):
|
||||||
|
data = {'title': 'foobar', 'comments': []}
|
||||||
|
serializer = self.build_model_serializer(data)
|
||||||
|
self.assertEquals(serializer.is_valid(), True)
|
||||||
|
instance = serializer.save()
|
||||||
|
expected = {
|
||||||
|
'title': u'foobar',
|
||||||
|
'comments': []
|
||||||
|
}
|
||||||
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
def test_create_with_comment_returns_expected_json_result(self):
|
||||||
|
data = {'title': 'foobar', 'comments': [self.comment.pk]}
|
||||||
|
serializer = self.build_model_serializer(data)
|
||||||
|
self.assertEquals(serializer.is_valid(), True)
|
||||||
|
instance = serializer.save()
|
||||||
|
expected = {
|
||||||
|
'title': u'foobar',
|
||||||
|
'comments': [self.comment.pk]
|
||||||
|
}
|
||||||
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def comment(self):
|
||||||
|
if not hasattr(self, '_comment'):
|
||||||
|
from rest_framework.tests.models import BlogPostRelatedComment
|
||||||
|
self._comment = BlogPostRelatedComment.objects.create(text="I love this blog post", blog_post=self.post)
|
||||||
|
return self._comment
|
||||||
|
|
||||||
|
@property
|
||||||
|
def post(self):
|
||||||
|
if not hasattr(self, '_post'):
|
||||||
|
from rest_framework.tests.models import BlogPost
|
||||||
|
self._post = BlogPost.objects.create(title="Test blog post")
|
||||||
|
return self._post
|
||||||
|
|
||||||
|
def build_model_serializer(self, data):
|
||||||
|
from rest_framework.tests.models import BlogPost, BlogPostRelatedComment
|
||||||
|
|
||||||
|
class BlogPostRelatedCommentSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = BlogPostRelatedComment
|
||||||
|
fields = ("text")
|
||||||
|
|
||||||
|
class BlogPostSerializer(serializers.ModelSerializer):
|
||||||
|
comments = serializers.ManyPrimaryKeyRelatedField()
|
||||||
|
class Meta:
|
||||||
|
model = BlogPost
|
||||||
|
fields = ("title", "comments")
|
||||||
|
|
||||||
|
return BlogPostSerializer(data=data)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user