From 0d354e8f92c7daaf8dac3b80f0fd64f983f21e0b Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 12 Sep 2014 09:49:35 +0100 Subject: [PATCH] to_internal_value() and to_representation() --- rest_framework/fields.py | 86 ++++++++++++++++++----------------- rest_framework/pagination.py | 4 +- rest_framework/relations.py | 2 +- rest_framework/serializers.py | 28 ++++++------ tests/test_validation.py | 2 +- 5 files changed, 62 insertions(+), 60 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 5f198767c..a96f9ba89 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -195,7 +195,7 @@ class Field(object): raise SkipField() return self.default - def validate_value(self, data=empty): + def run_validation(self, data=empty): """ Validate a simple representation and return the internal value. @@ -208,7 +208,7 @@ class Field(object): self.fail('required') return self.get_default() - value = self.to_native(data) + value = self.to_internal_value(data) self.run_validators(value) return value @@ -225,17 +225,17 @@ class Field(object): if errors: raise ValidationError(errors) - def to_native(self, data): + def to_internal_value(self, data): """ Transform the *incoming* primative data into a native value. """ - raise NotImplementedError('to_native() must be implemented.') + raise NotImplementedError('to_internal_value() must be implemented.') - def to_primative(self, value): + def to_representation(self, value): """ Transform the *outgoing* native value into primative data. """ - raise NotImplementedError('to_primative() must be implemented.') + raise NotImplementedError('to_representation() must be implemented.') def fail(self, key, **kwargs): """ @@ -279,14 +279,14 @@ class BooleanField(Field): return dictionary.get(self.field_name, False) return dictionary.get(self.field_name, empty) - def to_native(self, data): + def to_internal_value(self, data): if data in self.TRUE_VALUES: return True elif data in self.FALSE_VALUES: return False self.fail('invalid', input=data) - def to_primative(self, value): + def to_representation(self, value): if value is None: return None if value in self.TRUE_VALUES: @@ -309,12 +309,14 @@ class CharField(Field): self.min_length = kwargs.pop('min_length', None) super(CharField, self).__init__(**kwargs) - def to_native(self, data): + def to_internal_value(self, data): if data == '' and not self.allow_blank: self.fail('blank') + if data is None: + return None return str(data) - def to_primative(self, value): + def to_representation(self, value): if value is None: return None return str(value) @@ -326,17 +328,17 @@ class EmailField(CharField): } default_validators = [validators.validate_email] - def to_native(self, data): - ret = super(EmailField, self).to_native(data) - if ret is None: + def to_internal_value(self, data): + if data == '' and not self.allow_blank: + self.fail('blank') + if data is None: return None - return ret.strip() + return str(data).strip() - def to_primative(self, value): - ret = super(EmailField, self).to_primative(value) - if ret is None: + def to_representation(self, value): + if value is None: return None - return ret.strip() + return str(value).strip() class RegexField(CharField): @@ -378,14 +380,14 @@ class IntegerField(Field): if min_value is not None: self.validators.append(validators.MinValueValidator(min_value)) - def to_native(self, data): + def to_internal_value(self, data): try: data = int(str(data)) except (ValueError, TypeError): self.fail('invalid') return data - def to_primative(self, value): + def to_representation(self, value): if value is None: return None return int(value) @@ -405,7 +407,12 @@ class FloatField(Field): if min_value is not None: self.validators.append(validators.MinValueValidator(min_value)) - def to_primative(self, value): + def to_internal_value(self, value): + if value is None: + return None + return float(value) + + def to_representation(self, value): if value is None: return None try: @@ -413,11 +420,6 @@ class FloatField(Field): except (TypeError, ValueError): self.fail('invalid', value=value) - def to_native(self, value): - if value is None: - return None - return float(value) - class DecimalField(Field): default_error_messages = { @@ -439,7 +441,7 @@ class DecimalField(Field): if min_value is not None: self.validators.append(validators.MinValueValidator(min_value)) - def from_native(self, value): + def to_internal_value(self, value): """ Validates that the input is a decimal number. Returns a Decimal instance. Returns None for empty values. Ensures that there are no more @@ -485,7 +487,7 @@ class DecimalField(Field): return value - def to_primative(self, value): + def to_representation(self, value): if isinstance(value, decimal.Decimal): context = decimal.getcontext().copy() context.prec = self.max_digits @@ -516,7 +518,7 @@ class DateField(Field): self.format = format if format is not None else self.format super(DateField, self).__init__(*args, **kwargs) - def from_native(self, value): + def to_internal_value(self, value): if value in validators.EMPTY_VALUES: return None @@ -552,7 +554,7 @@ class DateField(Field): msg = self.error_messages['invalid'] % humanized_format raise ValidationError(msg) - def to_primative(self, value): + def to_representation(self, value): if value is None or self.format is None: return value @@ -576,7 +578,7 @@ class DateTimeField(Field): self.format = format if format is not None else self.format super(DateTimeField, self).__init__(*args, **kwargs) - def from_native(self, value): + def to_internal_value(self, value): if value in validators.EMPTY_VALUES: return None @@ -618,7 +620,7 @@ class DateTimeField(Field): msg = self.error_messages['invalid'] % humanized_format raise ValidationError(msg) - def to_primative(self, value): + def to_representation(self, value): if value is None or self.format is None: return value @@ -670,7 +672,7 @@ class TimeField(Field): msg = self.error_messages['invalid'] % humanized_format raise ValidationError(msg) - def to_primative(self, value): + def to_representation(self, value): if value is None or self.format is None: return value @@ -711,13 +713,13 @@ class ChoiceField(Field): super(ChoiceField, self).__init__(**kwargs) - def to_native(self, data): + def to_internal_value(self, data): try: return self.choice_strings_to_values[str(data)] except KeyError: self.fail('invalid_choice', input=data) - def to_primative(self, value): + def to_representation(self, value): return value @@ -727,15 +729,15 @@ class MultipleChoiceField(ChoiceField): 'not_a_list': _('Expected a list of items but got type `{input_type}`') } - def to_native(self, data): + def to_internal_value(self, data): if not hasattr(data, '__iter__'): self.fail('not_a_list', input_type=type(data).__name__) return set([ - super(MultipleChoiceField, self).to_native(item) + super(MultipleChoiceField, self).to_internal_value(item) for item in data ]) - def to_primative(self, value): + def to_representation(self, value): return value @@ -768,7 +770,7 @@ class ReadOnlyField(Field): kwargs['read_only'] = True super(ReadOnlyField, self).__init__(**kwargs) - def to_primative(self, value): + def to_representation(self, value): if is_simple_callable(value): return value() return value @@ -795,7 +797,7 @@ class SerializerMethodField(Field): kwargs['read_only'] = True super(SerializerMethodField, self).__init__(**kwargs) - def to_primative(self, value): + def to_representation(self, value): method_attr = self.method_attr if method_attr is None: method_attr = 'get_{field_name}'.format(field_name=self.field_name) @@ -815,13 +817,13 @@ class ModelField(Field): kwargs['source'] = '*' super(ModelField, self).__init__(**kwargs) - def to_native(self, data): + def to_internal_value(self, data): rel = getattr(self.model_field, 'rel', None) if rel is not None: return rel.to._meta.get_field(rel.field_name).to_python(data) return self.model_field.to_python(data) - def to_primative(self, obj): + def to_representation(self, obj): value = self.model_field._get_val_from_obj(obj) if is_protected_type(value): return value diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py index d82d2d3b3..c5a9270a4 100644 --- a/rest_framework/pagination.py +++ b/rest_framework/pagination.py @@ -13,7 +13,7 @@ class NextPageField(serializers.Field): """ page_field = 'page' - def to_primative(self, value): + def to_representation(self, value): if not value.has_next(): return None page = value.next_page_number() @@ -28,7 +28,7 @@ class PreviousPageField(serializers.Field): """ page_field = 'page' - def to_primative(self, value): + def to_representation(self, value): if not value.has_previous(): return None page = value.previous_page_number() diff --git a/rest_framework/relations.py b/rest_framework/relations.py index 661a1249a..30a252db9 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -110,7 +110,7 @@ class HyperlinkedIdentityField(RelatedField): def get_attribute(self, instance): return instance - def to_primative(self, value): + def to_representation(self, value): request = self.context.get('request', None) format = self.context.get('format', None) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 388fe29f0..502b1e190 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -47,11 +47,11 @@ class BaseSerializer(Field): self.instance = instance self._initial_data = data - def to_native(self, data): - raise NotImplementedError('`to_native()` must be implemented.') + def to_internal_value(self, data): + raise NotImplementedError('`to_internal_value()` must be implemented.') - def to_primative(self, instance): - raise NotImplementedError('`to_primative()` must be implemented.') + def to_representation(self, instance): + raise NotImplementedError('`to_representation()` must be implemented.') def update(self, instance, attrs): raise NotImplementedError('`update()` must be implemented.') @@ -74,7 +74,7 @@ class BaseSerializer(Field): def is_valid(self, raise_exception=False): if not hasattr(self, '_validated_data'): try: - self._validated_data = self.to_native(self._initial_data) + self._validated_data = self.to_internal_value(self._initial_data) except ValidationError as exc: self._validated_data = {} self._errors = exc.message_dict @@ -90,7 +90,7 @@ class BaseSerializer(Field): def data(self): if not hasattr(self, '_data'): if self.instance is not None: - self._data = self.to_primative(self.instance) + self._data = self.to_representation(self.instance) elif self._initial_data is not None: self._data = dict([ (field_name, field.get_value(self._initial_data)) @@ -193,7 +193,7 @@ class Serializer(BaseSerializer): return html.parse_html_dict(dictionary, prefix=self.field_name) return dictionary.get(self.field_name, empty) - def to_native(self, data): + def to_internal_value(self, data): """ Dict of native values <- Dict of primitive datatypes. """ @@ -208,7 +208,7 @@ class Serializer(BaseSerializer): validate_method = getattr(self, 'validate_' + field.field_name, None) primitive_value = field.get_value(data) try: - validated_value = field.validate_value(primitive_value) + validated_value = field.run_validation(primitive_value) if validate_method is not None: validated_value = validate_method(validated_value) except ValidationError as exc: @@ -226,7 +226,7 @@ class Serializer(BaseSerializer): except ValidationError as exc: raise ValidationError({'non_field_errors': exc.messages}) - def to_primative(self, instance): + def to_representation(self, instance): """ Object instance -> Dict of primitive datatypes. """ @@ -235,7 +235,7 @@ class Serializer(BaseSerializer): for field in fields: native_value = field.get_attribute(instance) - ret[field.field_name] = field.to_primative(native_value) + ret[field.field_name] = field.to_representation(native_value) return ret @@ -279,20 +279,20 @@ class ListSerializer(BaseSerializer): return html.parse_html_list(dictionary, prefix=self.field_name) return dictionary.get(self.field_name, empty) - def to_native(self, data): + def to_internal_value(self, data): """ List of dicts of native values <- List of dicts of primitive datatypes. """ if html.is_html_input(data): data = html.parse_html_list(data) - return [self.child.validate(item) for item in data] + return [self.child.run_validation(item) for item in data] - def to_primative(self, data): + def to_representation(self, data): """ List of object instances -> List of dicts of primitive datatypes. """ - return [self.child.to_primative(item) for item in data] + return [self.child.to_representation(item) for item in data] def create(self, attrs_list): return [self.child.create(attrs) for attrs in attrs_list] diff --git a/tests/test_validation.py b/tests/test_validation.py index c4506e7e9..7543d849b 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -158,7 +158,7 @@ class TestChoiceFieldChoicesValidate(TestCase): f = serializers.ChoiceField(choices=self.CHOICES) value = self.CHOICES[0][0] try: - f.to_native(value) + f.to_internal_value(value) except ValidationError: self.fail("Value %s does not validate" % str(value))