Merge pull request #1071 from craigds/field-transform-methods

Feature: add transform_<fieldname> methods to serializers
This commit is contained in:
Carlton Gibson 2013-10-09 01:11:46 -07:00
commit 0bbc775b95
3 changed files with 53 additions and 0 deletions

View File

@ -67,6 +67,21 @@ At this point we've translated the model instance into Python native datatypes.
json
# '{"email": "leila@example.com", "content": "foo bar", "created": "2012-08-22T16:20:09.822"}'
### Customizing field representation
Sometimes when serializing objects, you may not want to represent everything exactly the way it is in your model.
If you need to customize the serialized value of a particular field, you can do this by creating a `transform_<fieldname>` method. For example if you needed to render some markdown from a text field:
description = serializers.TextField()
description_html = serializers.TextField(source='description', read_only=True)
def transform_description_html(self, obj, value):
from django.contrib.markup.templatetags.markup import markdown
return markdown(value)
These methods are essentially the reverse of `validate_<fieldname>` (see *Validation* below.)
## Deserializing objects
Deserialization is similar. First we parse a stream into Python native datatypes...

View File

@ -307,6 +307,9 @@ class BaseSerializer(WritableField):
field.initialize(parent=self, field_name=field_name)
key = self.get_field_key(field_name)
value = field.field_to_native(obj, field_name)
method = getattr(self, 'transform_%s' % field_name, None)
if callable(method):
value = method(obj, value)
ret[key] = value
ret.fields[key] = field
return ret

View File

@ -1659,3 +1659,38 @@ class SerializerSupportsManyRelationships(TestCase):
serializer = SimpleSlugSourceModelSerializer(data={'text': 'foo', 'targets': [1, 2]})
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, {'text': 'foo', 'targets': [1, 2]})
class TransformMethodsSerializer(serializers.Serializer):
a = serializers.CharField()
b_renamed = serializers.CharField(source='b')
def transform_a(self, obj, value):
return value.lower()
def transform_b_renamed(self, obj, value):
if value is not None:
return 'and ' + value
class TestSerializerTransformMethods(TestCase):
def setUp(self):
self.s = TransformMethodsSerializer()
def test_transform_methods(self):
self.assertEqual(
self.s.to_native({'a': 'GREEN EGGS', 'b': 'HAM'}),
{
'a': 'green eggs',
'b_renamed': 'and HAM',
}
)
def test_missing_fields(self):
self.assertEqual(
self.s.to_native({'a': 'GREEN EGGS'}),
{
'a': 'green eggs',
'b_renamed': None,
}
)