aboutsummaryrefslogtreecommitdiffstats
path: root/api-guide
diff options
context:
space:
mode:
authorTom Christie2014-12-05 09:44:35 +0000
committerTom Christie2014-12-05 09:44:35 +0000
commit6cce0681a9da20f46f57aa2c19796b4266c3d505 (patch)
treeaa29a4123d2de4fbef7d28cc9aa881c44546ed76 /api-guide
parent442f49eb5b8bfe6aebd599191482e2ffc532d87c (diff)
downloaddjango-rest-framework-6cce0681a9da20f46f57aa2c19796b4266c3d505.tar.bz2
Update documentation
Diffstat (limited to 'api-guide')
-rw-r--r--api-guide/fields/index.html45
-rw-r--r--api-guide/serializers/index.html21
2 files changed, 62 insertions, 4 deletions
diff --git a/api-guide/fields/index.html b/api-guide/fields/index.html
index 9b4ad3e3..46fa5f68 100644
--- a/api-guide/fields/index.html
+++ b/api-guide/fields/index.html
@@ -851,7 +851,7 @@ class UserSerializer(serializers.ModelSerializer):
<h1 id="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>
<h2 id="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):
"""
return obj.__class__.__name__
</code></pre>
+<h4 id="raising-validation-errors">Raising validation errors</h4>
+<p>Our <code>ColorField</code> class above currently does not perform any data validation.
+To indicate invalid data, we should raise a <code>serializers.ValidationError</code>, like so:</p>
+<pre><code>def to_internal_value(self, data):
+ if not isinstance(data, six.text_type):
+ msg = 'Incorrect type. Expected a string, but got %s'
+ raise ValidationError(msg % type(data).__name__)
+
+ if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
+ raise ValidationError('Incorrect format. Expected `rgb(#,#,#)`.')
+
+ data = data.strip('rgb(').rstrip(')')
+ red, green, blue = [int(col) for col in data.split(',')]
+
+ if any([col &gt; 255 or col &lt; 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}',
+ 'incorrect_format': 'Incorrect format. Expected `rgb(#,#,#)`.',
+ 'out_of_range': 'Value out of range. Must be between 0 and 255.'
+}
+
+def to_internal_value(self, data):
+ if not isinstance(data, six.text_type):
+ msg = 'Incorrect type. Expected a string, but got %s'
+ self.fail('incorrect_type', input_type=type(data).__name__)
+
+ if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
+ self.fail('incorrect_format')
+
+ data = data.strip('rgb(').rstrip(')')
+ red, green, blue = [int(col) for col in data.split(',')]
+
+ if any([col &gt; 255 or col &lt; 0 for col in (red, green, blue)]):
+ self.fail('out_of_range')
+
+ return Color(red, green, blue)
+</code></pre>
+<p>This style keeps you error messages more cleanly separated from your code, and should be preferred.</p>
<h1 id="third-party-packages">Third party packages</h1>
<p>The following third party packages are also available.</p>
<h2 id="drf-compound-fields">DRF Compound Fields</h2>
diff --git a/api-guide/serializers/index.html b/api-guide/serializers/index.html
index cbb4f32f..75c3f454 100644
--- a/api-guide/serializers/index.html
+++ b/api-guide/serializers/index.html
@@ -461,6 +461,10 @@
<a href="#customizing-multiple-update">Customizing multiple update</a>
</li>
+ <li>
+ <a href="#customizing-listserializer-initialization">Customizing ListSerializer initialization</a>
+ </li>
+
@@ -617,7 +621,7 @@ serializer.validated_data
</code></pre>
<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>
<pre><code> def create(self, validated_data):
- return Comment.objcts.create(**validated_data)
+ return Comment.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.email = validated_data.get('email', instance.email)
@@ -982,12 +986,12 @@ AccountSerializer():
<h2 id="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>
<pre><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Account
fields = ('account_url', 'account_name', 'users', 'created')
- extra_field_kwargs = {
+ extra_kwargs = {
'url': {'view_name': 'accounts', 'lookup_field': 'account_name'}
'users': {'lookup_field': 'username'}
}
@@ -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>
+<h4 id="customizing-listserializer-initialization">Customizing ListSerializer initialization</h4>
+<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 />
<h1 id="baseserializer">BaseSerializer</h1>
<p><code>BaseSerializer</code> class that can be used to easily support alternative serialization and deserialization styles.</p>