mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-02 20:54:42 +03:00
build_field, build_final_kwargs
This commit is contained in:
parent
94883ae7cd
commit
f72928ea98
|
@ -908,75 +908,92 @@ class ModelSerializer(Serializer):
|
||||||
ret[field_name] = declared_fields[field_name]
|
ret[field_name] = declared_fields[field_name]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
elif field_name in info.fields_and_pk:
|
# Determine the serializer field class and keyword arguments.
|
||||||
# Create regular model fields.
|
field_cls, kwargs = self.build_field(field_name, info, model, depth)
|
||||||
model_field = info.fields_and_pk[field_name]
|
|
||||||
field_cls = self._field_mapping[model_field]
|
|
||||||
kwargs = get_field_kwargs(field_name, model_field)
|
|
||||||
if 'choices' in kwargs:
|
|
||||||
# Fields with choices get coerced into `ChoiceField`
|
|
||||||
# instead of using their regular typed field.
|
|
||||||
field_cls = ChoiceField
|
|
||||||
if not issubclass(field_cls, ModelField):
|
|
||||||
# `model_field` is only valid for the fallback case of
|
|
||||||
# `ModelField`, which is used when no other typed field
|
|
||||||
# matched to the model field.
|
|
||||||
kwargs.pop('model_field', None)
|
|
||||||
if not issubclass(field_cls, CharField) and not issubclass(field_cls, ChoiceField):
|
|
||||||
# `allow_blank` is only valid for textual fields.
|
|
||||||
kwargs.pop('allow_blank', None)
|
|
||||||
|
|
||||||
elif field_name in info.relations:
|
|
||||||
# Create forward and reverse relationships.
|
|
||||||
relation_info = info.relations[field_name]
|
|
||||||
if depth:
|
|
||||||
field_cls = self._get_nested_class(depth, relation_info)
|
|
||||||
kwargs = get_nested_relation_kwargs(relation_info)
|
|
||||||
else:
|
|
||||||
field_cls = self._related_class
|
|
||||||
kwargs = get_relation_kwargs(field_name, relation_info)
|
|
||||||
# `view_name` is only valid for hyperlinked relationships.
|
|
||||||
if not issubclass(field_cls, HyperlinkedRelatedField):
|
|
||||||
kwargs.pop('view_name', None)
|
|
||||||
|
|
||||||
elif hasattr(model, field_name):
|
|
||||||
# Create a read only field for model methods and properties.
|
|
||||||
field_cls = ReadOnlyField
|
|
||||||
kwargs = {}
|
|
||||||
|
|
||||||
elif field_name == api_settings.URL_FIELD_NAME:
|
|
||||||
# Create the URL field.
|
|
||||||
field_cls = HyperlinkedIdentityField
|
|
||||||
kwargs = get_url_kwargs(model)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise ImproperlyConfigured(
|
|
||||||
'Field name `%s` is not valid for model `%s`.' %
|
|
||||||
(field_name, model.__class__.__name__)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Populate any kwargs defined in `Meta.extra_kwargs`
|
# Populate any kwargs defined in `Meta.extra_kwargs`
|
||||||
extras = extra_kwargs.get(field_name, {})
|
kwargs = self.build_final_kwargs(kwargs, extra_kwargs, field_name)
|
||||||
if extras.get('read_only', False):
|
|
||||||
for attr in [
|
|
||||||
'required', 'default', 'allow_blank', 'allow_null',
|
|
||||||
'min_length', 'max_length', 'min_value', 'max_value',
|
|
||||||
'validators', 'queryset'
|
|
||||||
]:
|
|
||||||
kwargs.pop(attr, None)
|
|
||||||
|
|
||||||
if extras.get('default') and kwargs.get('required') is False:
|
|
||||||
kwargs.pop('required')
|
|
||||||
|
|
||||||
kwargs.update(extras)
|
|
||||||
|
|
||||||
# Create the serializer field.
|
# Create the serializer field.
|
||||||
ret[field_name] = field_cls(**kwargs)
|
ret[field_name] = field_cls(**kwargs)
|
||||||
|
|
||||||
|
# Add in any hidden fields.
|
||||||
ret.update(hidden_fields)
|
ret.update(hidden_fields)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def build_field(self, field_name, info, model, depth):
|
||||||
|
if field_name in info.fields_and_pk:
|
||||||
|
# Create regular model fields.
|
||||||
|
model_field = info.fields_and_pk[field_name]
|
||||||
|
field_cls = self._field_mapping[model_field]
|
||||||
|
kwargs = get_field_kwargs(field_name, model_field)
|
||||||
|
if 'choices' in kwargs:
|
||||||
|
# Fields with choices get coerced into `ChoiceField`
|
||||||
|
# instead of using their regular typed field.
|
||||||
|
field_cls = ChoiceField
|
||||||
|
if not issubclass(field_cls, ModelField):
|
||||||
|
# `model_field` is only valid for the fallback case of
|
||||||
|
# `ModelField`, which is used when no other typed field
|
||||||
|
# matched to the model field.
|
||||||
|
kwargs.pop('model_field', None)
|
||||||
|
if not issubclass(field_cls, CharField) and not issubclass(field_cls, ChoiceField):
|
||||||
|
# `allow_blank` is only valid for textual fields.
|
||||||
|
kwargs.pop('allow_blank', None)
|
||||||
|
|
||||||
|
elif field_name in info.relations:
|
||||||
|
# Create forward and reverse relationships.
|
||||||
|
relation_info = info.relations[field_name]
|
||||||
|
if depth:
|
||||||
|
field_cls = self._get_nested_class(depth, relation_info)
|
||||||
|
kwargs = get_nested_relation_kwargs(relation_info)
|
||||||
|
else:
|
||||||
|
field_cls = self._related_class
|
||||||
|
kwargs = get_relation_kwargs(field_name, relation_info)
|
||||||
|
# `view_name` is only valid for hyperlinked relationships.
|
||||||
|
if not issubclass(field_cls, HyperlinkedRelatedField):
|
||||||
|
kwargs.pop('view_name', None)
|
||||||
|
|
||||||
|
elif hasattr(model, field_name):
|
||||||
|
# Create a read only field for model methods and properties.
|
||||||
|
field_cls = ReadOnlyField
|
||||||
|
kwargs = {}
|
||||||
|
|
||||||
|
elif field_name == api_settings.URL_FIELD_NAME:
|
||||||
|
# Create the URL field.
|
||||||
|
field_cls = HyperlinkedIdentityField
|
||||||
|
kwargs = get_url_kwargs(model)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
'Field name `%s` is not valid for model `%s`.' %
|
||||||
|
(field_name, model.__class__.__name__)
|
||||||
|
)
|
||||||
|
|
||||||
|
return field_cls, kwargs
|
||||||
|
|
||||||
|
def build_final_kwargs(self, kwargs, extra_kwargs, field_name):
|
||||||
|
"""
|
||||||
|
Include an 'extra_kwargs' that have been included for this field,
|
||||||
|
possibly removing any incompatible existing keyword arguments.
|
||||||
|
"""
|
||||||
|
extras = extra_kwargs.get(field_name, {})
|
||||||
|
|
||||||
|
if extras.get('read_only', False):
|
||||||
|
for attr in [
|
||||||
|
'required', 'default', 'allow_blank', 'allow_null',
|
||||||
|
'min_length', 'max_length', 'min_value', 'max_value',
|
||||||
|
'validators', 'queryset'
|
||||||
|
]:
|
||||||
|
kwargs.pop(attr, None)
|
||||||
|
|
||||||
|
if extras.get('default') and kwargs.get('required') is False:
|
||||||
|
kwargs.pop('required')
|
||||||
|
|
||||||
|
kwargs.update(extras)
|
||||||
|
|
||||||
|
return kwargs
|
||||||
|
|
||||||
def _get_model_fields(self, field_names, declared_fields, extra_kwargs):
|
def _get_model_fields(self, field_names, declared_fields, extra_kwargs):
|
||||||
"""
|
"""
|
||||||
Returns all the model fields that are being mapped to by fields
|
Returns all the model fields that are being mapped to by fields
|
||||||
|
|
Loading…
Reference in New Issue
Block a user