aboutsummaryrefslogtreecommitdiffstats
path: root/docs/api-guide
diff options
context:
space:
mode:
Diffstat (limited to 'docs/api-guide')
-rwxr-xr-xdocs/api-guide/authentication.md5
-rw-r--r--docs/api-guide/fields.md22
-rwxr-xr-xdocs/api-guide/generic-views.md20
-rw-r--r--docs/api-guide/metadata.md103
-rw-r--r--docs/api-guide/permissions.md14
-rw-r--r--docs/api-guide/relations.md2
-rw-r--r--docs/api-guide/renderers.md29
-rw-r--r--docs/api-guide/requests.md14
-rw-r--r--docs/api-guide/serializers.md10
-rw-r--r--docs/api-guide/settings.md58
-rw-r--r--docs/api-guide/throttling.md6
-rw-r--r--docs/api-guide/validators.md225
12 files changed, 463 insertions, 45 deletions
diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md
index b355012e..01774c10 100755
--- a/docs/api-guide/authentication.md
+++ b/docs/api-guide/authentication.md
@@ -168,12 +168,13 @@ The `curl` command line tool may be useful for testing token authenticated APIs.
If you want every user to have an automatically generated Token, you can simply catch the User's `post_save` signal.
+ from django.conf import settings
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
- @receiver(post_save, sender=get_user_model())
+ @receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
@@ -397,7 +398,7 @@ HTTP digest authentication is a widely implemented scheme that was intended to r
## Django OAuth Toolkit
-The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by [Evonove][evonove] and uses the excelllent [OAuthLib][oauthlib]. The package is well documented, and comes as a recommended alternative for OAuth 2.0 support.
+The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by [Evonove][evonove] and uses the excellent [OAuthLib][oauthlib]. The package is well documented, and comes as a recommended alternative for OAuth 2.0 support.
## Django OAuth2 Consumer
diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md
index bfbff2ad..292a51d8 100644
--- a/docs/api-guide/fields.md
+++ b/docs/api-guide/fields.md
@@ -274,7 +274,27 @@ Corresponds to `django.db.models.fields.FloatField`.
## DecimalField
-A decimal representation.
+A decimal representation, represented in Python by a Decimal instance.
+
+Has two required arguments:
+
+- `max_digits` The maximum number of digits allowed in the number. Note that this number must be greater than or equal to decimal_places.
+
+- `decimal_places` The number of decimal places to store with the number.
+
+For example, to validate numbers up to 999 with a resolution of 2 decimal places, you would use:
+
+ serializers.DecimalField(max_digits=5, decimal_places=2)
+
+And to validate numbers up to anything less than one billion with a resolution of 10 decimal places:
+
+ serializers.DecimalField(max_digits=19, decimal_places=10)
+
+This field also takes an optional argument, `coerce_to_string`. If set to `True` the representation will be output as a string. If set to `False` the representation will be left as a `Decimal` instance and the final representation will be determined by the renderer.
+
+If unset, this will default to the same value as the `COERCE_DECIMAL_TO_STRING` setting, which is `True` unless set otherwise.
+
+**Signature:** `DecimalField(max_digits, decimal_places, coerce_to_string=None)`
Corresponds to `django.db.models.fields.DecimalField`.
diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md
index b1c4e65a..49a5e58f 100755
--- a/docs/api-guide/generic-views.md
+++ b/docs/api-guide/generic-views.md
@@ -19,8 +19,8 @@ Typically when using the generic views, you'll override the view, and set severa
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
- from rest_framework import generics
- from rest_framework.permissions import IsAdminUser
+ from rest_framework import generics
+ from rest_framework.permissions import IsAdminUser
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
@@ -212,8 +212,6 @@ Provides a `.list(request, *args, **kwargs)` method, that implements listing a q
If the queryset is populated, this returns a `200 OK` response, with a serialized representation of the queryset as the body of the response. The response data may optionally be paginated.
-If the queryset is empty this returns a `200 OK` response, unless the `.allow_empty` attribute on the view is set to `False`, in which case it will return a `404 Not Found`.
-
## CreateModelMixin
Provides a `.create(request, *args, **kwargs)` method, that implements creating and saving a new model instance.
@@ -370,6 +368,20 @@ If you are using a mixin across multiple views, you can take this a step further
Using custom base classes is a good option if you have custom behavior that consistently needs to be repeated across a large number of views throughout your project.
+---
+
+# PUT as create
+
+Prior to version 3.0 the REST framework mixins treated `PUT` as either an update or a create operation, depending on if the object already existed or not.
+
+Allowing `PUT` as create operations is problematic, as it necessarily exposes information about the existence or non-existence of objects. It's also not obvious that transparently allowing re-creating of previously deleted instances is necessarily a better default behavior than simply returning `404` responses.
+
+Both styles "`PUT` as 404" and "`PUT` as create" can be valid in different circumstances, but from version 3.0 onwards we now use 404 behavior as the default, due to it being simpler and more obvious.
+
+If you need to generic PUT-as-create behavior you may want to include something like [this `AllowPUTAsCreateMixin` class](https://gist.github.com/tomchristie/a2ace4577eff2c603b1b) as a mixin to your views.
+
+---
+
# Third party packages
The following third party packages provide additional generic view implementations.
diff --git a/docs/api-guide/metadata.md b/docs/api-guide/metadata.md
new file mode 100644
index 00000000..c3f036b7
--- /dev/null
+++ b/docs/api-guide/metadata.md
@@ -0,0 +1,103 @@
+<a class="github" href="metadata.py"></a>
+
+# Metadata
+
+> [The `OPTIONS`] method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.
+>
+> &mdash; [RFC7231, Section 4.3.7.][cite]
+
+REST framework includes a configurable mechanism for determining how your API should respond to `OPTIONS` requests. This allows you to return API schema or other resource information.
+
+There are not currently any widely adopted conventions for exactly what style of response should be returned for HTTP `OPTIONS` requests, so we provide an ad-hoc style that returns some useful information.
+
+Here's an example response that demonstrates the information that is returned by default.
+
+ HTTP 200 OK
+ Allow: GET, POST, HEAD, OPTIONS
+ Content-Type: application/json
+
+ {
+ "name": "To Do List",
+ "description": "List existing 'To Do' items, or create a new item.",
+ "renders": [
+ "application/json",
+ "text/html"
+ ],
+ "parses": [
+ "application/json",
+ "application/x-www-form-urlencoded",
+ "multipart/form-data"
+ ],
+ "actions": {
+ "POST": {
+ "note": {
+ "type": "string",
+ "required": false,
+ "read_only": false,
+ "label": "title",
+ "max_length": 100
+ }
+ }
+ }
+ }
+
+## Setting the metadata scheme
+
+You can set the metadata class globally using the `'DEFAULT_METADATA_CLASS'` settings key:
+
+ REST_FRAMEWORK = {
+ 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata'
+ }
+
+Or you can set the metadata class individually for a view:
+
+ class APIRoot(APIView):
+ metadata_class = APIRootMetadata
+
+ def get(self, request, format=None):
+ return Response({
+ ...
+ })
+
+The REST framework package only includes a single metadata class implementation, named `SimpleMetadata`. If you want to use an alternative style you'll need to implement a custom metadata class.
+
+## Creating schema endpoints
+
+If you have specific requirements for creating schema endpoints that are accessed with regular `GET` requests, you might consider re-using the metadata API for doing so.
+
+For example, the following additional route could be used on a viewset to provide a linkable schema endpoint.
+
+ @list_route(methods=['GET'])
+ def schema(self, request):
+ meta = self.metadata_class()
+ data = meta.determine_metadata(request, self)
+ return Response(data)
+
+There are a couple of reasons that you might choose to take this approach, including that `OPTIONS` responses [are not cacheable][no-options].
+
+---
+
+# Custom metadata classes
+
+If you want to provide a custom metadata class you should override `BaseMetadata` and implement the `determine_metadata(self, request, view)` method.
+
+Useful things that you might want to do could include returning schema information, using a format such as [JSON schema][json-schema], or returning debug information to admin users.
+
+## Example
+
+The following class could be used to limit the information that is returned to `OPTIONS` requests.
+
+ class MinimalMetadata(BaseMetadata):
+ """
+ Don't include field and other information for `OPTIONS` requests.
+ Just return the name and description.
+ """
+ def determine_metadata(self, request, view):
+ return {
+ 'name': view.get_view_name(),
+ 'description': view.get_view_description()
+ }
+
+[cite]: http://tools.ietf.org/html/rfc7231#section-4.3.7
+[no-options]: https://www.mnot.net/blog/2012/10/29/NO_OPTIONS
+[json-schema]: http://json-schema.org/
diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md
index e867a456..446e362e 100644
--- a/docs/api-guide/permissions.md
+++ b/docs/api-guide/permissions.md
@@ -146,7 +146,13 @@ As with `DjangoModelPermissions`, this permission must only be applied to views
Note that `DjangoObjectPermissions` **does not** require the `django-guardian` package, and should support other object-level backends equally well.
-As with `DjangoModelPermissions` you can use custom model permissions by overriding `DjangoModelPermissions` and setting the `.perms_map` property. Refer to the source code for details. Note that if you add a custom `view` permission for `GET`, `HEAD` and `OPTIONS` requests, you'll probably also want to consider adding the `DjangoObjectPermissionsFilter` class to ensure that list endpoints only return results including objects for which the user has appropriate view permissions.
+As with `DjangoModelPermissions` you can use custom model permissions by overriding `DjangoModelPermissions` and setting the `.perms_map` property. Refer to the source code for details.
+
+---
+
+**Note**: If you need object level `view` permissions for `GET`, `HEAD` and `OPTIONS` requests, you'll want to consider also adding the `DjangoObjectPermissionsFilter` class to ensure that list endpoints only return results including objects for which the user has appropriate view permissions.
+
+---
## TokenHasReadWriteScope
@@ -183,11 +189,7 @@ If you need to test if a request is a read operation or a write operation, you s
---
-**Note**: In versions 2.0 and 2.1, the signature for the permission checks always included an optional `obj` parameter, like so: `.has_permission(self, request, view, obj=None)`. The method would be called twice, first for the global permission checks, with no object supplied, and second for the object-level check when required.
-
-As of version 2.2 this signature has now been replaced with two separate method calls, which is more explicit and obvious. The old style signature continues to work, but its use will result in a `PendingDeprecationWarning`, which is silent by default. In 2.3 this will be escalated to a `DeprecationWarning`, and in 2.4 the old-style signature will be removed.
-
-For more details see the [2.2 release announcement][2.2-announcement].
+**Note**: The instance-level `has_object_permission` method will only be called if the view-level `has_permission` checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call `.check_object_permissions(request, obj)`. If you are using the generic views then this will be handled for you by default.
---
diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md
index cc4f5585..d03a75ae 100644
--- a/docs/api-guide/relations.md
+++ b/docs/api-guide/relations.md
@@ -202,7 +202,7 @@ This field is always read-only.
**Arguments**:
-* `view_name` - The view name that should be used as the target of the relationship. If you're using [the standard router classes][routers] this wil be a string with the format `<model_name>-detail`. **required**.
+* `view_name` - The view name that should be used as the target of the relationship. If you're using [the standard router classes][routers] this will be a string with the format `<model_name>-detail`. **required**.
* `lookup_field` - The field on the target that should be used for the lookup. Should correspond to a URL keyword argument on the referenced view. Default is `'pk'`.
* `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument.
diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md
index 20eed70d..db7436c2 100644
--- a/docs/api-guide/renderers.md
+++ b/docs/api-guide/renderers.md
@@ -74,37 +74,18 @@ If your API includes views that can serve both regular webpages and API response
Renders the request data into `JSON`, using utf-8 encoding.
-Note that non-ascii characters will be rendered using JSON's `\uXXXX` character escape. For example:
+Note that the default style is to include unicode characters, and render the response using a compact style with no unnecessary whitespace:
- {"unicode black star": "\u2605"}
+ {"unicode black star":"★","value":999}
The client may additionally include an `'indent'` media type parameter, in which case the returned `JSON` will be indented. For example `Accept: application/json; indent=4`.
{
- "unicode black star": "\u2605"
+ "unicode black star": "★",
+ "value": 999
}
-**.media_type**: `application/json`
-
-**.format**: `'.json'`
-
-**.charset**: `None`
-
-## UnicodeJSONRenderer
-
-Renders the request data into `JSON`, using utf-8 encoding.
-
-Note that non-ascii characters will not be character escaped. For example:
-
- {"unicode black star": "★"}
-
-The client may additionally include an `'indent'` media type parameter, in which case the returned `JSON` will be indented. For example `Accept: application/json; indent=4`.
-
- {
- "unicode black star": "★"
- }
-
-Both the `JSONRenderer` and `UnicodeJSONRenderer` styles conform to [RFC 4627][rfc4627], and are syntactically valid JSON.
+The default JSON encoding style can be altered using the `UNICODE_JSON` and `COMPACT_JSON` settings keys.
**.media_type**: `application/json`
diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md
index 0696fedf..87425ed1 100644
--- a/docs/api-guide/requests.md
+++ b/docs/api-guide/requests.md
@@ -49,6 +49,20 @@ If a client sends a request with a content-type that cannot be parsed then a `Un
---
+# Content negotiation
+
+The request exposes some properties that allow you to determine the result of the content negotiation stage. This allows you to implement behaviour such as selecting a different serialisation schemes for different media types.
+
+## .accepted_renderer
+
+The renderer instance what was selected by the content negotiation stage.
+
+## .accepted_media_type
+
+A string representing the media type that was accepted by the content negotiation stage.
+
+---
+
# Authentication
REST framework provides flexible, per-request authentication, that gives you the ability to:
diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md
index a3694510..eeeffa13 100644
--- a/docs/api-guide/serializers.md
+++ b/docs/api-guide/serializers.md
@@ -413,6 +413,16 @@ Alternative representations include serializing using hyperlinks, serializing co
For full details see the [serializer relations][relations] documentation.
+## Inheritance of the 'Meta' class
+
+The inner `Meta` class on serializers is not inherited from parent classes by default. This is the same behaviour as with Django's `Model` and `ModelForm` classes. If you want the `Meta` class to inherit from a parent class you must do so explicitly. For example:
+
+ class AccountSerializer(MyBaseSerializer):
+ class Meta(MyBaseSerializer.Meta):
+ model = Account
+
+Typically we would recommend *not* using inheritance on inner Meta classes, but instead declaring all options explicitly.
+
---
# HyperlinkedModelSerializer
diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md
index 27a09163..48af30a5 100644
--- a/docs/api-guide/settings.md
+++ b/docs/api-guide/settings.md
@@ -154,13 +154,13 @@ Default: `None`
### SEARCH_PARAM
-The name of a query paramater, which can be used to specify the search term used by `SearchFilter`.
+The name of a query parameter, which can be used to specify the search term used by `SearchFilter`.
Default: `search`
#### ORDERING_PARAM
-The name of a query paramater, which can be used to specify the ordering of results returned by `OrderingFilter`.
+The name of a query parameter, which can be used to specify the ordering of results returned by `OrderingFilter`.
Default: `ordering`
@@ -265,7 +265,7 @@ A format string that should be used by default for rendering the output of `Date
May be any of `None`, `'iso-8601'` or a Python [strftime format][strftime] string.
-Default: `None`
+Default: `'iso-8601'`
#### DATETIME_INPUT_FORMATS
@@ -281,7 +281,7 @@ A format string that should be used by default for rendering the output of `Date
May be any of `None`, `'iso-8601'` or a Python [strftime format][strftime] string.
-Default: `None`
+Default: `'iso-8601'`
#### DATE_INPUT_FORMATS
@@ -297,7 +297,7 @@ A format string that should be used by default for rendering the output of `Time
May be any of `None`, `'iso-8601'` or a Python [strftime format][strftime] string.
-Default: `None`
+Default: `'iso-8601'`
#### TIME_INPUT_FORMATS
@@ -309,6 +309,46 @@ Default: `['iso-8601']`
---
+## Encodings
+
+#### UNICODE_JSON
+
+When set to `True`, JSON responses will allow unicode characters in responses. For example:
+
+ {"unicode black star":"★"}
+
+When set to `False`, JSON responses will escape non-ascii characters, like so:
+
+ {"unicode black star":"\u2605"}
+
+Both styles conform to [RFC 4627][rfc4627], and are syntactically valid JSON. The unicode style is preferred as being more user-friendly when inspecting API responses.
+
+Default: `True`
+
+#### COMPACT_JSON
+
+When set to `True`, JSON responses will return compact representations, with no spacing after `':'` and `','` characters. For example:
+
+ {"is_admin":false,"email":"jane@example"}
+
+When set to `False`, JSON responses will return slightly more verbose representations, like so:
+
+ {"is_admin": false, "email": "jane@example"}
+
+The default style is to return minified responses, in line with [Heroku's API design guidelines][heroku-minified-json].
+
+Default: `True`
+
+#### COERCE_DECIMAL_TO_STRING
+
+When returning decimal objects in API representations that do not support a native decimal type, it is normally best to return the value as a string. This avoids the loss of precision that occurs with binary floating point implementations.
+
+When set to `True`, the serializer `DecimalField` class will return strings instead of `Decimal` objects. When set to `False`, serializers will return `Decimal` objects, which the default JSON encoder will return as floats.
+
+Default: `True`
+
+---
+
## View names and descriptions
**The following settings are used to generate the view names and descriptions, as used in responses to `OPTIONS` requests, and as used in the browsable API.**
@@ -359,6 +399,12 @@ This should be a function with the following signature:
Default: `'rest_framework.views.exception_handler'`
+#### NON_FIELD_ERRORS_KEY
+
+A string representing the key that should be used for serializer errors that do not refer to a specific field, but are instead general errors.
+
+Default: `'non_field_errors'`
+
#### URL_FIELD_NAME
A string representing the key that should be used for the URL fields generated by `HyperlinkedModelSerializer`.
@@ -378,4 +424,6 @@ An integer of 0 or more, that may be used to specify the number of application p
Default: `None`
[cite]: http://www.python.org/dev/peps/pep-0020/
+[rfc4627]: http://www.ietf.org/rfc/rfc4627.txt
+[heroku-minified-json]: https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses
[strftime]: http://docs.python.org/2/library/time.html#time.strftime
diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md
index 832304f1..147c16ff 100644
--- a/docs/api-guide/throttling.md
+++ b/docs/api-guide/throttling.md
@@ -74,7 +74,7 @@ If you need to strictly identify unique client IP addresses, you'll need to firs
It is important to understand that if you configure the `NUM_PROXIES` setting, then all clients behind a unique [NAT'd](http://en.wikipedia.org/wiki/Network_address_translation) gateway will be treated as a single client.
-Further context on how the `X-Forwarded-For` header works, and identifing a remote client IP can be [found here][identifing-clients].
+Further context on how the `X-Forwarded-For` header works, and identifying a remote client IP can be [found here][identifing-clients].
## Setting up the cache
@@ -85,7 +85,7 @@ If you need to use a cache other than `'default'`, you can do so by creating a c
class CustomAnonRateThrottle(AnonRateThrottle):
cache = get_cache('alternate')
-You'll need to rememeber to also set your custom throttle class in the `'DEFAULT_THROTTLE_CLASSES'` settings key, or using the `throttle_classes` view attribute.
+You'll need to remember to also set your custom throttle class in the `'DEFAULT_THROTTLE_CLASSES'` settings key, or using the `throttle_classes` view attribute.
---
@@ -178,6 +178,8 @@ To create a custom throttle, override `BaseThrottle` and implement `.allow_reque
Optionally you may also override the `.wait()` method. If implemented, `.wait()` should return a recommended number of seconds to wait before attempting the next request, or `None`. The `.wait()` method will only be called if `.allow_request()` has previously returned `False`.
+If the `.wait()` method is implemented and the request is throttled, then a `Retry-After` header will be included in the response.
+
## Example
The following is an example of a rate throttle, that will randomly throttle 1 in every 10 requests.
diff --git a/docs/api-guide/validators.md b/docs/api-guide/validators.md
new file mode 100644
index 00000000..ac2f3248
--- /dev/null
+++ b/docs/api-guide/validators.md
@@ -0,0 +1,225 @@
+<a class="github" href="validators.py"></a>
+
+# Validators
+
+> Validators can be useful for re-using validation logic between different types of fields.
+>
+> &mdash; [Django documentation][cite]
+
+Most of the time you're dealing with validation in REST framework you'll simply be relying on the default field validation, or writing explicit validation methods on serializer or field classes.
+
+However, sometimes you'll want to place your validation logic into reusable components, so that it can easily be reused throughout your codebase. This can be achieved by using validator functions and validator classes.
+
+## Validation in REST framework
+
+Validation in Django REST framework serializers is handled a little differently to how validation works in Django's `ModelForm` class.
+
+With `ModelForm` the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class. This is advantageous for the following reasons:
+
+* It introduces a proper separation of concerns, making your code behavior more obvious.
+* It is easy to switch between using shortcut `ModelSerializer` classes and using explicit `Serializer` classes. Any validation behavior being used for `ModelSerializer` is simple to replicate.
+* Printing the `repr` of a serializer instance will show you exactly what validation rules it applies. There's no extra hidden validation behavior being called on the model instance.
+
+When you're using `ModelSerializer` all of this is handled automatically for you. If you want to drop down to using a `Serializer` classes instead, then you need to define the validation rules explicitly.
+
+#### Example
+
+As an example of how REST framework uses explicit validation, we'll take a simple model class that has a field with a uniqueness constraint.
+
+ class CustomerReportRecord(models.Model):
+ time_raised = models.DateTimeField(default=timezone.now, editable=False)
+ reference = models.CharField(unique=True, max_length=20)
+ description = models.TextField()
+
+Here's a basic `ModelSerializer` that we can use for creating or updating instances of `CustomerReportRecord`:
+
+ class CustomerReportSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = CustomerReportRecord
+
+If we open up the Django shell using `manage.py shell` we can now
+
+ >>> from project.example.serializers import CustomerReportSerializer
+ >>> serializer = CustomerReportSerializer()
+ >>> print(repr(serializer))
+ CustomerReportSerializer():
+ id = IntegerField(label='ID', read_only=True)
+ time_raised = DateTimeField(read_only=True)
+ reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>])
+ description = CharField(style={'type': 'textarea'})
+
+The interesting bit here is the `reference` field. We can see that the uniqueness constraint is being explicitly enforced by a validator on the serializer field.
+
+Because of this more explicit style REST framework includes a few validator classes that are not available in core Django. These classes are detailed below.
+
+---
+
+## UniqueValidator
+
+This validator can be used to enforce the `unique=True` constraint on model fields.
+It takes a single required argument, and an optional `messages` argument:
+
+* `queryset` *required* - This is the queryset against which uniqueness should be enforced.
+* `message` - The error message that should be used when validation fails.
+
+This validator should be applied to *serializer fields*, like so:
+
+ slug = SlugField(
+ max_length=100,
+ validators=[UniqueValidator(queryset=BlogPost.objects.all())]
+ )
+
+## UniqueTogetherValidator
+
+This validator can be used to enforce `unique_together` constraints on model instances.
+It has two required arguments, and a single optional `messages` argument:
+
+* `queryset` *required* - This is the queryset against which uniqueness should be enforced.
+* `fields` *required* - A list or tuple of field names which should make a unique set. These must exist as fields on the serializer class.
+* `message` - The error message that should be used when validation fails.
+
+The validator should be applied to *serializer classes*, like so:
+
+ class ExampleSerializer(serializers.Serializer):
+ # ...
+ class Meta:
+ # ToDo items belong to a parent list, and have an ordering defined
+ # by the 'position' field. No two items in a given list may share
+ # the same position.
+ validators = [
+ UniqueTogetherValidator(
+ queryset=ToDoItem.objects.all(),
+ fields=('list', 'position')
+ )
+ ]
+
+---
+
+**Note**: The `UniqueTogetherValidation` class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
+
+---
+
+## UniqueForDateValidator
+
+## UniqueForMonthValidator
+
+## UniqueForYearValidator
+
+These validators can be used to enforce the `unique_for_date`, `unique_for_month` and `unique_for_year` constraints on model instances. They take the following arguments:
+
+* `queryset` *required* - This is the queryset against which uniqueness should be enforced.
+* `field` *required* - A field name against which uniqueness in the given date range will be validated. This must exist as a field on the serializer class.
+* `date_field` *required* - A field name which will be used to determine date range for the uniqueness constrain. This must exist as a field on the serializer class.
+* `message` - The error message that should be used when validation fails.
+
+The validator should be applied to *serializer classes*, like so:
+
+ class ExampleSerializer(serializers.Serializer):
+ # ...
+ class Meta:
+ # Blog posts should have a slug that is unique for the current year.
+ validators = [
+ UniqueForYearValidator(
+ queryset=BlogPostItem.objects.all(),
+ field='slug',
+ date_field='published'
+ )
+ ]
+
+The date field that is used for the validation is always required to be present on the serializer class. You can't simply rely on a model class `default=...`, because the value being used for the default wouldn't be generated until after the validation has run.
+
+There are a couple of styles you may want to use for this depending on how you want your API to behave. If you're using `ModelSerializer` you'll probably simply rely on the defaults that REST framework generates for you, but if you are using `Serializer` or simply want more explicit control, use on of the styles demonstrated below.
+
+#### Using with a writable date field.
+
+If you want the date field to be writable the only thing worth noting is that you should ensure that it is always available in the input data, either by setting a `default` argument, or by setting `required=True`.
+
+ published = serializers.DateTimeField(required=True)
+
+#### Using with a read-only date field.
+
+If you want the date field to be visible, but not editable by the user, then set `read_only=True` and additionally set a `default=...` argument.
+
+ published = serializers.DateTimeField(read_only=True, default=timezone.now)
+
+The field will not be writable to the user, but the default value will still be passed through to the `validated_data`.
+
+#### Using with a hidden date field.
+
+If you want the date field to be entirely hidden from the user, then use `HiddenField`. This field type does not accept user input, but instead always returns it's default value to the `validated_data` in the serializer.
+
+ published = serializers.HiddenField(default=timezone.now)
+
+---
+
+**Note**: The `UniqueFor<Range>Validation` classes always imposes an implicit constraint that the fields they are applied to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
+
+---
+
+# Advanced 'default' argument usage
+
+Validators that are applied across multiple fields in the serializer can sometimes require a field input that should not be provided by the API client, but that *is* available as input to the validator.
+
+Two patterns that you may want to use for this sort of validation include:
+
+* Using `HiddenField`. This field will be present in `validated_data` but *will not* be used in the serializer output representation.
+* Using a standard field with `read_only=True`, but that also includes a `default=…` argument. This field *will* be used in the serializer output representation, but cannot be set directly by the user.
+
+REST framework includes a couple of defaults that may be useful in this context.
+
+#### CurrentUserDefault
+
+A default class that can be used to represent the current user. In order to use this, the 'request' must have been provided as part of the context dictionary when instantiating the serializer.
+
+ owner = serializers.HiddenField(
+ default=CurrentUserDefault()
+ )
+
+#### CreateOnlyDefault
+
+A default class that can be used to *only set a default argument during create operations*. During updates the field is omitted.
+
+It takes a single argument, which is the default value or callable that should be used during create operations.
+
+ created_at = serializers.DateTimeField(
+ read_only=True,
+ default=CreateOnlyDefault(timezone.now)
+ )
+
+---
+
+# Writing custom validators
+
+You can use any of Django's existing validators, or write your own custom validators.
+
+## Function based
+
+A validator may be any callable that raises a `serializers.ValidationError` on failure.
+
+ def even_number(value):
+ if value % 2 != 0:
+ raise serializers.ValidationError('This field must be an even number.')
+
+## Class based
+
+To write a class based validator, use the `__call__` method. Class based validators are useful as they allow you to parameterize and reuse behavior.
+
+ class MultipleOf:
+ def __init__(self, base):
+ self.base = base
+
+ def __call__(self, value):
+ if value % self.base != 0
+ message = 'This field must be a multiple of %d.' % self.base
+ raise serializers.ValidationError(message)
+
+#### Using `set_context()`
+
+In some advanced cases you might want a validator to be passed the serializer field it is being used with as additional context. You can do so by declaring a `set_context` method on a class based validator.
+
+ def set_context(self, serializer_field):
+ # Determine if this is an update or a create operation.
+ # In `__call__` we can then use that information to modify the validation behavior.
+ self.is_update = serializer_field.parent.instance is not None
+
+[cite]: https://docs.djangoproject.com/en/dev/ref/validators/