This commit is contained in:
Nadav Samet 2013-06-04 21:34:41 -07:00
commit 88dd3263c8
3 changed files with 24 additions and 1 deletions

View File

@ -20,7 +20,7 @@ Each serializer field class constructor takes at least these arguments. Some Fi
### `source`
The name of the attribute that will be used to populate the field. May be a method that only takes a `self` argument, such as `Field(source='get_absolute_url')`, or may use dotted notation to traverse attributes, such as `Field(source='user.email')`.
The name of the attribute that will be used to populate the field. May be a method that only takes a `self` argument, such as `Field(source='get_absolute_url')`, or may use dotted notation to traverse attributes, such as `Field(source='user.email')`. Alternatively, `source` can be a callable that takes a single argument (the object being serialized) and returns the value that will populate this field.
The value `source='*'` has a special meaning, and is used to indicate that the entire object should be passed through to the field. This can be useful for creating nested representations. (See the implementation of the `PaginationSerializer` class for an example.)

View File

@ -160,6 +160,9 @@ class Field(object):
source = self.source or field_name
value = obj
if callable(source):
return source(value)
for component in source.split('.'):
value = get_component(value, component)
if value is None:

View File

@ -803,6 +803,26 @@ class CallableDefaultValueTests(TestCase):
self.assertEqual(instance.text, 'overridden')
class CallableSourceTests(TestCase):
def setUp(self):
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField()
content = serializers.CharField(max_length=1000)
length = serializers.IntegerField(
source=lambda comment: len(comment.content),
read_only=True)
self.serializer_class = CommentSerializer
def test_callable_source(self):
instance = Comment('user@email.com', 'foobar', None)
serializer = self.serializer_class(instance=instance)
self.assertEquals(serializer.data, {
'email': 'user@email.com',
'content': 'foobar',
'length': 6
})
class ManyRelatedTests(TestCase):
def test_reverse_relations(self):
post = BlogPost.objects.create(title="Test blog post")