diff options
Diffstat (limited to 'rest_framework/serializers.py')
| -rw-r--r-- | rest_framework/serializers.py | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 0727b8cd..459f8a8c 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -15,6 +15,7 @@ from django.core.exceptions import ValidationError from django.db import models from django.utils import six from collections import namedtuple, OrderedDict +from rest_framework.compat import clean_manytomany_helptext from rest_framework.fields import empty, set_value, Field, SkipField from rest_framework.settings import api_settings from rest_framework.utils import html, modelinfo, representation @@ -117,8 +118,9 @@ class SerializerMetaclass(type): """ This metaclass sets a dictionary named `base_fields` on the class. - Any fields included as attributes on either the class or it's superclasses - will be include in the `base_fields` dictionary. + Any instances of `Field` included as attributes on either the class + or on any of its superclasses will be include in the + `base_fields` dictionary. """ @classmethod @@ -379,6 +381,10 @@ class ModelSerializer(Serializer): info = modelinfo.get_field_info(self.opts.model) ret = OrderedDict() + serializer_url_field = self.get_url_field() + if serializer_url_field: + ret[api_settings.URL_FIELD_NAME] = serializer_url_field + serializer_pk_field = self.get_pk_field(info.pk) if serializer_pk_field: ret[info.pk.name] = serializer_pk_field @@ -404,6 +410,9 @@ class ModelSerializer(Serializer): return ret + def get_url_field(self): + return None + def get_pk_field(self, model_field): """ Returns a default instance of the pk field. @@ -446,13 +455,14 @@ class ModelSerializer(Serializer): if model_field: if model_field.null or model_field.blank: kwargs['required'] = False - # if model_field.help_text is not None: - # kwargs['help_text'] = model_field.help_text - if model_field.verbose_name is not None: + if model_field.verbose_name: kwargs['label'] = model_field.verbose_name if not model_field.editable: kwargs['read_only'] = True kwargs.pop('queryset', None) + help_text = clean_manytomany_helptext(model_field.help_text) + if help_text: + kwargs['help_text'] = help_text return PrimaryKeyRelatedField(**kwargs) @@ -469,6 +479,9 @@ class ModelSerializer(Serializer): if model_field.verbose_name is not None: kwargs['label'] = model_field.verbose_name + if model_field.help_text: + kwargs['help_text'] = model_field.help_text + if isinstance(model_field, models.AutoField) or not model_field.editable: kwargs['read_only'] = True # Read only implies that the field is not required. @@ -481,6 +494,14 @@ class ModelSerializer(Serializer): # We have a cleaner repr on the instance if we don't set it. kwargs.pop('required', None) + if model_field.flatchoices: + # If this model field contains choices, then use a ChoiceField, + # rather than the standard serializer field for this type. + # Note that we return this prior to setting any validation type + # keyword arguments, as those are not valid initializers. + kwargs['choices'] = model_field.flatchoices + return ChoiceField(**kwargs) + # Ensure that max_length is passed explicitly as a keyword arg, # rather than as a validator. max_length = getattr(model_field, 'max_length', None) @@ -561,23 +582,6 @@ class ModelSerializer(Serializer): if validator_kwarg: kwargs['validators'] = validator_kwarg - # if issubclass(model_field.__class__, models.TextField): - # kwargs['widget'] = widgets.Textarea - - # if model_field.help_text is not None: - # kwargs['help_text'] = model_field.help_text - - # TODO: TypedChoiceField? - if model_field.flatchoices: # This ModelField contains choices - kwargs['choices'] = model_field.flatchoices - if model_field.null: - kwargs['empty'] = None - return ChoiceField(**kwargs) - - if model_field.null and \ - issubclass(model_field.__class__, (models.CharField, models.TextField)): - kwargs['allow_none'] = True - try: return self.field_mapping[model_field.__class__](**kwargs) except KeyError: @@ -597,33 +601,24 @@ class HyperlinkedModelSerializerOptions(ModelSerializerOptions): class HyperlinkedModelSerializer(ModelSerializer): _options_class = HyperlinkedModelSerializerOptions - def get_default_fields(self): - fields = super(HyperlinkedModelSerializer, self).get_default_fields() - - if self.opts.view_name is None: - self.opts.view_name = self.get_default_view_name(self.opts.model) - - url_field_name = api_settings.URL_FIELD_NAME - if url_field_name not in fields: - ret = fields.__class__() - ret[url_field_name] = self.get_url_field() - ret.update(fields) - fields = ret - - return fields - - def get_pk_field(self, model_field): - if self.opts.fields and model_field.name in self.opts.fields: - return self.get_field(model_field) - def get_url_field(self): + if self.opts.view_name is not None: + view_name = self.opts.view_name + else: + view_name = self.get_default_view_name(self.opts.model) + kwargs = { - 'view_name': self.get_default_view_name(self.opts.model) + 'view_name': view_name } if self.opts.lookup_field: kwargs['lookup_field'] = self.opts.lookup_field + return HyperlinkedIdentityField(**kwargs) + def get_pk_field(self, model_field): + if self.opts.fields and model_field.name in self.opts.fields: + return self.get_field(model_field) + def get_related_field(self, model_field, related_model, to_many, has_through_model): """ Creates a default instance of a flat relational field. @@ -643,13 +638,14 @@ class HyperlinkedModelSerializer(ModelSerializer): if model_field: if model_field.null or model_field.blank: kwargs['required'] = False - # if model_field.help_text is not None: - # kwargs['help_text'] = model_field.help_text - if model_field.verbose_name is not None: + if model_field.verbose_name: kwargs['label'] = model_field.verbose_name if not model_field.editable: kwargs['read_only'] = True kwargs.pop('queryset', None) + help_text = clean_manytomany_helptext(model_field.help_text) + if help_text: + kwargs['help_text'] = help_text return HyperlinkedRelatedField(**kwargs) |
