From 6cce0681a9da20f46f57aa2c19796b4266c3d505 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 5 Dec 2014 09:44:35 +0000 Subject: Update documentation --- api-guide/fields/index.html | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'api-guide/fields') 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):
If you want to create a custom field, you'll need to subclass Field and then override either one or both of the .to_representation() and .to_internal_value() 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, date/time/datetime or None. 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.
The .to_representation() method is called to convert the initial datatype into a primitive, serializable datatype.
The to_internal_value() method is called to restore a primitive datatype into its internal python representation.
The to_internal_value() method is called to restore a primitive datatype into its internal python representation. This method should raise a serializer.ValidationError if the data is invalid.
Note that the WritableField class that was present in version 2.x no longer exists. You should subclass Field and override to_internal_value() if the field supports data input.
Let's look at an example of serializing a class that represents an RGB color value:
@@ -890,6 +890,49 @@ class ColorField(serializers.Field): """ return obj.__class__.__name__ +Our ColorField class above currently does not perform any data validation.
+To indicate invalid data, we should raise a serializers.ValidationError, like so:
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 > 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)
+
+The .fail() method is a shortcut for raising ValidationError that takes a message string from the error_messages dictionary. For example:
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 > 255 or col < 0 for col in (red, green, blue)]):
+ self.fail('out_of_range')
+
+ return Color(red, green, blue)
+
+This style keeps you error messages more cleanly separated from your code, and should be preferred.
The following third party packages are also available.