Merge pull request #462 from asfaltboy/modelserializer_traverse_related

ModelSerializer traverse related
This commit is contained in:
Tom Christie 2012-12-06 14:35:57 -08:00
commit e2175eb71b
3 changed files with 65 additions and 15 deletions

View File

@ -272,10 +272,18 @@ class BaseSerializer(Field):
Override default so that we can apply ModelSerializer as a nested Override default so that we can apply ModelSerializer as a nested
field to relationships. field to relationships.
""" """
obj = getattr(obj, self.source or field_name)
if is_simple_callable(obj): if self.source:
obj = obj() value = obj
for component in self.source.split('.'):
value = getattr(value, component)
if is_simple_callable(value):
value = value()
obj = value
else:
value = getattr(obj, field_name)
if is_simple_callable(value):
obj = value()
# If the object has an "all" method, assume it's a relationship # If the object has an "all" method, assume it's a relationship
if is_simple_callable(getattr(obj, 'all', None)): if is_simple_callable(getattr(obj, 'all', None)):

View File

@ -124,8 +124,21 @@ class ActionItem(RESTFrameworkModel):
# Models for reverse relations # Models for reverse relations
class Person(RESTFrameworkModel):
name = models.CharField(max_length=10)
age = models.IntegerField(null=True, blank=True)
@property
def info(self):
return {
'name': self.name,
'age': self.age,
}
class BlogPost(RESTFrameworkModel): class BlogPost(RESTFrameworkModel):
title = models.CharField(max_length=100) title = models.CharField(max_length=100)
writer = models.ForeignKey(Person, null=True, blank=True)
def get_first_comment(self): def get_first_comment(self):
return self.blogpostcomment_set.all()[0] return self.blogpostcomment_set.all()[0]
@ -145,18 +158,6 @@ class Photo(RESTFrameworkModel):
album = models.ForeignKey(Album) album = models.ForeignKey(Album)
class Person(RESTFrameworkModel):
name = models.CharField(max_length=10)
age = models.IntegerField(null=True, blank=True)
@property
def info(self):
return {
'name': self.name,
'age': self.age,
}
# Model for issue #324 # Model for issue #324
class BlankFieldModel(RESTFrameworkModel): class BlankFieldModel(RESTFrameworkModel):
title = models.CharField(max_length=100, blank=True) title = models.CharField(max_length=100, blank=True)

View File

@ -560,6 +560,47 @@ class ManyRelatedTests(TestCase):
self.assertEqual(serializer.data, expected) self.assertEqual(serializer.data, expected)
class RelatedTraversalTest(TestCase):
def test_nested_traversal(self):
user = Person.objects.create(name="django")
post = BlogPost.objects.create(title="Test blog post", writer=user)
post.blogpostcomment_set.create(text="I love this blog post")
from rest_framework.tests.models import BlogPostComment
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = ("name", "age")
class BlogPostCommentSerializer(serializers.ModelSerializer):
class Meta:
model = BlogPostComment
fields = ("text", "post_owner")
text = serializers.CharField()
post_owner = PersonSerializer(source='blog_post.writer')
class BlogPostSerializer(serializers.Serializer):
title = serializers.CharField()
comments = BlogPostCommentSerializer(source='blogpostcomment_set')
serializer = BlogPostSerializer(instance=post)
expected = {
'title': u'Test blog post',
'comments': [{
'text': u'I love this blog post',
'post_owner': {
"name": u"django",
"age": None
}
}]
}
self.assertEqual(serializer.data, expected)
class SerializerMethodFieldTests(TestCase): class SerializerMethodFieldTests(TestCase):
def setUp(self): def setUp(self):