Notes on removal of Field.validate() and Serializer.transform_<field_name>

This commit is contained in:
Tom Christie 2014-11-27 17:01:46 +00:00
parent 0262262fee
commit c61c59f8b7

View File

@ -199,6 +199,33 @@ Alternatively if you want the errors to be against a specific field, use a dicti
This ensures you can still write validation that compares all the input fields, but that marks the error against a particular field.
#### Removal of `transform_<field_name>`.
The under-used `transform_<field_name>` on serializer classes is no longer provided. Instead you should just override `to_representation()` if you need to apply any modifications to the representation style.
For example:
def to_representation(self, instance):
ret = super(UserSerializer, self).to_representation(instance)
ret['username'] = ret['username'].lower()
return ret
Dropping the extra point of API means there's now only one right way to do things. This helps with repetition and reinforcement of the core API, rather than having multiple differing approaches.
If you absolutely need to preserve `transform_<field_name>` behavior, for example, in order to provide a simpler 2.x to 3.0 upgrade, you can use a mixin, or serializer base class that add the behavior back in. For example:
class BaseModelSerializer(ModelSerializer):
"""
A custom ModelSerializer class that preserves 2.x style `transform_<field_name>` behavior.
"""
def to_representation(self, instance):
ret = super(BaseModelSerializer, self).to_representation(instance)
for key, value in ret.items():
method = getattr(self, 'transform_' + key, None)
if method is not None:
ret[key] = method(value)
return ret
#### Differences between ModelSerializer validation and ModelForm.
This change also means that we no longer use the `.full_clean()` method on model instances, but instead perform all validation explicitly on the serializer. This gives a cleaner separation, and ensures that there's no automatic validation behavior on `ModelSerializer` classes that can't also be easily replicated on regular `Serializer` classes.
@ -544,6 +571,19 @@ The `default` argument is also available and always implies that the field is no
The previous field implementations did not forcibly coerce returned values into the correct type in many cases. For example, an `IntegerField` would return a string output if the attribute value was a string. We now more strictly coerce to the correct return type, leading to more constrained and expected behavior.
#### Removal of `.validate()`.
The `.validate()` method is now removed from field classes. This method was in any case undocumented and not public API. You should instead simply override `to_internal_value()`.
class UppercaseCharField(serializers.CharField):
def to_internal_value(self, data):
value = super(UppercaseCharField, self).to_internal_value(data)
if value != value.upper():
raise serializers.ValidationError('The input should be uppercase only.')
return value
Previously validation errors could be raised in either `.to_native()` or `.validate()`, making it non-obvious which should be used. Providing only a single point of API ensures more repetition and reinforcement of the core API.
#### The `ListField` class.
The `ListField` class has now been added. This field validates list input. It takes a `child` keyword argument which is used to specify the field used to validate each item in the list. For example: