From 68c397371c647e88270b8c9e9a6f5f610bbd3a2b Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Tue, 20 Nov 2012 09:41:36 +0000 Subject: [PATCH 1/2] Fix related serializers with source argument that resolves to a callable --- rest_framework/serializers.py | 3 +++ rest_framework/tests/models.py | 3 +++ rest_framework/tests/serializer.py | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 397866a76..2e7e2cf5d 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -277,6 +277,9 @@ class BaseSerializer(Field): """ obj = getattr(obj, self.source or field_name) + if is_simple_callable(obj): + obj = obj() + # 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()] diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py index 59d811502..3704cda7b 100644 --- a/rest_framework/tests/models.py +++ b/rest_framework/tests/models.py @@ -127,6 +127,9 @@ class ActionItem(RESTFrameworkModel): class BlogPost(RESTFrameworkModel): title = models.CharField(max_length=100) + def get_first_comment(self): + return self.blogpostcomment_set.all()[0] + class BlogPostComment(RESTFrameworkModel): text = models.TextField() diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 814c24993..9ca4f002f 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -488,6 +488,7 @@ class ManyRelatedTests(TestCase): title = serializers.CharField() comments = BlogPostCommentSerializer(source='blogpostcomment_set') + self.comment_serializer_class = BlogPostCommentSerializer self.serializer_class = BlogPostSerializer def test_reverse_relations(self): @@ -506,6 +507,23 @@ class ManyRelatedTests(TestCase): self.assertEqual(serializer.data, expected) + def test_callable_source(self): + post = BlogPost.objects.create(title="Test blog post") + post.blogpostcomment_set.create(text="I love this blog post") + + class ExtendedBlogPostSerializer(self.serializer_class): + first_comment = self.comment_serializer_class(source='get_first_comment') + + serializer = ExtendedBlogPostSerializer(post) + expected = { + 'title': 'Test blog post', + 'comments': [ + {'text': 'I love this blog post'} + ], + 'first_comment': {'text': 'I love this blog post'} + } + self.assertEqual(serializer.data, expected) + # Test for issue #324 class BlankFieldTests(TestCase): From 3cc5349b2f98d9c70788a2aadefc150290316479 Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Tue, 20 Nov 2012 09:49:54 +0000 Subject: [PATCH 2/2] Clean up and clarify tests for related serializers --- rest_framework/tests/serializer.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index 9ca4f002f..d522ef972 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -479,7 +479,10 @@ class CallableDefaultValueTests(TestCase): class ManyRelatedTests(TestCase): - def setUp(self): + 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") class BlogPostCommentSerializer(serializers.Serializer): text = serializers.CharField() @@ -488,15 +491,7 @@ class ManyRelatedTests(TestCase): title = serializers.CharField() comments = BlogPostCommentSerializer(source='blogpostcomment_set') - self.comment_serializer_class = BlogPostCommentSerializer - 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) + serializer = BlogPostSerializer(instance=post) expected = { 'title': 'Test blog post', 'comments': [ @@ -511,15 +506,17 @@ class ManyRelatedTests(TestCase): post = BlogPost.objects.create(title="Test blog post") post.blogpostcomment_set.create(text="I love this blog post") - class ExtendedBlogPostSerializer(self.serializer_class): - first_comment = self.comment_serializer_class(source='get_first_comment') + class BlogPostCommentSerializer(serializers.Serializer): + text = serializers.CharField() + + class BlogPostSerializer(serializers.Serializer): + title = serializers.CharField() + first_comment = BlogPostCommentSerializer(source='get_first_comment') + + serializer = BlogPostSerializer(post) - serializer = ExtendedBlogPostSerializer(post) expected = { 'title': 'Test blog post', - 'comments': [ - {'text': 'I love this blog post'} - ], 'first_comment': {'text': 'I love this blog post'} } self.assertEqual(serializer.data, expected)