@@ -163,7 +163,7 @@ The `validate_<field_name>` method hooks that can be attached to serializer clas
...
@@ -163,7 +163,7 @@ The `validate_<field_name>` method hooks that can be attached to serializer clas
raise serializers.ValidationError('This field should be a multiple of ten.')
raise serializers.ValidationError('This field should be a multiple of ten.')
return attrs
return attrs
This is now simplified slightly, and the method hooks simply take the value to be validated, and return it's validated value.
This is now simplified slightly, and the method hooks simply take the value to be validated, and return the validated value.
def validate_score(self, value):
def validate_score(self, value):
if value % 10 != 0:
if value % 10 != 0:
...
@@ -172,6 +172,22 @@ This is now simplified slightly, and the method hooks simply take the value to b
...
@@ -172,6 +172,22 @@ This is now simplified slightly, and the method hooks simply take the value to b
Any ad-hoc validation that applies to more than one field should go in the `.validate(self, attrs)` method as usual.
Any ad-hoc validation that applies to more than one field should go in the `.validate(self, attrs)` method as usual.
Because `.validate_<field_name>` would previously accept the complete dictionary of attributes, it could be used to validate a field depending on the input in another field. Now if you need to do this you should use `.validate()` instead.
You can either return `non_field_errors` from the validate method by raising a simple `ValidationError`
def validate(self, attrs):
# serializer.errors == {'non_field_errors': ['A non field error']}
raise serailizers.ValidationError('A non field error')
Alternatively if you want the errors to be against a specific field, use a dictionary of when instantiating the `ValidationError`, like so:
def validate(self, attrs):
# serializer.errors == {'my_field': ['A field error']}
raise serailizers.ValidationError({'my_field': 'A field error'})
This ensures you can still write validation that compares all the input fields, but that marks the error against a particular field.
#### Limitations of ModelSerializer validation.
#### Limitations of ModelSerializer validation.
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.
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.
...
@@ -189,7 +205,32 @@ REST framework 2.x attempted to automatically support writable nested serializat
...
@@ -189,7 +205,32 @@ REST framework 2.x attempted to automatically support writable nested serializat
* It's unclear what behavior the user should expect when related models are passed `None` data.
* It's unclear what behavior the user should expect when related models are passed `None` data.
* It's unclear how the user should expect to-many relationships to handle updates, creations and deletions of multiple records.
* It's unclear how the user should expect to-many relationships to handle updates, creations and deletions of multiple records.
Using the `depth` option on `ModelSerializer` will now create **read-only nested serializers** by default. To use writable nested serialization you'll want to declare a nested field on the serializer class, and write the `create()` and/or `update()` methods explicitly.
Using the `depth` option on `ModelSerializer` will now create **read-only nested serializers** by default.
If you try to use a writable nested serializer without writing a custom `create()` and/or `update()` method you'll see an assertion error when you attempt to save the serializer. For example:
>>> class ProfileSerializer(serializers.ModelSerializer):
>>> class Meta:
>>> model = Profile
>>> fields = ('address', 'phone')
>>>
>>> class UserSerializer(serializers.ModelSerializer):
AssertionError: The `.create()` method does not suport nested writable fields by default. Write an explicit `.create()` method for serializer `UserSerializer`, or set `read_only=True` on nested serializer fields.
To use writable nested serialization you'll want to declare a nested field on the serializer class, and write the `create()` and/or `update()` methods explicitly.
class UserSerializer(serializers.ModelSerializer):
class UserSerializer(serializers.ModelSerializer):