From 73553c99e06c4fd551c2bfe6d39997d80a3ea2bf Mon Sep 17 00:00:00 2001 From: Vincent Delaitre Date: Mon, 15 Oct 2018 15:12:55 +0200 Subject: [PATCH] Try second idea: call to_internal_value after validation --- rest_framework/serializers.py | 36 ++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 368450f51..b30c06c95 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -370,12 +370,6 @@ class Serializer(BaseSerializer): field for field in self.fields.values() if not field.read_only ] - @cached_property - def _read_only_fields(self): - return [ - field for field in self.fields.values() if field.read_only - ] - @cached_property def _readable_fields(self): return [ @@ -437,10 +431,11 @@ class Serializer(BaseSerializer): if is_empty_value: return data - value = self.to_internal_value(data) + value = self._to_primitive_value(data) try: self.run_validators(value) value = self.validate(value) + value = self.to_internal_value(value) assert value is not None, '.validate() should return the validated data' except (ValidationError, DjangoValidationError) as exc: raise ValidationError(detail=as_serializer_error(exc)) @@ -463,7 +458,15 @@ class Serializer(BaseSerializer): return defaults - def to_internal_value(self, data): + def run_validators(self, value): + """ + Add read_only fields with defaults to value before running validators. + """ + to_validate = self._read_only_defaults() + to_validate.update(value) + super(Serializer, self).run_validators(to_validate) + + def _to_primitive_value(self, data): """ Dict of native values <- Dict of primitive datatypes. """ @@ -477,11 +480,9 @@ class Serializer(BaseSerializer): ret = OrderedDict() errors = OrderedDict() - writable_fields = self._writable_fields - read_only_fields = self._read_only_fields - read_only_defaults = self._read_only_defaults() + fields = self._writable_fields - for field in writable_fields: + for field in fields: validate_method = getattr(self, 'validate_' + field.field_name, None) primitive_value = field.get_value(data) try: @@ -497,16 +498,17 @@ class Serializer(BaseSerializer): else: set_value(ret, field.source_attrs, validated_value) - for field in read_only_fields: - primitive_value = field.get_value(read_only_defaults) - if primitive_value is not empty: - set_value(ret, field.source_attrs, primitive_value) - if errors: raise ValidationError(errors) return ret + def to_internal_value(self, data): + """ + Converts a dict of primitive datatypes into the internal format + """ + return data + def to_representation(self, instance): """ Object instance -> Dict of primitive datatypes.