mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-06-20 05:23:18 +03:00
get_field_names, get_default_field_names
This commit is contained in:
parent
ba753a7536
commit
6d907cde9a
|
@ -883,41 +883,14 @@ class ModelSerializer(Serializer):
|
||||||
|
|
||||||
ret = OrderedDict()
|
ret = OrderedDict()
|
||||||
model = getattr(self.Meta, 'model')
|
model = getattr(self.Meta, 'model')
|
||||||
fields = getattr(self.Meta, 'fields', None)
|
|
||||||
exclude = getattr(self.Meta, 'exclude', None)
|
|
||||||
depth = getattr(self.Meta, 'depth', 0)
|
depth = getattr(self.Meta, 'depth', 0)
|
||||||
extra_kwargs = getattr(self.Meta, 'extra_kwargs', {})
|
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)
|
extra_kwargs = self._include_additional_options(extra_kwargs)
|
||||||
|
|
||||||
# Retrieve metadata about fields & relationships on the model class.
|
# Retrieve metadata about fields & relationships on the model class.
|
||||||
info = model_meta.get_field_info(model)
|
info = model_meta.get_field_info(model)
|
||||||
|
|
||||||
# Use the default set of field names if none is supplied explicitly.
|
fields = self.get_field_names(declared_fields, info)
|
||||||
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)
|
|
||||||
|
|
||||||
# Determine the set of model fields, and the fields that they map to.
|
# 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
|
# We actually only need this to deal with the slightly awkward case
|
||||||
|
@ -1133,7 +1106,72 @@ class ModelSerializer(Serializer):
|
||||||
|
|
||||||
return extra_kwargs
|
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 (
|
return (
|
||||||
[model_info.pk.name] +
|
[model_info.pk.name] +
|
||||||
list(declared_fields.keys()) +
|
list(declared_fields.keys()) +
|
||||||
|
@ -1160,7 +1198,11 @@ class HyperlinkedModelSerializer(ModelSerializer):
|
||||||
"""
|
"""
|
||||||
_related_class = HyperlinkedRelatedField
|
_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 (
|
return (
|
||||||
[api_settings.URL_FIELD_NAME] +
|
[api_settings.URL_FIELD_NAME] +
|
||||||
list(declared_fields.keys()) +
|
list(declared_fields.keys()) +
|
||||||
|
|
|
@ -221,11 +221,11 @@ class TestRegularFieldMappings(TestCase):
|
||||||
model = RegularFieldsModel
|
model = RegularFieldsModel
|
||||||
fields = ('auto_field',)
|
fields = ('auto_field',)
|
||||||
|
|
||||||
with self.assertRaises(ImproperlyConfigured) as excinfo:
|
with self.assertRaises(AssertionError) as excinfo:
|
||||||
TestSerializer().fields
|
TestSerializer().fields
|
||||||
expected = (
|
expected = (
|
||||||
'Field `missing` has been declared on serializer '
|
"The field 'missing' was declared on serializer TestSerializer, "
|
||||||
'`TestSerializer`, but is missing from `Meta.fields`.'
|
"but has not been included in the 'fields' option."
|
||||||
)
|
)
|
||||||
assert str(excinfo.exception) == expected
|
assert str(excinfo.exception) == expected
|
||||||
|
|
||||||
|
@ -607,5 +607,5 @@ class TestSerializerMetaClass(TestCase):
|
||||||
exception = result.exception
|
exception = result.exception
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
str(exception),
|
str(exception),
|
||||||
"Cannot set both 'fields' and 'exclude'."
|
"Cannot set both 'fields' and 'exclude' options on serializer ExampleSerializer."
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user