diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/topics/3.0-announcement.md | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 658b50d3..9aeb5df6 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -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.') 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): if value % 10 != 0: @@ -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. +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. 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 * 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. -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): + >>> profile = ProfileSerializer() + >>> class Meta: + >>> model = User + >>> fields = ('username', 'email', 'profile') + >>> + >>> data = { + >>> 'username': 'lizzy', + >>> 'email': 'lizzy@example.com', + >>> 'profile': {'address': '123 Acacia Avenue', 'phone': '01273 100200'} + >>> } + >>> + >>> serializer = UserSerializer(data=data) + >>> serializer.save() + 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): profile = ProfileSerializer() |
