From 4798df52df5d59cc570043e3eb7e26f7ce57b54f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 29 Sep 2014 12:57:05 +0100 Subject: [PATCH] Update release notes --- docs/topics/3.0-announcement.md | 44 +++++++++++++++++++++++++++++---- tests/test_validators.py | 1 - 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 24f4ed4c2..92062552a 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -146,7 +146,41 @@ The corresponding code would now look like this: extras = {'user': request.user} # Include the user when saving. serializer.save(extras=extras) -#### Printable serializer reprensentations. +#### 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 seperation, 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 comes with the following limitations: + +* The model `.clean()` method will not be called as part of serializer validation. Use the serializer `.validate()` method to perform a final validation step on incoming data where required. +* The `.unique_for_date`, `.unique_for_month` and `.unique_for_year` options on model fields are not automatically validated. Again, you'll need to handle these explicitly on the serializer if required. + +#### Writable nested serialization. + +REST framework 2.x attempted to automatically support writable nested serialization, but the behavior was complex and non-obvious. Attempting to automatically handle these case is problematic: + +* There can be complex dependancies involved in order of saving multiple related model instances. +* 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. + + class UserSerializer(serializers.ModelSerializer): + profile = ProfileSerializer() + + class Meta: + model = User + fields = ('username', 'email', 'profile') + + def create(self, validated_data): + profile_data = validated_data.pop['profile'] + user = User.objects.create(**validated_data) + profile = Profile.objects.create(user=user, **profile_data) + return user + +The single-step object creation makes this far simpler and more obvious than the previous `.restore_object()` behavior. + +#### Printable serializer representations. Serializer instances now support a printable representation that allows you to inspect the fields present on the instance. @@ -279,7 +313,7 @@ There are four mathods that can be overriding, depending on what functionality y * `.to_internal_value()` - Override this to support deserialization, for write operations. * `.create()` and `.update()` - Overide either or both of these to support saving instances. -##### Read-only serializers. +##### Read-only `BaseSerializer` classes. To implement a read-only serializer using the `BaseSerializer` class, we just need to override the `.to_representation()` method. Let's take a look at an example using a simple Django model: @@ -313,7 +347,7 @@ Or use it to serialize multiple instances: serializer = HighScoreSerializer(queryset, many=True) return Response(serializer.data) -##### Read-write serializers. +##### Read-write `BaseSerializer` classes. To create a read-write serializer we first need to implement a `.to_internal_value()` method. This method returns the validated values that will be used to construct the object instance, and may raise a `ValidationError` if the supplied data is in an incorrect format. @@ -358,9 +392,9 @@ Here's a complete example of our previous `HighScoreSerializer`, that's been upd def create(self, validated_data): return HighScore.objects.create(**validated_data) -#### Creating new base classes with `BaseSerializer`. +#### Creating new generic serializers with `BaseSerializer`. -The `BaseSerializer` class is also useful if you want to implement new generic serializer classes for dealing with particular serialization styles or for integrating with different storage backends. +The `BaseSerializer` class is also useful if you want to implement new generic serializer classes for dealing with particular serialization styles, or for integrating with alternative storage backends. The following class is an example of a generic serializer that can handle coercing aribitrary objects into primative representations. diff --git a/tests/test_validators.py b/tests/test_validators.py index c35ecb514..ac04d2b4c 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -98,7 +98,6 @@ class TestUniquenessTogetherValidation(TestCase): """ data = {'race_name': 'example', 'position': 2} serializer = UniquenessTogetherSerializer(data=data) - print serializer.validators assert not serializer.is_valid() assert serializer.errors == { 'non_field_errors': [