Fix serialization of reverse relationships

This commit is contained in:
Jamie Matthews 2012-10-22 15:12:25 +01:00
parent d53ee8a10c
commit 45d4622f09
3 changed files with 53 additions and 10 deletions

View File

@ -247,6 +247,19 @@ class BaseSerializer(Field):
if not self._errors:
return self.restore_object(attrs, instance=getattr(self, 'object', None))
def field_to_native(self, obj, field_name):
"""
Override default so that we can apply ModelSerializer as a nested
field to relationships.
"""
obj = getattr(obj, self.source or field_name)
# If the object has an "all" method, assume it's a relationship
if is_simple_callable(getattr(obj, 'all', None)):
return [self.to_native(item) for item in obj.all()]
return self.to_native(obj)
@property
def errors(self):
"""
@ -295,16 +308,6 @@ class ModelSerializer(Serializer):
"""
_options_class = ModelSerializerOptions
def field_to_native(self, obj, field_name):
"""
Override default so that we can apply ModelSerializer as a nested
field to relationships.
"""
obj = getattr(obj, self.source or field_name)
if obj.__class__.__name__ in ('RelatedManager', 'ManyRelatedManager'):
return [self.to_native(item) for item in obj.all()]
return self.to_native(obj)
def default_fields(self, serialize, obj=None, data=None, nested=False):
"""
Return all the fields that should be serialized for the model.

View File

@ -92,6 +92,17 @@ class Comment(RESTFrameworkModel):
content = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
class ActionItem(RESTFrameworkModel):
title = models.CharField(max_length=200)
done = models.BooleanField(default=False)
# Models for reverse relations
class BlogPost(RESTFrameworkModel):
title = models.CharField(max_length=100)
class BlogPostComment(RESTFrameworkModel):
text = models.TextField()
blog_post = models.ForeignKey(BlogPost)

View File

@ -302,3 +302,32 @@ class CallableDefaultValueTests(TestCase):
self.assertEquals(len(self.objects.all()), 1)
self.assertEquals(instance.pk, 1)
self.assertEquals(instance.text, 'overridden')
class ManyRelatedTests(TestCase):
def setUp(self):
class BlogPostCommentSerializer(serializers.Serializer):
text = serializers.CharField()
class BlogPostSerializer(serializers.Serializer):
title = serializers.CharField()
comments = BlogPostCommentSerializer(source='blogpostcomment_set')
self.serializer_class = BlogPostSerializer
def test_reverse_relations(self):
post = BlogPost.objects.create(title="Test blog post")
post.blogpostcomment_set.create(text="I hate this blog post")
post.blogpostcomment_set.create(text="I love this blog post")
serializer = self.serializer_class(instance=post)
expected = {
'title': 'Test blog post',
'comments': [
{'text': 'I hate this blog post'},
{'text': 'I love this blog post'}
]
}
self.assertEqual(serializer.data, expected)