Release notes

This commit is contained in:
Tom Christie 2014-09-26 11:56:29 +01:00
parent 2859eaf524
commit 43e80c74b2
2 changed files with 75 additions and 7 deletions

View File

@ -4,12 +4,25 @@ See the [Version 3.0 GitHub issue](https://github.com/tomchristie/django-rest-fr
# REST framework 3.0
**TODO**: Note incremental nature, discuss upgrading, motivation, features.
The 3.0 release of Django REST framework is the result of almost four years of iteration and refinement. It comprehensively addresses some of the previous remaining design issues in serializers, fields and the generic views.
* Serializer reprs.
* Non-magical model serializers.
* Base serializer class.
* Clean logic in views, serializers, fields.
This release is incremental in nature. There *are* some breaking API changes, and upgrading *will* require you to read the release notes carefully, but the migration path should otherwise be relatively straightforward.
The difference in quality of the REST framework API and implementation should make writing, maintaining and debugging your application far easier.
## New features
Notable features of this new release include:
* Printable representations on serializers that allow you to inspect exactly what fields are present on the instance.
* Simple model serializers that are vastly easier to understand and debug, and that make it easy to switch between the implicit `ModelSerializer` class and the explicit `Serializer` class.
* A new `BaseSerializer` class, making it easier to write serializers for alternative storage backends, or to completely customize your serialization and validation logic.
* A cleaner fields API plus new `ListField` and `MultipleChoiceField` classes.
* Super simple default implementations for the generic views.
* Support for overriding how validation errors are handled by your API.
* A metadata API that allows you to customize how `OPTIONS` requests are handled by your API.
Below is an in-depth guide to the API changes and migration notes for 3.0.
---
@ -37,9 +50,59 @@ The usage of `request.QUERY_PARAMS` is now discouraged in favor of the lowercase
#### Single-step object creation.
Previously the serializers used a two-step object creation, as follows:
1. Validating the data would create an object instance. This instance would be available as `serializer.object`.
2. Calling `serializer.save()` would then save the object instance to the database.
This style is in line with how the `ModelForm` class works in Django, but is problematic for a number of reasons:
* Some data, such as many-to-many relationships, cannot be added to the object instance until after it has been save. This type of data needed to be hidden in some undocumentated state on the object instance, or kept as state on the serializer instance so that it could be used when `.save()` is called.
* Instantiating model instances directly means that you cannot use model manager classes for instance creation, eg `ExampleModel.objects.create(...)`. Manager classes are an excellent layer at which to enforce business logic and application-level data constraints.
* The two step process makes it unclear where to put deserialization logic. For example, should extra attributes such as the current user get added to the instance during object creation or during object save?
We now use single-step object creation, like so:
1. Validating the data makes the cleaned data available as `serializer.validated_data`.
2. Calling `serializer.save()` then saves and returns the new object instance.
The resulting API changes are further detailed below.
#### The `.create()` and `.update()` methods.
**TODO**: Drop `.restore_object()`, use `.create()` and `.update()` which should save the instance.
The `.restore_object()` method is now replaced with two seperate methods, `.create()` and `.update()`.
When using the `.create()` and `.update()` methods you should both create *and save* the object instance. This is in contrast to the previous `.restore_object()` behavior that would instantiate the object but not save it.
The following example from the tutorial previously used `restore_object()` to handle both creating and updating object instances.
def restore_object(self, attrs, instance=None):
if instance:
# Update existing instance
instance.title = attrs.get('title', instance.title)
instance.code = attrs.get('code', instance.code)
instance.linenos = attrs.get('linenos', instance.linenos)
instance.language = attrs.get('language', instance.language)
instance.style = attrs.get('style', instance.style)
return instance
# Create new instance
return Snippet(**attrs)
This would now be split out into two seperate methods.
def update(self, instance, validated_attrs)
instance.title = validated_attrs.get('title', instance.title)
instance.code = validated_attrs.get('code', instance.code)
instance.linenos = validated_attrs.get('linenos', instance.linenos)
instance.language = validated_attrs.get('language', instance.language)
instance.style = validated_attrs.get('style', instance.style)
instance.save()
def create(self, validated_attrs):
return Snippet.objects.create(**validated_attrs)
Note that the `.create` method should return the newly created object instance.
#### Use `.validated_data` instead of `.object`.
@ -457,7 +520,9 @@ This change means that you can now easily cusomize the style of error responses
## The metadata API
**TODO**
Behavior for dealing with `OPTIONS` requests was previously built directly into the class based views. This has now been properly seperated out into a Metadata API that allows the same pluggable style as other API policies in REST framework.
This makes it far easier to use a different style for `OPTIONS` responses throughout your API, and makes it possible to create third-party metadata policies.
## API style

View File

@ -75,6 +75,9 @@ class BaseSerializer(Field):
self.update(self.instance, validated_data)
else:
self.instance = self.create(validated_data)
assert self.instance is not None, (
'`create()` did not return an object instance.'
)
return self.instance