Check for redundant on SerializerMethodField

This commit is contained in:
Tom Christie 2014-09-25 12:09:12 +01:00
parent 64632da371
commit b47ca158b9
2 changed files with 52 additions and 7 deletions

View File

@ -178,7 +178,7 @@ class Field(object):
# In order to enforce a consistent style, we error if a redundant # In order to enforce a consistent style, we error if a redundant
# 'source' argument has been used. For example: # 'source' argument has been used. For example:
# my_field = serializer.CharField(source='my_field') # my_field = serializer.CharField(source='my_field')
assert self._kwargs.get('source') != field_name, ( assert self.source != field_name, (
"It is redundant to specify `source='%s'` on field '%s' in " "It is redundant to specify `source='%s'` on field '%s' in "
"serializer '%s', because it is the same as the field name. " "serializer '%s', because it is the same as the field name. "
"Remove the `source` keyword argument." % "Remove the `source` keyword argument." %
@ -883,17 +883,32 @@ class SerializerMethodField(Field):
def get_extra_info(self, obj): def get_extra_info(self, obj):
return ... # Calculate some data to return. return ... # Calculate some data to return.
""" """
def __init__(self, method_attr=None, **kwargs): def __init__(self, method_name=None, **kwargs):
self.method_attr = method_attr self.method_name = method_name
kwargs['source'] = '*' kwargs['source'] = '*'
kwargs['read_only'] = True kwargs['read_only'] = True
super(SerializerMethodField, self).__init__(**kwargs) super(SerializerMethodField, self).__init__(**kwargs)
def bind(self, field_name, parent):
# In order to enforce a consistent style, we error if a redundant
# 'method_name' argument has been used. For example:
# my_field = serializer.CharField(source='my_field')
default_method_name = 'get_{field_name}'.format(field_name=field_name)
assert self.method_name != default_method_name, (
"It is redundant to specify `%s` on SerializerMethodField '%s' in "
"serializer '%s', because it is the same as the default method name. "
"Remove the `method_name` argument." %
(self.method_name, field_name, parent.__class__.__name__)
)
# The method name should default to `get_{field_name}`.
if self.method_name is None:
self.method_name = default_method_name
super(SerializerMethodField, self).bind(field_name, parent)
def to_representation(self, value): def to_representation(self, value):
method_attr = self.method_attr method = getattr(self.parent, self.method_name)
if method_attr is None:
method_attr = 'get_{field_name}'.format(field_name=self.field_name)
method = getattr(self.parent, method_attr)
return method(value) return method(value)

View File

@ -710,3 +710,33 @@ class TestMultipleChoiceField(FieldValues):
('diesel', 'Diesel'), ('diesel', 'Diesel'),
] ]
) )
# Tests for SerializerMethodField.
# --------------------------------
class TestSerializerMethodField:
def test_serializer_method_field(self):
class ExampleSerializer(serializers.Serializer):
example_field = serializers.SerializerMethodField()
def get_example_field(self, obj):
return 'ran get_example_field(%d)' % obj['example_field']
serializer = ExampleSerializer({'example_field': 123})
assert serializer.data == {
'example_field': 'ran get_example_field(123)'
}
def test_redundant_method_name(self):
class ExampleSerializer(serializers.Serializer):
example_field = serializers.SerializerMethodField('get_example_field')
with pytest.raises(AssertionError) as exc_info:
ExampleSerializer()
assert str(exc_info.value) == (
"It is redundant to specify `get_example_field` on "
"SerializerMethodField 'example_field' in serializer "
"'ExampleSerializer', because it is the same as the default "
"method name. Remove the `method_name` argument."
)