Unauthenticated responses that are denied permission will result in an HTTP 403 Forbidden response.
If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as PUT, PATCH, POST or DELETE requests. See the Django CSRF documentation for more details.
-
OAuthAuthentication
-
This authentication uses OAuth 1.0a authentication scheme. OAuth 1.0a provides signature validation which provides a reasonable level of security over plain non-HTTPS connections. However, it may also be considered more complicated than OAuth2, as it requires clients to sign their requests.
-
This authentication class depends on the optional django-oauth-plus and oauth2 packages. In order to make it work you must install these packages and add oauth_provider to your INSTALLED_APPS:
-
INSTALLED_APPS = (
- ...
- `oauth_provider`,
-)
-
-
Don't forget to run syncdb once you've added the package.
-
python manage.py syncdb
-
-
Getting started with django-oauth-plus
-
The OAuthAuthentication class only provides token verification and signature validation for requests. It doesn't provide authorization flow for your clients. You still need to implement your own views for accessing and authorizing tokens.
-
The django-oauth-plus package provides simple foundation for classic 'three-legged' oauth flow. Please refer to the documentation for more details.
-
OAuth2Authentication
-
This authentication uses OAuth 2.0 authentication scheme. OAuth2 is more simple to work with than OAuth1, and provides much better security than simple token authentication. It is an unauthenticated scheme, and requires you to use an HTTPS connection.
-
This authentication class depends on the optional django-oauth2-provider project. In order to make it work you must install this package and add provider and provider.oauth2 to your INSTALLED_APPS:
Note: If you use OAuth2Authentication in production you must ensure that your API is only available over https.
-
-
Getting started with django-oauth2-provider
-
The OAuth2Authentication class only provides token verification for requests. It doesn't provide authorization flow for your clients.
-
The OAuth 2 authorization flow is taken care by the django-oauth2-provider dependency. A walkthrough is given here, but for more details you should refer to the documentation.
-
To get started:
-
1. Create a client
-
You can create a client, either through the shell, or by using the Django admin.
-
Go to the admin panel and create a new Provider.Client entry. It will create the client_id and client_secret properties for you.
-
2. Request an access token
-
To request an access token, submit a POST request to the url /oauth2/access_token with the following fields:
-
-
client_id the client id you've just configured at the previous step.
-
client_secret again configured at the previous step.
-
username the username with which you want to log in.
-
password well, that speaks for itself.
-
-
You can use the command line to test that your local configuration is working:
-
curl -X POST -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=password&username=YOUR_USERNAME&password=YOUR_PASSWORD" http://localhost:8000/oauth2/access_token/
-
-
You should get a response that looks something like this:
Note that Django OAuth Toolkit is an alternative external package that also includes OAuth 2.0 support for REST framework.
-
Custom authentication
To implement a custom authentication scheme, subclass BaseAuthentication and override the .authenticate(self, request) method. The method should return a two-tuple of (user, auth) if authentication succeeds, or None otherwise.
In some circumstances instead of returning None, you may want to raise an AuthenticationFailed exception from the .authenticate() method.
@@ -749,10 +673,35 @@ class ExampleAuthentication(authentication.BaseAuthentication):
Third party packages
The following third party packages are also available.
+
Django OAuth Toolkit
+
The 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 and uses the excellent OAuthLib. The package is well documented, and well supported and is currently our recommended package for OAuth 2.0 support.
+
Installation & configuration
+
Install using pip.
+
pip install django-oauth-toolkit
+
+
Add the package to your INSTALLED_APPS and modify your REST framework settings.
This package was previously included directly in REST framework but is now supported and maintained as a third party package.
+
Installation & configuration
+
Install the package using pip.
+
pip install djangorestframework-oauth
+
+
For details on configuration and usage see the Django REST framework OAuth documentation for authentication and permissions.
Digest Authentication
HTTP digest authentication is a widely implemented scheme that was intended to replace HTTP basic authentication, and which provides a simple encrypted authentication mechanism. Juan Riaza maintains the djangorestframework-digestauth package which provides HTTP digest authentication support for REST framework.
-
Django OAuth Toolkit
-
The 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 and uses the excellent OAuthLib. The package is well documented, and comes as a recommended alternative for OAuth 2.0 support.
@@ -763,6 +712,8 @@ class ExampleAuthentication(authentication.BaseAuthentication):
HTTP Signature (currently a IETF draft) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to Amazon's HTTP Signature scheme, used by many of its services, it permits stateless, per-request authentication. Elvio Toccalino maintains the djangorestframework-httpsignature package which provides an easy to use HTTP Signature Authentication mechanism.
Djoser
Djoser library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and it uses token based authentication. This is a ready to use REST implementation of Django authentication system.
+
django-rest-auth
+
Django-rest-auth library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.
You can implement custom exception handling by creating a handler function that converts exceptions raised in your API views into response objects. This allows you to control the style of error responses used by your API.
-
The function must take a single argument, which is the exception to be handled, and should either return a Response object, or return None if the exception cannot be handled. If the handler returns None then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.
+
The function must take a pair of arguments, this first is the exception to be handled, and the second is a dictionary containing any extra context such as the view currently being handled. The exception handler function should either return a Response object, or return None if the exception cannot be handled. If the handler returns None then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.
For example, you might want to ensure that all error responses include the HTTP status code in the body of the response, like so:
In order to alter the style of the response, you could write the following custom exception handler:
from rest_framework.views import exception_handler
-def custom_exception_handler(exc):
+def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
- response = exception_handler(exc)
+ response = exception_handler(exc, context)
# Now add the HTTP status code to the response.
if response is not None:
@@ -486,6 +486,7 @@ def custom_exception_handler(exc):
return response
+
The context argument is not used by the default handler, but can be useful if the exception handler needs further information such as the view currently being handled, which can be accessed as context['view'].
The exception handler must also be configured in your settings, using the EXCEPTION_HANDLER setting key. For example:
max_length - Validates that the input contains no more than this number of characters.
min_length - Validates that the input contains no fewer than this number of characters.
allow_blank - If set to True then the empty string should be considered a valid value. If set to False then the empty string is considered invalid and will raise a validation error. Defaults to False.
+
trim_whitespace - If set to True then leading and trailing whitespace is trimmed. Defaults to True.
The allow_null option is also available for string fields, although its usage is discouraged in favor of allow_blank. It is valid to set both allow_blank=True and allow_null=True, but doing so means that there will be two differing types of empty value permissible for string representations, which can lead to data inconsistencies and subtle application bugs.
-
@@ -568,11 +560,9 @@ class UserList(generics.ListCreateAPIView):
Pagination:
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:
filter_backends - A list of filter backend classes that should be used for filtering the queryset. Defaults to the same value as the DEFAULT_FILTER_BACKENDS setting.
REST framework includes a PaginationSerializer class that makes it easy to return paginated data in a way that can then be rendered to arbitrary media types.
-
Paginating basic data
-
Let's start by taking a look at an example from the Django documentation.
REST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.
+
The pagination API can support either:
+
+
Pagination links that are provided as part of the content of the response.
+
Pagination links that are included in response headers, such as Content-Range or Link.
+
+
The built-in styles currently all use links included as part of the content of the response. This style is more accessible when using the browsable API.
+
Pagination is only performed automatically if you're using the generic views or viewsets. If you're using a regular APIView, you'll need to call into the pagination API yourself to ensure you return a paginated response. See the source code for the mixins.ListMixin and generics.GenericAPIView classes for an example.
+
Setting the pagination style
+
The default pagination style may be set globally, using the DEFAULT_PAGINATION_CLASS settings key. For example, to use the built-in limit/offset pagination, you would do:
At this point we've got a page object. If we wanted to return this page object as a JSON response, we'd need to provide the client with context such as next and previous links, so that it would be able to page through the remaining results.
You can also set the pagination class on an individual view by using the pagination_class attribute. Typically you'll want to use the same pagination style throughout your API, although you might want to vary individual aspects of the pagination, such as default or maximum page size, on a per-view basis.
+
Modifying the pagination style
+
If you want to modify particular aspects of the pagination style, you'll want to override one of the pagination classes, and set the attributes that you want to change.
This pagination style accepts a single number page number in the request query parameters.
+
Request:
+
GET https://api.example.org/accounts/?page=4
-
The context argument of the PaginationSerializer class may optionally include the request. If the request is included in the context then the next and previous links returned by the serializer will use absolute URLs instead of relative URLs.
We could now return that data in a Response object, and it would be rendered into the correct media type.
-
Paginating QuerySets
-
Our first example worked because we were using primitive objects. If we wanted to paginate a queryset or other complex data, we'd need to specify a serializer to use to serialize the result set itself.
-
We can do this using the object_serializer_class attribute on the inner Meta class of the pagination serializer. For example.
-
class UserSerializer(serializers.ModelSerializer):
- """
- Serializes user querysets.
- """
- class Meta:
- model = User
- fields = ('username', 'email')
-
-class PaginatedUserSerializer(pagination.PaginationSerializer):
- """
- Serializes page objects of user querysets.
- """
- class Meta:
- object_serializer_class = UserSerializer
+
Setup
+
To enable the PageNumberPagination style globally, use the following configuration, modifying the DEFAULT_PAGE_SIZE as desired:
We could now use our pagination serializer in a view like this.
-
@api_view('GET')
-def user_list(request):
- queryset = User.objects.all()
- paginator = Paginator(queryset, 20)
-
- page = request.QUERY_PARAMS.get('page')
- try:
- users = paginator.page(page)
- except PageNotAnInteger:
- # If page is not an integer, deliver first page.
- users = paginator.page(1)
- except EmptyPage:
- # If page is out of range (e.g. 9999),
- # deliver last page of results.
- users = paginator.page(paginator.num_pages)
-
- serializer_context = {'request': request}
- serializer = PaginatedUserSerializer(users,
- context=serializer_context)
- return Response(serializer.data)
+
On GenericAPIView subclasses you may also set the pagination_class attribute to select PageNumberPagination on a per-view basis.
+
Configuration
+
The PageNumberPagination class includes a number of attributes that may be overridden to modify the pagination style.
+
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_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.
+
last_page_strings - A list or tuple of string values indicating values that may be used with the page_query_param to request the final page in the set. Defaults to ('last',)
+
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/numbers.html".
+
+
+
LimitOffsetPagination
+
This pagination style mirrors the syntax used when looking up multiple database records. The client includes both a "limit" and an
+"offset" query parameter. The limit indicates the maximum number of items to return, and is equivalent to the page_size in other styles. The offset indicates the starting position of the query in relation to the complete set of unpaginated items.
+
Request:
+
GET https://api.example.org/accounts/?limit=100&offset=400
-
Pagination in the generic views
-
The generic class based views ListAPIView and ListCreateAPIView provide pagination of the returned querysets by default. You can customise this behaviour by altering the pagination style, by modifying the default number of results, by allowing clients to override the page size using a query parameter, or by turning pagination off completely.
-
The default pagination style may be set globally, using the DEFAULT_PAGINATION_SERIALIZER_CLASS, PAGINATE_BY, PAGINATE_BY_PARAM, and MAX_PAGINATE_BY settings. For example.
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.
+
On GenericAPIView subclasses you may also set the pagination_class attribute to select LimitOffsetPagination on a per-view basis.
+
Configuration
+
The LimitOffsetPagination class includes a number of attributes that may be overridden to modify the pagination style.
+
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.
+
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.
+
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/numbers.html".
+
+
+
CursorPagination
+
The cursor-based pagination presents an opaque "cursor" indicator that the client may use to page through the result set. This pagination style only presents forward and reverse controls, and does not allow the client to navigate to arbitrary positions.
+
Cursor based pagination requires that there is a unique, unchanging ordering of items in the result set. This ordering might typically be a creation timestamp on the records, as this presents a consistent ordering to paginate against.
+
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, 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
+
Proper use of cursor based pagination 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.
+
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.
+
Proper usage of cursor pagination should have an ordering field that satisfies the following:
+
+
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" 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:
Note that using a paginate_by value of None will turn off pagination for the view.
-Note if you use the PAGINATE_BY_PARAM settings, you also have to set the paginate_by_param attribute in your view to None in order to turn off pagination for those requests that contain the paginate_by_param parameter.
-
For more complex requirements such as serialization that differs depending on the requested media type you can override the .get_paginate_by() and .get_pagination_serializer_class() methods.
+
On GenericAPIView subclasses you may also set the pagination_class attribute to select CursorPagination on a per-view basis.
+
Configuration
+
The CursorPagination class includes a number of attributes that may be overridden to modify the pagination style.
+
To set these attributes you should override the CursorPagination 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.
+
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 = '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".
+
-
Custom pagination serializers
-
To create a custom pagination serializer class you should override pagination.BasePaginationSerializer and set the fields that you want the serializer to return.
-
You can also override the name used for the object list field, by setting the results_field attribute, which defaults to 'results'.
+
Custom pagination styles
+
To create a custom pagination serializer class you should subclass pagination.BasePagination and override the paginate_queryset(self, queryset, request, view=None) and get_paginated_response(self, data) methods:
+
+
The paginate_queryset method is passed the initial queryset and should return an iterable object that contains only the data in the requested page.
+
The get_paginated_response method is passed the serialized page data and should return a Response instance.
+
+
Note that the paginate_queryset method may set state on the pagination instance, that may later be used by the get_paginated_response method.
Example
-
For example, to nest a pair of links labelled 'prev' and 'next', and set the name for the results field to 'objects', you might use something like this.
-
from rest_framework import pagination
-from rest_framework import serializers
-
-class LinksSerializer(serializers.Serializer):
- next = pagination.NextPageField(source='*')
- prev = pagination.PreviousPageField(source='*')
-
-class CustomPaginationSerializer(pagination.BasePaginationSerializer):
- links = LinksSerializer(source='*') # Takes the page object as the source
- total_results = serializers.ReadOnlyField(source='paginator.count')
-
- results_field = 'objects'
+
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:
Alternatively, to set your custom pagination serializer on a per-view basis, use the pagination_serializer_class attribute on a generic class based view:
-
class PaginatedListView(generics.ListAPIView):
- model = ExampleModel
- pagination_serializer_class = CustomPaginationSerializer
- paginate_by = 10
+
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.
+
class LinkHeaderPagination(pagination.PageNumberPagination):
+ def get_paginated_response(self, data):
+ 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">'
+ elif next_url is not None:
+ link = '<{next_url}; rel="next">'
+ elif previous_url is not None:
+ link = '<{previous_url}; rel="prev">'
+ else:
+ link = ''
+
+ link = link.format(next_url=next_url, previous_url=previous_url)
+ headers = {'Link': link} if link else {}
+
+ return Response(data, headers=headers)
+
Using your custom pagination class
+
To have your custom pagination class be used by default, use the DEFAULT_PAGINATION_CLASS setting:
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:
+
+
+
A custom pagination style, using the 'Link' header'
+
+
HTML pagination controls
+
By default using the pagination classes will cause HTML pagination controls to be displayed in the browsable API. There are two built-in display styles. The PageNumberPagination and LimitOffsetPagination classes display a list of page numbers with previous and next controls. The CursorPagination class displays a simpler style that only displays a previous and next control.
+
Customizing the controls
+
You can override the templates that render the HTML pagination controls. The two built-in styles are:
+
+
rest_framework/pagination/numbers.html
+
rest_framework/pagination/previous_and_next.html
+
+
Providing a template with either of these paths in a global template directory will override the default rendering for the relevant pagination classes.
+
Alternatively you can disable HTML pagination controls completely by subclassing on of the existing classes, setting template = None as an attribute on the class. You'll then need to configure your DEFAULT_PAGINATION_CLASS settings key to use your custom class as the default pagination style.
+
Low-level API
+
The low-level API for determining if a pagination class should display the controls or not is exposed as a display_page_controls attribute on the pagination instance. Custom pagination classes should be set to True in the paginate_queryset method if they require the HTML pagination controls to be displayed.
+
The .to_html() and .get_html_context() methods may also be overridden in a custom pagination class in order to further customize how the controls are rendered.
+
Third party packages
The following third party packages are also available.
@@ -472,34 +464,34 @@ sending more complex data than simple forms
As an example, if you are sending json encoded data using jQuery with the .ajax() method, you should make sure to include the contentType: 'application/json' setting.
Setting the parsers
-
The default set of parsers may be set globally, using the DEFAULT_PARSER_CLASSES setting. For example, the following settings would allow requests with YAML content.
+
The default set of parsers may be set globally, using the DEFAULT_PARSER_CLASSES setting. For example, the following settings would allow only requests with JSON content, instead of the default of JSON or form data.
You can also set the parsers used for an individual view, or viewset,
using the APIView class based views.
-
from rest_framework.parsers import YAMLParser
+
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
"""
- A view that can accept POST requests with YAML content.
+ A view that can accept POST requests with JSON content.
"""
- parser_classes = (YAMLParser,)
+ parser_classes = (JSONParser,)
def post(self, request, format=None):
return Response({'received data': request.data})
Or, if you're using the @api_view decorator with function based views.
@api_view(['POST'])
-@parser_classes((YAMLParser,))
+@parser_classes((JSONParser,))
def example_view(request, format=None):
"""
- A view that can accept POST requests with YAML content.
+ A view that can accept POST requests with JSON content.
"""
return Response({'received data': request.data})
Parses REST framework's default style of XML request content.
-
Note that the XML markup language is typically used as the base language for more strictly defined domain-specific languages, such as RSS, Atom, and XHTML.
-
If you are considering using XML for your API, you may want to consider implementing a custom renderer and parser for your specific requirements, and using an existing domain-specific media-type, or creating your own custom XML-based media-type.
-
Requires the defusedxml package to be installed.
-
.media_type: application/xml
FormParser
Parses HTML form content. request.data will be populated with a QueryDict of data.
You will typically want to use both FormParser and MultiPartParser together in order to fully support HTML form data.
Optional. If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content.
By default this will include the following keys: view, request, args, kwargs.
Example
-
The following is an example plaintext parser that will populate the request.data property with a string representing the body of the request.
+
The following is an example plaintext parser that will populate the request.data property with a string representing the body of the request.
class PlainTextParser(BaseParser):
"""
Plain text parser.
@@ -578,6 +560,38 @@ def parse(self, stream, media_type=None, parser_context=None):
Third party packages
The following third party packages are also available.
+
YAML
+
REST framework YAML provides YAML parsing and rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.
REST Framework XML provides a simple informal XML format. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.
MessagePack is a fast, efficient binary serialization format. Juan Riaza maintains the djangorestframework-msgpack package which provides MessagePack renderer and parser support for REST framework.
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
-
This permission class is intended for use with either of the OAuthAuthentication and OAuth2Authentication classes, and ties into the scoping that their backends provide.
-
Requests with a safe methods of GET, OPTIONS or HEAD will be allowed if the authenticated token has read permission.
-
Requests for POST, PUT, PATCH and DELETE will be allowed if the authenticated token has write permission.
-
This permission class relies on the implementations of the django-oauth-plus and django-oauth2-provider libraries, which both provide limited support for controlling the scope of access tokens:
-
-
django-oauth-plus: Tokens are associated with a Resource class which has a name, url and is_readonly properties.
-
django-oauth2-provider: Tokens are associated with a bitwise scope attribute, that defaults to providing bitwise values for read and/or write.
-
-
If you require more advanced scoping for your API, such as restricting tokens to accessing a subset of functionality of your API then you will need to provide a custom permission class. See the source of the django-oauth-plus or django-oauth2-provider package for more details on scoping token access.
Custom permissions
To implement a custom permission, override BasePermission and implement either, or both, of the following methods:
The basic process of content negotiation involves examining the request's Accept header, to determine which media types it expects in the response. Optionally, format suffixes on the URL may be used to explicitly request a particular representation. For example the URL http://example.com/api/users_count.json might be an endpoint that always returns JSON data.
The default set of renderers may be set globally, using the DEFAULT_RENDERER_CLASSES setting. For example, the following settings would use YAML as the main media type and also include the self describing API.
+
The default set of renderers may be set globally, using the DEFAULT_RENDERER_CLASSES setting. For example, the following settings would use JSON as the main media type and also include the self describing API.
You can also set the renderers used for an individual view, or viewset,
using the APIView class based views.
from django.contrib.auth.models import User
-from rest_framework.renderers import JSONRenderer, YAMLRenderer
+from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
class UserCountView(APIView):
"""
- A view that returns the count of active users, in JSON or YAML.
+ A view that returns the count of active users in JSON.
"""
- renderer_classes = (JSONRenderer, YAMLRenderer)
+ renderer_classes = (JSONRenderer, )
def get(self, request, format=None):
user_count = User.objects.filter(active=True).count()
@@ -555,10 +543,10 @@ class UserCountView(APIView):
Or, if you're using the @api_view decorator with function based views.
@api_view(['GET'])
-@renderer_classes((JSONRenderer, JSONPRenderer))
+@renderer_classes((JSONRenderer,))
def user_count_view(request, format=None):
"""
- A view that returns the count of active users, in JSON or JSONp.
+ A view that returns the count of active users in JSON.
"""
user_count = User.objects.filter(active=True).count()
content = {'user_count': user_count}
@@ -585,41 +573,6 @@ def user_count_view(request, format=None):
.media_type: application/json
.format: '.json'
.charset: None
-
JSONPRenderer
-
Renders the request data into JSONP. The JSONP media type provides a mechanism of allowing cross-domain AJAX requests, by wrapping a JSON response in a javascript callback.
-
The javascript callback function must be set by the client including a callback URL query parameter. For example http://example.com/api/users?callback=jsonpCallback. If the callback function is not explicitly set by the client it will default to 'callback'.
-
-
Warning: If you require cross-domain AJAX requests, you should almost certainly be using the more modern approach of CORS as an alternative to JSONP. See the CORS documentation for more details.
Note that non-ascii characters will be rendered using \uXXXX character escape. For example:
-
unicode black star: "\u2605"
-
-
.media_type: application/yaml
-
.format: '.yaml'
-
.charset: utf-8
-
UnicodeYAMLRenderer
-
Renders the request data into YAML.
-
Requires the pyyaml package to be installed.
-
Note that non-ascii characters will not be character escaped. For example:
-
unicode black star: ★
-
-
.media_type: application/yaml
-
.format: '.yaml'
-
.charset: utf-8
-
XMLRenderer
-
Renders REST framework's default style of XML response content.
-
Note that the XML markup language is used typically used as the base language for more strictly defined domain-specific languages, such as RSS, Atom, and XHTML.
-
If you are considering using XML for your API, you may want to consider implementing a custom renderer and parser for your specific requirements, and using an existing domain-specific media-type, or creating your own custom XML-based media-type.
-
.media_type: application/xml
-
.format: '.xml'
-
.charset: utf-8
TemplateHTMLRenderer
Renders data to HTML, using Django's standard template rendering.
Unlike other renderers, the data passed to the Response does not need to be serialized. Also, unlike other renderers, you may want to include a template_name argument when creating the Response.
@@ -791,10 +744,59 @@ In this case you can underspecify the media types it should respond to, by using
Third party packages
The following third party packages are also available.
+
YAML
+
REST framework YAML provides YAML parsing and rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.
REST Framework XML provides a simple informal XML format. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.
REST framework JSONP provides JSONP rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.
+
+
Warning: If you require cross-domain AJAX requests, you should generally be using the more modern approach of CORS as an alternative to JSONP. See the CORS documentation for more details.
MessagePack is a fast, efficient binary serialization format. Juan Riaza maintains the djangorestframework-msgpack package which provides MessagePack renderer and parser support for REST framework.
CSV
-
Comma-separated values are a plain-text tabular data format, that can be easily imported into spreadsheet applications. Mjumbe Poe maintains the djangorestframework-csv package which provides CSV renderer support for REST framework.
+
Comma-separated values are a plain-text tabular data format, that can be easily imported into spreadsheet applications. Mjumbe Poe maintains the djangorestframework-csv package which provides CSV renderer support for REST framework.
UltraJSON
UltraJSON is an optimized C JSON encoder which can give significantly faster JSON rendering. Jacob Haslehurst maintains the drf-ujson-renderer package which implements JSON rendering using the UJSON package.
request.query_params is a more correctly named synonym for request.GET.
For clarity inside your code, we recommend using request.query_params instead of the Django's standard request.GET. Doing so will help keep your codebase more correct and obvious - any HTTP method type may include query parameters, not just GET requests.
.DATA and .FILES
-
The old-style version 2.x request.data and request.FILES attributes are still available, but are now pending deprecation in favor of the unified request.data attribute.
+
The old-style version 2.x request.DATA and request.FILES attributes are still available, but are now pending deprecation in favor of the unified request.data attribute.
.QUERY_PARAMS
The old-style version 2.x request.QUERY_PARAMS attribute is still available, but is now pending deprecation in favor of the more pythonic request.query_params.
If you only want a subset of the default fields to be used in a model serializer, you can do so using fields or exclude options, just as you would with a ModelForm.
For example:
class AccountSerializer(serializers.ModelSerializer):
@@ -950,7 +946,7 @@ AccountSerializer():
model = Account
Extra fields can correspond to any property or callable on the model.
-
Specifying which fields should be read-only
+
Specifying read only fields
You may wish to specify multiple fields as read-only. Instead of adding each field explicitly with the read_only=True attribute, you may use the shortcut Meta option, read_only_fields.
This option should be a list or tuple of field names, and is declared as follows:
class AccountSerializer(serializers.ModelSerializer):
@@ -968,7 +964,7 @@ AccountSerializer():
Specifying additional keyword arguments for fields.
+
Additional keyword arguments
There is also a shortcut allowing you to specify arbitrary additional keyword arguments on fields, using the extra_kwargs option. Similarly to read_only_fields this means you do not need to explicitly declare the field on the serializer.
This option is a dictionary, mapping field names to a dictionary of keyword arguments. For example:
class CreateUserSerializer(serializers.ModelSerializer):
@@ -997,6 +993,43 @@ AccountSerializer():
model = Account
Typically we would recommend not using inheritance on inner Meta classes, but instead declaring all options explicitly.
+
Customizing field mappings
+
The ModelSerializer class also exposes an API that you can override in order to alter how serializer fields are automatically determined when instantiating the serializer.
+
Normally if a ModelSerializer does not generate the fields you need by default the you should either add them to the class explicitly, or simply use a regular Serializer class instead. However in some cases you may want to create a new base class that defines how the serializer fields are created for any given model.
+
.serializer_field_mapping
+
A mapping of Django model classes to REST framework serializer classes. You can override this mapping to alter the default serializer classes that should be used for each model class.
+
.serializer_related_field
+
This property should be the serializer field class, that is used for relational fields by default.
+
For ModelSerializer this defaults to PrimaryKeyRelatedField.
+
For HyperlinkedModelSerializer this defaults to serializers.HyperlinkedRelatedField.
+
serializer_url_field
+
The serializer field class that should be used for any url field on the serializer.
+
Defaults to serializers.HyperlinkedIdentityField
+
serializer_choice_field
+
The serializer field class that should be used for any choice fields on the serializer.
+
Defaults to serializers.ChoiceField
+
The field_class and field_kwargs API
+
The following methods are called to determine the class and keyword arguments for each field that should be automatically included on the serializer. Each of these methods should return a two tuple of (field_class, field_kwargs).
Called when the field name did not map to any model field or model property.
+The default implementation raises an error, although subclasses may customize this behavior.
HyperlinkedModelSerializer
The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys.
@@ -534,6 +530,17 @@ If set to None then generic filtering is disabled.
The name of a query parameter, which can be used to specify the ordering of results returned by OrderingFilter.
Default: ordering
+
Versioning settings
+
DEFAULT_VERSION
+
The value that should be used for request.version when no versioning information is present.
+
Default: None
+
ALLOWED_VERSIONS
+
If set, this value will restrict the set of versions that may be returned by the versioning scheme, and will raise an error if the provided version if not in this set.
+
Default: None
+
VERSION_PARAMETER
+
The string that should used for any versioning parameters, such as in the media type or URL query parameters.
+
Default: 'version'
+
Authentication settings
The following settings control the behavior of unauthenticated requests.
UNAUTHENTICATED_USER
@@ -661,7 +668,7 @@ If set to None then generic filtering is disabled.
A string representing the function that should be used when returning a response for any given exception. If the function returns None, a 500 error will be raised.
This setting can be changed to support error responses other than the default {"detail": "Failure..."} responses. For example, you can use it to provide API responses like {"errors": [{"message": "Failure...", "code": ""} ...]}.
This should be a function with the following signature:
The APIRequestFactory class supports an almost identical API to Django's standard RequestFactory class. This means the that standard .get(), .post(), .put(), .patch(), .delete(), .head() and .options() methods are all available.
+
The APIRequestFactory class supports an almost identical API to Django's standard RequestFactory class. This means that the standard .get(), .post(), .put(), .patch(), .delete(), .head() and .options() methods are all available.
from rest_framework.test import APIRequestFactory
# Using the standard RequestFactory API to create a form POST request
@@ -506,7 +498,9 @@ request = factory.put('/notes/547/', content, content_type=content_type)
Forcing authentication
When testing views directly using a request factory, it's often convenient to be able to directly authenticate the request, rather than having to construct the correct authentication credentials.
To forcibly authenticate a request, use the force_authenticate() method.
Note: It's worth noting that Django's standard RequestFactory doesn't need to include this option, because when using regular Django the CSRF validation takes place in middleware, which is not run when testing views directly. When using REST framework, CSRF validation takes place inside the view, so the request factory needs to disable view-level CSRF checks.
The APIClient class supports the same request interface as APIRequestFactory. This means the that standard .get(), .post(), .put(), .patch(), .delete(), .head() and .options() methods are all available. For example:
+
The APIClient class supports the same request interface as Django's standard Client class. This means the that standard .get(), .post(), .put(), .patch(), .delete(), .head() and .options() methods are all available. For example:
If you need to test requests using something other than multipart or json requests, you can do so by setting the TEST_REQUEST_RENDERER_CLASSES setting.
-
For example, to add support for using format='yaml' in test requests, you might have something like this in your settings.py file.
+
For example, to add support for using format='html' in test requests, you might have something like this in your settings.py file.
API versioning allows you to alter behavior between different clients. REST framework provides for a number of different versioning schemes.
+
Versioning is determined by the incoming client request, and may either be based on the request URL, or based on the request headers.
+
There are a number of valid approaches to approaching versioning. Non-versioned systems can also be appropriate, particularly if you're engineering for very long-term systems with multiple clients outside of your control.
+
Versioning with REST framework
+
When API versioning is enabled, the request.version attribute will contain a string that corresponds to the version requested in the incoming client request.
+
By default, versioning is not enabled, and request.version will always return None.
+
Varying behavior based on the version
+
How you vary the API behavior is up to you, but one example you might typically want is to switch to a different serialization style in a newer version. For example:
The reverse function included by REST framework ties in with the versioning scheme. You need to make sure to include the current request as a keyword argument, like so.
+
reverse('bookings-list', request=request)
+
+
The above function will apply any URL transformations appropriate to the request version. For example:
+
+
If NamespacedVersioning was being used, and the API version was 'v1', then the URL lookup used would be 'v1:bookings-list', which might resolve to a URL like http://example.org/v1/bookings/.
+
If QueryParameterVersioning was being used, and the API version was 1.0, then the returned URL might be something like http://example.org/bookings/?version=1.0
+
+
Versioned APIs and hyperlinked serializers
+
When using hyperlinked serialization styles together with a URL based versioning scheme make sure to include the request as context to the serializer.
Unless it is explicitly set, the value for DEFAULT_VERSIONING_CLASS will be None. In this case the request.version attribute will always return None.
+
You can also set the versioning scheme on an individual view. Typically you won't need to do this, as it makes more sense to have a single versioning scheme used globally. If you do need to do so, use the versioning_class attribute.
+
class ProfileList(APIView):
+ versioning_class = versioning.QueryParameterVersioning
+
+
Other versioning settings
+
The following settings keys are also used to control versioning:
+
+
DEFAULT_VERSION. The value that should be used for request.version when no versioning information is present. Defaults to None.
+
ALLOWED_VERSIONS. If set, this value will restrict the set of versions that may be returned by the versioning scheme, and will raise an error if the provided version if not in this set. Defaults to None.
+
VERSION_PARAMETER. The string that should used for any versioning parameters, such as in the media type or URL query parameters. Defaults to 'version'.
+
+
+
API Reference
+
AcceptHeaderVersioning
+
This scheme requires the client to specify the version as part of the media type in the Accept header. The version is included as a media type parameter, that supplements the main media type.
+
Here's an example HTTP request using the accept header versioning style.
+
GET /bookings/ HTTP/1.1
+Host: example.com
+Accept: application/json; version=1.0
+
+
In the example request above request.version attribute would return the string '1.0'.
+
Versioning based on accept headers is generally considered as best practice, although other styles may be suitable depending on your client requirements.
+
Using accept headers with vendor media types
+
Strictly speaking the json media type is not specified as including additional parameters. If you are building a well-specified public API you might consider using a vendor media type. To do so, configure your renderers to use a JSON based renderer with a custom media type:
+
class BookingsAPIRenderer(JSONRenderer):
+ media_type = 'application/vnd.megacorp.bookings+json'
+
+
Your client requests would now look like this:
+
GET /bookings/ HTTP/1.1
+Host: example.com
+Accept: application/vnd.megacorp.bookings+json; version=1.0
+
+
URLParameterVersioning
+
This scheme requires the client to specify the version as part of the URL path.
+
GET /v1/bookings/ HTTP/1.1
+Host: example.com
+Accept: application/json
+
+
Your URL conf must include a pattern that matches the version with a 'version' keyword argument, so that this information is available to the versioning scheme.
To the client, this scheme is the same as URLParameterVersioning. The only difference is how it is configured in your Django application, as it uses URL namespacing, instead of URL keyword arguments.
+
GET /v1/something/ HTTP/1.1
+Host: example.com
+Accept: application/json
+
+
With this scheme the request.version attribute is determined based on the namespace that matches the incoming request path.
+
In the following example we're giving a set of views two different possible URL prefixes, each under a different namespace:
Both URLParameterVersioning and NamespaceVersioning are reasonable if you just need a simple versioning scheme. The URLParameterVersioning approach might be better suitable for small ad-hoc projects, and the NamespaceVersioning is probably easier to manage for larger projects.
+
HostNameVersioning
+
The hostname versioning scheme requires the client to specify the requested version as part of the hostname in the URL.
+
For example the following is an HTTP request to the http://v1.example.com/bookings/ URL:
+
GET /bookings/ HTTP/1.1
+Host: v1.example.com
+Accept: application/json
+
+
By default this implementation expects the hostname to match this simple regular expression:
+
^([a-zA-Z0-9]+)\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+$
+
+
Note that the first group is enclosed in brackets, indicating that this is the matched portion of the hostname.
+
The HostNameVersioning scheme can be awkward to use in debug mode as you will typically be accessing a raw IP address such as 127.0.0.1. There are various online services which you to access localhost with a custom subdomain which you may find helpful in this case.
+
Hostname based versioning can be particularly useful if you have requirements to route incoming requests to different servers based on the version, as you can configure different DNS records for different API versions.
+
QueryParameterVersioning
+
This scheme is a simple style that includes the version as a query parameter in the URL. For example:
+
GET /something/?version=0.1 HTTP/1.1
+Host: example.com
+Accept: application/json
+
+
+
Custom versioning schemes
+
To implement a custom versioning scheme, subclass BaseVersioning and override the .determine_version method.
+
Example
+
The following example uses a custom X-API-Version header to determine the requested version.
If your versioning scheme is based on the request URL, you will also want to alter how versioned URLs are determined. In order to do so you should override the .reverse() method on the class. See the source code for examples.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api-guide/views/index.html b/api-guide/views/index.html
index f07a4921..09a1de41 100644
--- a/api-guide/views/index.html
+++ b/api-guide/views/index.html
@@ -188,6 +188,10 @@
Pagination
+
-
@@ -566,7 +558,7 @@ class UserViewSet(viewsets.ModelViewSet):
The ModelViewSet class inherits from GenericAPIView and includes implementations for various actions, by mixing in the behavior of the various mixin classes.
The actions provided by the ModelViewSet class are .list(), .retrieve(), .create(), .update(), and .destroy().
Example
-
Because ModelViewSet extends GenericAPIView, you'll normally need to provide at least the queryset and serializer_class attributes, or the model attribute shortcut. For example:
+
Because ModelViewSet extends GenericAPIView, you'll normally need to provide at least the queryset and serializer_class attributes. For example:
class AccountViewSet(viewsets.ModelViewSet):
"""
A simple ViewSet for viewing and editing accounts.
--
cgit v1.2.3