@@ -851,7 +851,7 @@ class UserSerializer(serializers.ModelSerializer):
<h1id="custom-fields">Custom fields</h1>
<p>If you want to create a custom field, you'll need to subclass <code>Field</code> and then override either one or both of the <code>.to_representation()</code> and <code>.to_internal_value()</code> methods. These two methods are used to convert between the initial datatype, and a primitive, serializable datatype. Primitive datatypes will typically be any of a number, string, boolean, <code>date</code>/<code>time</code>/<code>datetime</code> or <code>None</code>. They may also be any list or dictionary like object that only contains other primitive objects. Other types might be supported, depending on the renderer that you are using.</p>
<p>The <code>.to_representation()</code> method is called to convert the initial datatype into a primitive, serializable datatype.</p>
<p>The <code>to_internal_value()</code> method is called to restore a primitive datatype into its internal python representation.</p>
<p>The <code>to_internal_value()</code> method is called to restore a primitive datatype into its internal python representation. This method should raise a <code>serializer.ValidationError</code> if the data is invalid.</p>
<p>Note that the <code>WritableField</code> class that was present in version 2.x no longer exists. You should subclass <code>Field</code> and override <code>to_internal_value()</code> if the field supports data input.</p>
<h2id="examples">Examples</h2>
<p>Let's look at an example of serializing a class that represents an RGB color value:</p>
...
...
@@ -890,6 +890,49 @@ class ColorField(serializers.Field):
red, green, blue = [int(col) for col in data.split(',')]
if any([col > 255 or col < 0 for col in (red, green, blue)]):
raise ValidationError('Value out of range. Must be between 0 and 255.')
return Color(red, green, blue)
</code></pre>
<p>The <code>.fail()</code> method is a shortcut for raising <code>ValidationError</code> that takes a message string from the <code>error_messages</code> dictionary. For example:</p>
<pre><code>default_error_messages = {
'incorrect_type': 'Incorrect type. Expected a string, but got {input_type}',
<p>If your object instances correspond to Django models you'll also want to ensure that these methods save the object to the database. For example, if <code>Comment</code> was a Django model, the methods might look like this:</p>
<h2id="how-hyperlinked-views-are-determined">How hyperlinked views are determined</h2>
<p>There needs to be a way of determining which views should be used for hyperlinking to model instances.</p>
<p>By default hyperlinks are expected to correspond to a view name that matches the style <code>'{model_name}-detail'</code>, and looks up the instance by a <code>pk</code> keyword argument.</p>
<p>You can override a URL field view name and lookup field by using either, or both of, the <code>view_name</code> and <code>lookup_field</code> options in the <code>extra_field_kwargs</code> setting, like so:</p>
<p>You can override a URL field view name and lookup field by using either, or both of, the <code>view_name</code> and <code>lookup_field</code> options in the <code>extra_kwargs</code> setting, like so:</p>
@@ -1084,6 +1088,17 @@ class BookSerializer(serializers.Serializer):
list_serializer_class = BookListSerializer
</code></pre>
<p>It is possible that a third party package may be included alongside the 3.1 release that provides some automatic support for multiple update operations, similar to the <code>allow_add_remove</code> behavior that was present in REST framework 2.</p>
<p>When a serializer with <code>many=True</code> is instantiated, we need to determine which arguments and keyword arguments should be passed to the <code>.__init__()</code> method for both the child <code>Serializer</code> class, and for the parent <code>ListSerializer</code> class.</p>
<p>The default implementation is to pass all arguments to both classes, except for <code>validators</code>, and any custom keyword arguments, both of which are assumed to be intended for the child serializer class.</p>
<p>Occasionally you might need to explicitly specify how the child and parent classes should be instantiated when <code>many=True</code> is passed. You can do so by using the <code>many_init</code> class method.</p>
<pre><code> @classmethod
def many_init(cls, *args, **kwargs):
# Instantiate the child serializer.
kwargs['child'] = cls()
# Instantiate the parent list serializer.
return CustomListSerializer(*args, **kwargs)
</code></pre>
<hr/>
<h1id="baseserializer">BaseSerializer</h1>
<p><code>BaseSerializer</code> class that can be used to easily support alternative serialization and deserialization styles.</p>
<ahref="https://twitter.com/share"class="twitter-share-button"data-url="django-rest-framework.org"data-text="Checking out the totally awesome Django REST framework! http://www.django-rest-framework.org"data-count="none"></a>
<p>Django REST framework is a powerful and flexible toolkit that makes it easy to build Web APIs.</p>
<p>Some reasons you might want to use REST framework:</p>
<ul>
<li>The <ahref="http://restframework.herokuapp.com/">Web browseable API</a> is a huge usability win for your developers.</li>
<li>The <ahref="http://restframework.herokuapp.com/">Web browsable API</a> is a huge usability win for your developers.</li>
<li><ahref="api-guide/authentication/">Authentication policies</a> including <ahref="./api-guide/authentication#oauthauthentication">OAuth1a</a> and <ahref="./api-guide/authentication#oauth2authentication">OAuth2</a> out of the box.</li>
<li><ahref="api-guide/serializers/">Serialization</a> that supports both <ahref="./api-guide/serializers#modelserializer">ORM</a> and <ahref="./api-guide/serializers#serializers">non-ORM</a> data sources.</li>
<li>Customizable all the way down - just use <ahref="./api-guide/views#function-based-views">regular function-based views</a> if you don't need the <ahref="api-guide/generic-views/">more</a><ahref="api-guide/viewsets/">powerful</a><ahref="api-guide/routers/">features</a>.</li>
<p>In the unlikely event that you're providing a custom serializer class, and implementing these methods you should note the new call signature for both methods is now <code>(self, model_field, related_model, to_many)</code>. For reverse relationships <code>model_field</code> will be <code>None</code>.</p>
<p>The old-style signature will continue to function but will raise a <code>PendingDeprecationWarning</code>.</p>
<h2id="view-names-and-descriptions">View names and descriptions</h2>
<p>The mechanics of how the names and descriptions used in the browseable API are generated has been modified and cleaned up somewhat.</p>
<p>If you've been customizing this behavior, for example perhaps to use <code>rst</code> markup for the browseable API, then you'll need to take a look at the implementation to see what updates you need to make.</p>
<p>The mechanics of how the names and descriptions used in the browsable API are generated has been modified and cleaned up somewhat.</p>
<p>If you've been customizing this behavior, for example perhaps to use <code>rst</code> markup for the browsable API, then you'll need to take a look at the implementation to see what updates you need to make.</p>
<p>Note that the relevant methods have always been private APIs, and the docstrings called them out as intended to be deprecated.</p>
<p>Notice how similar the API is to working with forms. The similarity should become even more apparent when we start writing views that use our serializer.</p>
...
...
@@ -574,7 +574,7 @@ Open the file <code>snippets/serializers.py</code> again, and edit the <code>Sni
<p>One nice property that serializers have is that you can inspect all the fields in a serializer instance, by printing it's representation. Open the Django shell with <code>python manange.py shell</code>, then try the following:</p>
<pre><code>>>> from snippets.serializers import SnippetSerializer
>>> serializer = SnippetSerializer()
>>> print repr(serializer) # In python 3 use `print(repr(serializer))`
>>> print(repr(serializer))
SnippetSerializer():
id = IntegerField(label='ID', read_only=True)
title = CharField(allow_blank=True, max_length=100, required=False)
<p>Using viewsets can be a really useful abstraction. It helps ensure that URL conventions will be consistent across your API, minimizes the amount of code you need to write, and allows you to concentrate on the interactions and representations your API provides rather than the specifics of the URL conf.</p>
<p>That doesn't mean it's always the right approach to take. There's a similar set of trade-offs to consider as when using class-based views instead of function based views. Using viewsets is less explicit than building your views individually.</p>
<p>With an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browseable, and comes complete with authentication, per-object permissions, and multiple renderer formats.</p>
<p>With an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browsable, and comes complete with authentication, per-object permissions, and multiple renderer formats.</p>
<p>We've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views.</p>
<p>You can review the final <ahref="https://github.com/tomchristie/rest-framework-tutorial">tutorial code</a> on GitHub, or try out a live example in <ahref="http://restframework.herokuapp.com/">the sandbox</a>.</p>
<h2id="onwards-and-upwards">Onwards and upwards</h2>