aboutsummaryrefslogtreecommitdiffstats
path: root/docs/api-guide
diff options
context:
space:
mode:
Diffstat (limited to 'docs/api-guide')
-rw-r--r--[-rwxr-xr-x]docs/api-guide/authentication.md0
-rw-r--r--docs/api-guide/fields.md6
-rw-r--r--[-rwxr-xr-x]docs/api-guide/generic-views.md13
-rw-r--r--docs/api-guide/metadata.md8
-rw-r--r--docs/api-guide/pagination.md67
-rw-r--r--docs/api-guide/relations.md6
-rw-r--r--docs/api-guide/requests.md6
-rw-r--r--docs/api-guide/serializers.md8
-rw-r--r--docs/api-guide/testing.md2
-rw-r--r--docs/api-guide/validators.md14
10 files changed, 59 insertions, 71 deletions
diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md
index fe1be7bf..fe1be7bf 100755..100644
--- a/docs/api-guide/authentication.md
+++ b/docs/api-guide/authentication.md
diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md
index f113bb23..5edc997a 100644
--- a/docs/api-guide/fields.md
+++ b/docs/api-guide/fields.md
@@ -1,11 +1,5 @@
source: fields.py
----
-
-**Note**: This is the documentation for the **version 3.0** of REST framework. Documentation for [version 2.4](http://tomchristie.github.io/rest-framework-2-docs/) is also available.
-
----
-
# Serializer fields
> Each field in a Form class is responsible not only for validating data, but also for "cleaning" it — normalizing it to a consistent format.
diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md
index 61c8e8d8..7df3d6ff 100755..100644
--- a/docs/api-guide/generic-views.md
+++ b/docs/api-guide/generic-views.md
@@ -1,12 +1,6 @@
source: mixins.py
generics.py
----
-
-**Note**: This is the documentation for the **version 3.0** of REST framework. Documentation for [version 2.4](http://tomchristie.github.io/rest-framework-2-docs/) is also available.
-
----
-
# Generic views
> Django’s generic views... were developed as a shortcut for common usage patterns... They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to repeat yourself.
@@ -84,10 +78,9 @@ The following attributes control the basic view behavior.
The following attributes are used to control pagination when used with list views.
-* `paginate_by` - The size of pages to use with paginated data. If set to `None` then pagination is turned off. If unset this uses the same value as the `PAGINATE_BY` setting, which defaults to `None`.
-* `paginate_by_param` - The name of a query parameter, which can be used by the client to override the default page size to use for pagination. If unset this uses the same value as the `PAGINATE_BY_PARAM` setting, which defaults to `None`.
-* `pagination_serializer_class` - The pagination serializer class to use when determining the style of paginated responses. Defaults to the same value as the `DEFAULT_PAGINATION_SERIALIZER_CLASS` setting.
-* `page_kwarg` - The name of a URL kwarg or URL query parameter which can be used by the client to control which page is requested. Defaults to `'page'`.
+* `pagination_class` - The pagination class that should be used when paginating list results. Defaults to the same value as the `DEFAULT_PAGINATION_CLASS` setting, which is `'rest_framework.pagination.PageNumberPagination'`.
+
+Note that usage of the `paginate_by`, `paginate_by_param` and `page_kwarg` attributes are now pending deprecation. The `pagination_serializer_class` attribute and `DEFAULT_PAGINATION_SERIALIZER_CLASS` setting have been removed completely. Pagination settings should instead be controlled by overriding a pagination class and setting any configuration attributes there. See the pagination documentation for more details.
**Filtering**:
diff --git a/docs/api-guide/metadata.md b/docs/api-guide/metadata.md
index 247ae988..01727440 100644
--- a/docs/api-guide/metadata.md
+++ b/docs/api-guide/metadata.md
@@ -1,11 +1,5 @@
source: metadata.py
----
-
-**Note**: This is the documentation for the **version 3.0** of REST framework. Documentation for [version 2.4](http://tomchristie.github.io/rest-framework-2-docs/) is also available.
-
----
-
# 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.
@@ -59,7 +53,7 @@ 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({
...
diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md
index 697ba38d..eca468b8 100644
--- a/docs/api-guide/pagination.md
+++ b/docs/api-guide/pagination.md
@@ -51,7 +51,8 @@ You can then apply your new style to a view using the `.pagination_class` attrib
Or apply the style globally, using the `DEFAULT_PAGINATION_CLASS` settings key. For example:
REST_FRAMEWORK = {
- 'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination' }
+ 'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
+ }
---
@@ -79,11 +80,11 @@ This pagination style accepts a single number page number in the request query p
#### Setup
-To enable the `PageNumberPagination` style globally, use the following configuration, modifying the `DEFAULT_PAGE_SIZE` as desired:
+To enable the `PageNumberPagination` style globally, use the following configuration, modifying the `PAGE_SIZE` as desired:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
- 'DEFAULT_PAGE_SIZE': 100
+ 'PAGE_SIZE': 100
}
On `GenericAPIView` subclasses you may also set the `pagination_class` attribute to select `PageNumberPagination` on a per-view basis.
@@ -94,7 +95,7 @@ The `PageNumberPagination` class includes a number of attributes that may be ove
To set these attributes you should override the `PageNumberPagination` class, and then enable your custom pagination class as above.
-* `page_size` - A numeric value indicating the page size. If set, this overrides the `DEFAULT_PAGE_SIZE` setting. Defaults to the same value as the `DEFAULT_PAGE_SIZE` settings key.
+* `page_size` - A numeric value indicating the page size. If set, this overrides the `PAGE_SIZE` setting. Defaults to the same value as the `PAGE_SIZE` settings key.
* `page_query_param` - A string value indicating the name of the query parameter to use for the pagination control.
* `page_size_query_param` - If set, this is a string value indicating the name of a query parameter that allows the client to set the page size on a per-request basis. Defaults to `None`, indicating that the client may not control the requested page size.
* `max_page_size` - If set, this is a numeric value indicating the maximum allowable requested page size. This attribute is only valid if `page_size_query_param` is also set.
@@ -126,13 +127,13 @@ This pagination style mirrors the syntax used when looking up multiple database
#### Setup
-To enable the `PageNumberPagination` style globally, use the following configuration:
+To enable the `LimitOffsetPagination` style globally, use the following configuration:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}
-Optionally, you may also set a `DEFAULT_PAGE_SIZE` key. If the `DEFAULT_PAGE_SIZE` parameter is also used then the `limit` query parameter will be optional, and may be omitted by the client.
+Optionally, you may also set a `PAGE_SIZE` key. If the `PAGE_SIZE` parameter is also used then the `limit` query parameter will be optional, and may be omitted by the client.
On `GenericAPIView` subclasses you may also set the `pagination_class` attribute to select `LimitOffsetPagination` on a per-view basis.
@@ -142,7 +143,7 @@ The `LimitOffsetPagination` class includes a number of attributes that may be ov
To set these attributes you should override the `LimitOffsetPagination` class, and then enable your custom pagination class as above.
-* `default_limit` - A numeric value indicating the limit to use if one is not provided by the client in a query parameter. Defaults to the same value as the `DEFAULT_PAGE_SIZE` settings key.
+* `default_limit` - A numeric value indicating the limit to use if one is not provided by the client in a query parameter. Defaults to the same value as the `PAGE_SIZE` settings key.
* `limit_query_param` - A string value indicating the name of the "limit" query parameter. Defaults to `'limit'`.
* `offset_query_param` - A string value indicating the name of the "offset" query parameter. Defaults to `'offset'`.
* `max_limit` - If set this is a numeric value indicating the maximum allowable limit that may be requested by the client. Defaults to `None`.
@@ -158,28 +159,33 @@ Cursor based pagination requires that there is a unique, unchanging ordering of
Cursor based pagination is more complex than other schemes. It also requires that the result set presents a fixed ordering, and does not allow the client to arbitrarily index into the result set. However it does provide the following benefits:
-* Provides a consistent pagination view. When used properly `CursorPagination` ensures that the client will never see the same item twice when paging through records.
+* Provides a consistent pagination view. When used properly `CursorPagination` ensures that the client will never see the same item twice when paging through records, even when new items are being inserted by other clients during the pagination process.
* Supports usage with very large datasets. With extremely large datasets pagination using offset-based pagination styles may become inefficient or unusable. Cursor based pagination schemes instead have fixed-time properties, and do not slow down as the dataset size increases.
#### Details and limitations
-This implementation of cursor pagination uses a smart "position plus offset" style that allows it to properly support not-strictly-unique values as the ordering.
+Proper use of cursor based pagination requires a little attention to detail. You'll need to think about what ordering you want the scheme to be applied against. The default is to order by `"-created"`. This assumes that **there must be a 'created' timestamp field** on the model instances, and will present a "timeline" style paginated view, with the most recently added items first.
-It should be noted that using non-unique values the ordering does introduce the possibility of paging artifacts, where pagination consistency is no longer 100% guaranteed.
+You can modify the ordering by overriding the `'ordering'` attribute on the pagination class, or by using the `OrderingFilter` filter class together with `CursorPagination`. When used with `OrderingFilter` you should strongly consider restricting the fields that the user may order by.
-**TODO**: Notes on `None`.
+Proper usage of cursor pagination should have an ordering field that satisfies the following:
-The implementation also supports both forward and reverse pagination, which is often not supported in other implementations.
+* Should be an unchanging value, such as a timestamp, slug, or other field that is only set once, on creation.
+* Should be unique, or nearly unique. Millisecond precision timestamps are a good example. This implementation of cursor pagination uses a smart "position plus offset" style that allows it to properly support not-strictly-unique values as the ordering.
+* Should be a non-nullable value that can be coerced to a string.
+* The field should have a database index.
+
+Using an ordering field that does not satisfy these constraints will generally still work, but you'll be loosing some of the benefits of cursor pagination.
For more technical details on the implementation we use for cursor pagination, the ["Building cursors for the Disqus API"][disqus-cursor-api] blog post gives a good overview of the basic approach.
#### Setup
-To enable the `CursorPagination` style globally, use the following configuration, modifying the `DEFAULT_PAGE_SIZE` as desired:
+To enable the `CursorPagination` style globally, use the following configuration, modifying the `PAGE_SIZE` as desired:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
- 'DEFAULT_PAGE_SIZE': 100
+ 'PAGE_SIZE': 100
}
On `GenericAPIView` subclasses you may also set the `pagination_class` attribute to select `CursorPagination` on a per-view basis.
@@ -192,7 +198,7 @@ To set these attributes you should override the `CursorPagination` class, and th
* `page_size` = A numeric value indicating the page size. If set, this overrides the `DEFAULT_PAGE_SIZE` setting. Defaults to the same value as the `DEFAULT_PAGE_SIZE` settings key.
* `cursor_query_param` = A string value indicating the name of the "cursor" query parameter. Defaults to `'cursor'`.
-* `ordering` = This should be a string, or list of strings, indicating the field against which the cursor based pagination will be applied. For example: `ordering = 'created'`. Any filters on the view which define a `get_ordering` will override this attribute. Defaults to `None`.
+* `ordering` = This should be a string, or list of strings, indicating the field against which the cursor based pagination will be applied. For example: `ordering = 'slug'`. Defaults to `-created`. This value may also be overridden by using `OrderingFilter` on the view.
* `template` = The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to `None` to disable HTML pagination controls completely. Defaults to `"rest_framework/pagination/previous_and_next.html"`.
---
@@ -208,11 +214,36 @@ Note that the `paginate_queryset` method may set state on the pagination instanc
## Example
+Suppose we want to replace the default pagination output style with a modified format that includes the next and previous links under in a nested 'links' key. We could specify a custom pagination class like so:
+
+ class CustomPagination(pagination.PageNumberPagination):
+ def get_paginated_response(self, data):
+ return Response({
+ 'links': {
+ 'next': self.get_next_link(),
+ 'previous': self.get_previous_link()
+ },
+ 'count': self.page.paginator.count,
+ 'results': data
+ })
+
+We'd then need to setup the custom class in our configuration:
+
+ REST_FRAMEWORK = {
+ 'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
+ 'PAGE_SIZE': 100
+ }
+
+Note that if you care about how the ordering of keys is displayed in responses in the browsable API you might choose to use an `OrderedDict` when constructing the body of paginated responses, but this is optional.
+
+## Header based pagination
+
Let's modify the built-in `PageNumberPagination` style, so that instead of include the pagination links in the body of the response, we'll instead include a `Link` header, in a [similar style to the GitHub API][github-link-pagination].
class LinkHeaderPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data):
- next_url = self.get_next_link() previous_url = self.get_previous_link()
+ next_url = self.get_next_link()
+ previous_url = self.get_previous_link()
if next_url is not None and previous_url is not None:
link = '<{next_url}; rel="next">, <{previous_url}; rel="prev">'
@@ -234,7 +265,7 @@ To have your custom pagination class be used by default, use the `DEFAULT_PAGINA
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.LinkHeaderPagination',
- 'DEFAULT_PAGE_SIZE': 10
+ 'PAGE_SIZE': 100
}
API responses for list endpoints will now include a `Link` header, instead of including the pagination links as part of the body of the response, for example:
@@ -283,4 +314,4 @@ The [`DRF-extensions` package][drf-extensions] includes a [`PaginateByMaxMixin`
[link-header]: ../img/link-header-pagination.png
[drf-extensions]: http://chibisov.github.io/drf-extensions/docs/
[paginate-by-max-mixin]: http://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin
-[disqus-cursor-api]: http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api/ \ No newline at end of file
+[disqus-cursor-api]: http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api/
diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md
index 50e3b7b5..093bbdd0 100644
--- a/docs/api-guide/relations.md
+++ b/docs/api-guide/relations.md
@@ -1,11 +1,5 @@
source: relations.py
----
-
-**Note**: This is the documentation for the **version 3.0** of REST framework. Documentation for [version 2.4](http://tomchristie.github.io/rest-framework-2-docs/) is also available.
-
----
-
# Serializer relations
> Bad programmers worry about the code.
diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md
index c993dfae..658a5ffd 100644
--- a/docs/api-guide/requests.md
+++ b/docs/api-guide/requests.md
@@ -1,11 +1,5 @@
source: request.py
----
-
-**Note**: This is the documentation for the **version 3.0** of REST framework. Documentation for [version 2.4](http://tomchristie.github.io/rest-framework-2-docs/) is also available.
-
----
-
# Requests
> If you're doing REST-based web service stuff ... you should ignore request.POST.
diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md
index 940eb424..aad2236f 100644
--- a/docs/api-guide/serializers.md
+++ b/docs/api-guide/serializers.md
@@ -1,11 +1,5 @@
source: serializers.py
----
-
-**Note**: This is the documentation for the **version 3.0** of REST framework. Documentation for [version 2.4](http://tomchristie.github.io/rest-framework-2-docs/) is also available.
-
----
-
# Serializers
> Expanding the usefulness of the serializers is something that we would
@@ -23,7 +17,7 @@ The serializers in REST framework work very similarly to Django's `Form` and `Mo
Let's start by creating a simple object we can use for example purposes:
from datetime import datetime
-
+
class Comment(object):
def __init__(self, email, content, created=None):
self.email = email
diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md
index 8a848c20..dd3295c4 100644
--- a/docs/api-guide/testing.md
+++ b/docs/api-guide/testing.md
@@ -65,7 +65,7 @@ When testing views directly using a request factory, it's often convenient to be
To forcibly authenticate a request, use the `force_authenticate()` method.
- from rest_framework.tests import force_authenticate
+ from rest_framework.test import force_authenticate
factory = APIRequestFactory()
user = User.objects.get(username='olivia')
diff --git a/docs/api-guide/validators.md b/docs/api-guide/validators.md
index 8f5a8929..40ad4857 100644
--- a/docs/api-guide/validators.md
+++ b/docs/api-guide/validators.md
@@ -1,11 +1,5 @@
source: validators.py
----
-
-**Note**: This is the documentation for the **version 3.0** of REST framework. Documentation for [version 2.4](http://tomchristie.github.io/rest-framework-2-docs/) is also available.
-
----
-
# Validators
> Validators can be useful for re-using validation logic between different types of fields.
@@ -33,7 +27,7 @@ When you're using `ModelSerializer` all of this is handled automatically for you
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)
+ time_raised = models.DateTimeField(default=timezone.now, editable=False)
reference = models.CharField(unique=True, max_length=20)
description = models.TextField()
@@ -43,7 +37,7 @@ Here's a basic `ModelSerializer` that we can use for creating or updating instan
class Meta:
model = CustomerReportRecord
-If we open up the Django shell using `manage.py shell` we can now
+If we open up the Django shell using `manage.py shell` we can now
>>> from project.example.serializers import CustomerReportSerializer
>>> serializer = CustomerReportSerializer()
@@ -204,7 +198,7 @@ A validator may be any callable that raises a `serializers.ValidationError` on f
def even_number(value):
if value % 2 != 0:
- raise serializers.ValidationError('This field must be an even number.')
+ raise serializers.ValidationError('This field must be an even number.')
## Class based
@@ -213,7 +207,7 @@ To write a class based validator, use the `__call__` method. Class based validat
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