diff options
Diffstat (limited to 'rest_framework/serializers.py')
| -rw-r--r-- | rest_framework/serializers.py | 72 |
1 files changed, 54 insertions, 18 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 7707de7a..ff5eb873 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -378,23 +378,27 @@ class BaseSerializer(WritableField): # Set the serializer object if it exists obj = getattr(self.parent.object, field_name) if self.parent.object else None - if value in (None, ''): - into[(self.source or field_name)] = None + if self.source == '*': + if value: + into.update(value) else: - kwargs = { - 'instance': obj, - 'data': value, - 'context': self.context, - 'partial': self.partial, - 'many': self.many - } - serializer = self.__class__(**kwargs) - - if serializer.is_valid(): - into[self.source or field_name] = serializer.object + if value in (None, ''): + into[(self.source or field_name)] = None else: - # Propagate errors up to our parent - raise NestedValidationError(serializer.errors) + kwargs = { + 'instance': obj, + 'data': value, + 'context': self.context, + 'partial': self.partial, + 'many': self.many + } + serializer = self.__class__(**kwargs) + + if serializer.is_valid(): + into[self.source or field_name] = serializer.object + else: + # Propagate errors up to our parent + raise NestedValidationError(serializer.errors) def get_identity(self, data): """ @@ -587,11 +591,16 @@ class ModelSerializer(Serializer): forward_rels += [field for field in opts.many_to_many if field.serialize] for model_field in forward_rels: + has_through_model = False + if model_field.rel: to_many = isinstance(model_field, models.fields.related.ManyToManyField) related_model = model_field.rel.to + if to_many and not model_field.rel.through._meta.auto_created: + has_through_model = True + if model_field.rel and nested: if len(inspect.getargspec(self.get_nested_field).args) == 2: warnings.warn( @@ -620,6 +629,9 @@ class ModelSerializer(Serializer): field = self.get_field(model_field) if field: + if has_through_model: + field.read_only = True + ret[model_field.name] = field # Deal with reverse relationships @@ -637,6 +649,12 @@ class ModelSerializer(Serializer): continue related_model = relation.model to_many = relation.field.rel.multiple + has_through_model = False + is_m2m = isinstance(relation.field, + models.fields.related.ManyToManyField) + + if is_m2m and not relation.field.rel.through._meta.auto_created: + has_through_model = True if nested: field = self.get_nested_field(None, related_model, to_many) @@ -644,6 +662,9 @@ class ModelSerializer(Serializer): field = self.get_related_field(None, related_model, to_many) if field: + if has_through_model: + field.read_only = True + ret[accessor_name] = field # Add the `read_only` flag to any fields that have bee specified @@ -705,15 +726,14 @@ class ModelSerializer(Serializer): Creates a default instance of a basic non-relational field. """ kwargs = {} - has_default = model_field.has_default() - if model_field.null or model_field.blank or has_default: + if model_field.null or model_field.blank: kwargs['required'] = False if isinstance(model_field, models.AutoField) or not model_field.editable: kwargs['read_only'] = True - if has_default: + if model_field.has_default(): kwargs['default'] = model_field.get_default() if issubclass(model_field.__class__, models.TextField): @@ -724,6 +744,22 @@ class ModelSerializer(Serializer): kwargs['choices'] = model_field.flatchoices return ChoiceField(**kwargs) + attribute_dict = { + models.CharField: ['max_length'], + models.CommaSeparatedIntegerField: ['max_length'], + models.DecimalField: ['max_digits', 'decimal_places'], + models.EmailField: ['max_length'], + models.FileField: ['max_length'], + models.ImageField: ['max_length'], + models.SlugField: ['max_length'], + models.URLField: ['max_length'], + } + + if model_field.__class__ in attribute_dict: + attributes = attribute_dict[model_field.__class__] + for attribute in attributes: + kwargs.update({attribute: getattr(model_field, attribute)}) + try: return self.field_mapping[model_field.__class__](**kwargs) except KeyError: |
