get_field_names, get_default_field_names

This commit is contained in:
Tom Christie 2014-12-19 12:18:40 +00:00
parent ba753a7536
commit 6d907cde9a
2 changed files with 76 additions and 34 deletions

View File

@ -883,41 +883,14 @@ class ModelSerializer(Serializer):
ret = OrderedDict()
model = getattr(self.Meta, 'model')
fields = getattr(self.Meta, 'fields', None)
exclude = getattr(self.Meta, 'exclude', None)
depth = getattr(self.Meta, 'depth', 0)
extra_kwargs = getattr(self.Meta, 'extra_kwargs', {})
if fields and not isinstance(fields, (list, tuple)):
raise TypeError(
'The `fields` option must be a list or tuple. Got %s.' %
type(fields).__name__
)
if exclude and not isinstance(exclude, (list, tuple)):
raise TypeError(
'The `exclude` option must be a list or tuple. Got %s.' %
type(exclude).__name__
)
assert not (fields and exclude), "Cannot set both 'fields' and 'exclude'."
extra_kwargs = self._include_additional_options(extra_kwargs)
# Retrieve metadata about fields & relationships on the model class.
info = model_meta.get_field_info(model)
# Use the default set of field names if none is supplied explicitly.
if fields is None:
fields = self._get_default_field_names(declared_fields, info)
exclude = getattr(self.Meta, 'exclude', None)
if exclude is not None:
for field_name in exclude:
assert field_name in fields, (
'The field in the `exclude` option must be a model field. Got %s.' %
field_name
)
fields.remove(field_name)
fields = self.get_field_names(declared_fields, info)
# Determine the set of model fields, and the fields that they map to.
# We actually only need this to deal with the slightly awkward case
@ -1133,7 +1106,72 @@ class ModelSerializer(Serializer):
return extra_kwargs
def _get_default_field_names(self, declared_fields, model_info):
def get_field_names(self, declared_fields, info):
"""
Returns the list of all field names that should be created when
instantiating this serializer class. This is based on the default
set of fields, but also takes into account the `Meta.fields` or
`Meta.exclude` options if they have been specified.
"""
fields = getattr(self.Meta, 'fields', None)
exclude = getattr(self.Meta, 'exclude', None)
if fields and not isinstance(fields, (list, tuple)):
raise TypeError(
'The `fields` option must be a list or tuple. Got %s.' %
type(fields).__name__
)
if exclude and not isinstance(exclude, (list, tuple)):
raise TypeError(
'The `exclude` option must be a list or tuple. Got %s.' %
type(exclude).__name__
)
assert not (fields and exclude), (
"Cannot set both 'fields' and 'exclude' options on "
"serializer {serializer_class}.".format(
serializer_class=self.__class__.__name__
)
)
if fields is not None:
# Ensure that all declared fields have also been included in the
# `Meta.fields` option.
for field_name in declared_fields:
assert field_name in fields, (
"The field '{field_name}' was declared on serializer "
"{serializer_class}, but has not been included in the "
"'fields' option.".format(
field_name=field_name,
serializer_class=self.__class__.__name__
)
)
return fields
# Use the default set of field names if `Meta.fields` is not specified.
fields = self.get_default_field_names(declared_fields, info)
if exclude is not None:
# If `Meta.exclude` is included, then remove those fields.
for field_name in exclude:
assert field_name in fields, (
"The field '{field_name}' was include on serializer "
"{serializer_class} in the 'exclude' option, but does "
"not match any model field.".format(
field_name=field_name,
serializer_class=self.__class__.__name__
)
)
fields.remove(field_name)
return fields
def get_default_field_names(self, declared_fields, model_info):
"""
Return the default list of field names that will be used if the
`Meta.fields` option is not specified.
"""
return (
[model_info.pk.name] +
list(declared_fields.keys()) +
@ -1160,7 +1198,11 @@ class HyperlinkedModelSerializer(ModelSerializer):
"""
_related_class = HyperlinkedRelatedField
def _get_default_field_names(self, declared_fields, model_info):
def get_default_field_names(self, declared_fields, model_info):
"""
Return the default list of field names that will be used if the
`Meta.fields` option is not specified.
"""
return (
[api_settings.URL_FIELD_NAME] +
list(declared_fields.keys()) +

View File

@ -221,11 +221,11 @@ class TestRegularFieldMappings(TestCase):
model = RegularFieldsModel
fields = ('auto_field',)
with self.assertRaises(ImproperlyConfigured) as excinfo:
with self.assertRaises(AssertionError) as excinfo:
TestSerializer().fields
expected = (
'Field `missing` has been declared on serializer '
'`TestSerializer`, but is missing from `Meta.fields`.'
"The field 'missing' was declared on serializer TestSerializer, "
"but has not been included in the 'fields' option."
)
assert str(excinfo.exception) == expected
@ -607,5 +607,5 @@ class TestSerializerMetaClass(TestCase):
exception = result.exception
self.assertEqual(
str(exception),
"Cannot set both 'fields' and 'exclude'."
"Cannot set both 'fields' and 'exclude' options on serializer ExampleSerializer."
)