From 9381ce1ee2447f9fcde8dde32ca99cb308ae0b88 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 16 Jan 2019 13:29:55 +0000 Subject: [PATCH] Deployed 453196e9 with MkDocs version: 0.16.3 --- api-guide/parsers/index.html | 2 +- api-guide/permissions/index.html | 4 +- api-guide/relations/index.html | 7 +- api-guide/renderers/index.html | 14 +- api-guide/schemas/index.html | 11 +- api-guide/testing/index.html | 2 +- community/3.0-announcement/index.html | 2 +- community/3.1-announcement/index.html | 12 +- community/3.2-announcement/index.html | 2 +- community/3.4-announcement/index.html | 6 +- community/3.5-announcement/index.html | 6 +- community/3.6-announcement/index.html | 8 +- community/3.7-announcement/index.html | 8 +- community/3.8-announcement/index.html | 2 +- community/3.9-announcement/index.html | 6 +- community/funding/index.html | 10 +- community/jobs/index.html | 2 - community/kickstarter-announcement/index.html | 12 +- community/release-notes/index.html | 9 ++ index.html | 4 +- mkdocs/search_index.json | 78 +++++------ sitemap.xml | 128 +++++++++--------- topics/browsable-api/index.html | 4 +- .../index.html | 6 +- tutorial/quickstart/index.html | 12 +- 25 files changed, 180 insertions(+), 177 deletions(-) diff --git a/api-guide/parsers/index.html b/api-guide/parsers/index.html index ab6d30322..43c16b91b 100644 --- a/api-guide/parsers/index.html +++ b/api-guide/parsers/index.html @@ -571,7 +571,7 @@ def example_view(request, format=None):

.media_type: */*

Notes:
diff --git a/api-guide/permissions/index.html b/api-guide/permissions/index.html index ae4db303f..79c3dbae0 100644 --- a/api-guide/permissions/index.html +++ b/api-guide/permissions/index.html @@ -591,7 +591,7 @@ def example_view(request, format=None):

Note: when you set new permission classes through class attribute or decorators you're telling the view to ignore the default list set over the settings.py file.

Provided they inherit from rest_framework.permissions.BasePermission, permissions can be composed using standard Python bitwise operators. For example, IsAuthenticatedOrReadOnly could be written:

-
from rest_framework.permissions import BasePermission, IsAuthenticated
+
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
 from rest_framework.response import Response
 from rest_framework.views import APIView
 
@@ -714,7 +714,7 @@ class BlacklistPermission(permissions.BasePermission):
 

Composed Permissions

The Composed Permissions package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components.

REST Condition

-

The REST Condition package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.

+

The REST Condition package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.

DRY Rest Permissions

The DRY Rest Permissions package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrieve per user.

Django Rest Framework Roles

diff --git a/api-guide/relations/index.html b/api-guide/relations/index.html index b4f8e8c18..a4d6ce2d0 100644 --- a/api-guide/relations/index.html +++ b/api-guide/relations/index.html @@ -536,9 +536,8 @@

Serializer relations

-

Bad programmers worry about the code. -Good programmers worry about data structures and their relationships.

-

Linus Torvalds

+

Data structures, not algorithms, are central to programming.

+

Rob Pike

Relational fields are used to represent model relationships. They can be applied to ForeignKey, ManyToManyField and OneToOneField relationships, as well as to reverse relationships, and custom relationships such as GenericForeignKey.


@@ -549,7 +548,7 @@ Good programmers worry about data structures and their relationships.

To do so, open the Django shell, using python manage.py shell, then import the serializer class, instantiate it, and print the object representation…

>>> from myapp.serializers import AccountSerializer
 >>> serializer = AccountSerializer()
->>> print repr(serializer)  # Or `print(repr(serializer))` in Python 3.x.
+>>> print(repr(serializer))
 AccountSerializer():
     id = IntegerField(label='ID', read_only=True)
     name = CharField(allow_blank=True, max_length=100, required=False)
diff --git a/api-guide/renderers/index.html b/api-guide/renderers/index.html
index 75f5bc8c7..778083e6a 100644
--- a/api-guide/renderers/index.html
+++ b/api-guide/renderers/index.html
@@ -633,7 +633,7 @@ def user_count_view(request, format=None):
 

The default JSON encoding style can be altered using the UNICODE_JSON and COMPACT_JSON settings keys.

.media_type: application/json

-

.format: '.json'

+

.format: 'json'

.charset: None

TemplateHTMLRenderer

Renders data to HTML, using Django's standard template rendering. @@ -661,7 +661,7 @@ Unlike other renderers, the data passed to the Response does not ne

If you're building websites that use TemplateHTMLRenderer along with other renderer classes, you should consider listing TemplateHTMLRenderer as the first class in the renderer_classes list, so that it will be prioritised first even for browsers that send poorly formed ACCEPT: headers.

See the HTML & Forms Topic Page for further examples of TemplateHTMLRenderer usage.

.media_type: text/html

-

.format: '.html'

+

.format: 'html'

.charset: utf-8

See also: StaticHTMLRenderer

StaticHTMLRenderer

@@ -675,7 +675,7 @@ def simple_html_view(request):

You can use StaticHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.

.media_type: text/html

-

.format: '.html'

+

.format: 'html'

.charset: utf-8

See also: TemplateHTMLRenderer

BrowsableAPIRenderer

@@ -683,7 +683,7 @@ def simple_html_view(request):

The BrowsableAPIRenderer

This renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page.

.media_type: text/html

-

.format: '.api'

+

.format: 'api'

.charset: utf-8

.template: 'rest_framework/api.html'

Customizing BrowsableAPIRenderer

@@ -705,7 +705,7 @@ def simple_html_view(request): model = Account

.media_type: text/html

-

.format: '.admin'

+

.format: 'admin'

.charset: utf-8

.template: 'rest_framework/admin.html'

HTMLFormRenderer

@@ -721,13 +721,13 @@ def simple_html_view(request):

For more information see the HTML & Forms documentation.

.media_type: text/html

-

.format: '.form'

+

.format: 'form'

.charset: utf-8

.template: 'rest_framework/horizontal/form.html'

MultiPartRenderer

This renderer is used for rendering HTML multipart form data. It is not suitable as a response renderer, but is instead used for creating test requests, using REST framework's test client and test request factory.

.media_type: multipart/form-data; boundary=BoUnDaRyStRiNg

-

.format: '.multipart'

+

.format: 'multipart'

.charset: utf-8


Custom renderers

diff --git a/api-guide/schemas/index.html b/api-guide/schemas/index.html index be1ce89f3..87f266358 100644 --- a/api-guide/schemas/index.html +++ b/api-guide/schemas/index.html @@ -503,10 +503,6 @@ drf-yasg - Yet Another Swagger Generator -
  • - DRF OpenAPI -
  • -
    @@ -619,8 +615,8 @@ has to be rendered into the actual bytes that are used in the response.

    REST framework includes a few different renderers that you can use for encoding the API schema.

    @@ -1158,9 +1154,6 @@ Valid only if a location="body" field is included on the Link

    drf-yasg - Yet Another Swagger Generator

    drf-yasg generates OpenAPI documents suitable for code generation - nested schemas, named models, response bodies, enum/pattern/min/max validators, form parameters, etc.

    -

    DRF OpenAPI

    -

    DRF OpenAPI renders the schema generated by Django Rest Framework -in OpenAPI format.

    diff --git a/api-guide/testing/index.html b/api-guide/testing/index.html index ea79a4dd2..9ced7f338 100644 --- a/api-guide/testing/index.html +++ b/api-guide/testing/index.html @@ -694,7 +694,7 @@ response = client.get('http://testserver/users/') assert response.status_code == 200

    Note that the requests client requires you to pass fully qualified URLs.

    -

    RequestsClient and working with the database

    +

    RequestsClient and working with the database

    The RequestsClient class is useful if you want to write tests that solely interact with the service interface. This is a little stricter than using the standard Django test client, as it means that all interactions should be via the API.

    If you're using RequestsClient you'll want to ensure that test setup, and results assertions are performed as regular API calls, rather than interacting with the database models directly. For example, rather than checking that Customer.objects.count() == 3 you would list the customers endpoint, and ensure that it contains three records.

    Headers & Authentication

    diff --git a/community/3.0-announcement/index.html b/community/3.0-announcement/index.html index 6eb2acc70..4c55848ea 100644 --- a/community/3.0-announcement/index.html +++ b/community/3.0-announcement/index.html @@ -465,7 +465,7 @@

    This release is incremental in nature. There are some breaking API changes, and upgrading will require you to read the release notes carefully, but the migration path should otherwise be relatively straightforward.

    The difference in quality of the REST framework API and implementation should make writing, maintaining and debugging your application far easier.

    3.0 is the first of three releases that have been funded by our recent Kickstarter campaign.

    -

    As ever, a huge thank you to our many wonderful sponsors. If you're looking for a Django gig, and want to work with smart community-minded folks, you should probably check out that list and see who's hiring.

    +

    As ever, a huge thank you to our many wonderful sponsors. If you're looking for a Django gig, and want to work with smart community-minded folks, you should probably check out that list and see who's hiring.


    New features

    Notable features of this new release include:

    diff --git a/community/3.1-announcement/index.html b/community/3.1-announcement/index.html index 2efeafdcd..b93d6fb65 100644 --- a/community/3.1-announcement/index.html +++ b/community/3.1-announcement/index.html @@ -476,7 +476,7 @@

    New pagination schemes.

    Until now, there has only been a single built-in pagination style in REST framework. We now have page, limit/offset and cursor based schemes included by default.

    -

    The cursor based pagination scheme is particularly smart, and is a better approach for clients iterating through large or frequently changing result sets. The scheme supports paging against non-unique indexes, by using both cursor and limit/offset information. It also allows for both forward and reverse cursor pagination. Much credit goes to David Cramer for this blog post on the subject.

    +

    The cursor based pagination scheme is particularly smart, and is a better approach for clients iterating through large or frequently changing result sets. The scheme supports paging against non-unique indexes, by using both cursor and limit/offset information. It also allows for both forward and reverse cursor pagination. Much credit goes to David Cramer for this blog post on the subject.

    Pagination controls in the browsable API.

    Paginated results now include controls that render directly in the browsable API. If you're using the page or limit/offset style, then you'll see a page based control displayed in the browsable API:

    page number based pagination

    @@ -535,7 +535,7 @@ Host: example.org

    Note that the structure of the error responses is still the same. We still have a detail key in the response. If needed you can modify this behavior too, by using a custom exception handler.

    We include built-in translations both for standard exception cases, and for serializer validation errors.

    -

    The full list of supported languages can be found on our Transifex project page.

    +

    The full list of supported languages can be found on our Transifex project page.

    If you only wish to support a subset of the supported languages, use Django's standard LANGUAGES setting:

    LANGUAGES = [
         ('de', _('German')),
    @@ -559,13 +559,13 @@ Host: example.org
     

    Moving packages out of core

    We've now moved a number of packages out of the core of REST framework, and into separately installable packages. If you're currently using these you don't need to worry, you simply need to pip install the new packages, and change any import paths.

    We're making this change in order to help distribute the maintenance workload, and keep better focus of the core essentials of the framework.

    -

    The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained Django OAuth toolkit has now been promoted as our recommended option for integrating OAuth support.

    +

    The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained Django OAuth toolkit has now been promoted as our recommended option for integrating OAuth support.

    The following packages are now moved out of core and should be separately installed:

    It's worth reiterating that this change in policy shouldn't mean any work in your codebase other than adding a new requirement and modifying some import paths. For example to install XML rendering, you would now do:

    pip install djangorestframework-xml
    diff --git a/community/3.2-announcement/index.html b/community/3.2-announcement/index.html
    index cdf53e875..1fb3e4c5d 100644
    --- a/community/3.2-announcement/index.html
    +++ b/community/3.2-announcement/index.html
    @@ -446,7 +446,7 @@
     

    This interface is intended to act as a more user-friendly interface to the API. It can be used either as a replacement to the existing BrowsableAPIRenderer, or used together with it, allowing you to switch between the two styles as required.

    We've also fixed a huge number of issues, and made numerous cleanups and improvements.

    Over the course of the 3.1.x series we've resolved nearly 600 tickets on our GitHub issue tracker. This means we're currently running at a rate of closing around 100 issues or pull requests per month.

    -

    None of this would have been possible without the support of our wonderful Kickstarter backers. If you're looking for a job in Django development we'd strongly recommend taking a look through our sponsors and finding out who's hiring.

    +

    None of this would have been possible without the support of our wonderful Kickstarter backers. If you're looking for a job in Django development we'd strongly recommend taking a look through our sponsors and finding out who's hiring.

    AdminRenderer

    To include AdminRenderer simply add it to your settings:

    REST_FRAMEWORK = {
    diff --git a/community/3.4-announcement/index.html b/community/3.4-announcement/index.html
    index 9d04c1dd2..2648c344c 100644
    --- a/community/3.4-announcement/index.html
    +++ b/community/3.4-announcement/index.html
    @@ -472,14 +472,14 @@ continued development by signing up for a paid pla
     Right now we're over 60% of the way towards achieving that.
     Every single sign-up makes a significant impact.

    -

    Many thanks to all our awesome sponsors, and in particular to our premium backers, Rover, Sentry, and Stream.

    +

    Many thanks to all our awesome sponsors, and in particular to our premium backers, Rover, Sentry, and Stream.


    Schemas & client libraries

    REST framework 3.4 brings built-in support for generating API schemas.

    diff --git a/community/3.5-announcement/index.html b/community/3.5-announcement/index.html index aba8c5880..08dda5702 100644 --- a/community/3.5-announcement/index.html +++ b/community/3.5-announcement/index.html @@ -485,15 +485,15 @@ If you use REST framework commercially and would like to see this work continue, we strongly encourage you to invest in its continued development by signing up for a paid plan.

    -

    Many thanks to all our sponsors, and in particular to our premium backers, Rover, Sentry, Stream, and Machinalis.

    +

    Many thanks to all our sponsors, and in particular to our premium backers, Rover, Sentry, Stream, and Machinalis.


    Improved schema generation

    Docstrings on views are now pulled through into schema definitions, allowing diff --git a/community/3.6-announcement/index.html b/community/3.6-announcement/index.html index 274822d2b..3c72716c9 100644 --- a/community/3.6-announcement/index.html +++ b/community/3.6-announcement/index.html @@ -478,17 +478,17 @@ we strongly encourage you to invest in its continued development by signing up for a paid plan.

    -

    Many thanks to all our sponsors, and in particular to our premium backers, Rover, Sentry, Stream, Machinalis, Rollbar, and MicroPyramid.

    +

    Many thanks to all our sponsors, and in particular to our premium backers, Rover, Sentry, Stream, Machinalis, Rollbar, and MicroPyramid.


    Interactive API documentation

    REST framework's new API documentation supports a number of features:

    diff --git a/community/3.7-announcement/index.html b/community/3.7-announcement/index.html index efe9e3c12..febf36c6f 100644 --- a/community/3.7-announcement/index.html +++ b/community/3.7-announcement/index.html @@ -472,16 +472,16 @@

    If you use REST framework commercially and would like to see this work continue, we strongly encourage you to invest in its continued development by signing up for a paid plan.

    -

    As well as our release sponsor, we'd like to say thanks in particular our premium backers, Rover, Sentry, Stream, Machinalis, and Rollbar.

    +

    As well as our release sponsor, we'd like to say thanks in particular our premium backers, Rover, Sentry, Stream, Machinalis, and Rollbar.


    Customizing API docs & schema generation.

    The schema generation introduced in 3.5 and the related API docs generation in 3.6 are both hugely powerful features, however they've been somewhat limited in cases where the view introspection isn't able to correctly identify the schema for a particular view.

    diff --git a/community/3.8-announcement/index.html b/community/3.8-announcement/index.html index 5f0f09516..8fbb58ed2 100644 --- a/community/3.8-announcement/index.html +++ b/community/3.8-announcement/index.html @@ -466,7 +466,7 @@ the foundations for future changes.

    Funding

    If you use REST framework commercially and would like to see this work continue, we strongly encourage you to invest in its continued development by signing up for a paid plan.

    -

    We'd like to say thanks in particular our premium backers, Rover, Sentry, Stream, Machinalis, and Rollbar.

    +

    We'd like to say thanks in particular our premium backers, Rover, Sentry, Stream, Machinalis, and Rollbar.


    Breaking Changes

    Altered the behaviour of read_only plus default on Field.

    diff --git a/community/3.9-announcement/index.html b/community/3.9-announcement/index.html index 1718d51ac..2700b2d59 100644 --- a/community/3.9-announcement/index.html +++ b/community/3.9-announcement/index.html @@ -478,8 +478,8 @@

    If you use REST framework commercially and would like to see this work continue, we strongly encourage you to invest in its continued development by signing up for a paid plan.

    diff --git a/community/release-notes/index.html b/community/release-notes/index.html index 6cdae155d..dbe40ca3b 100644 --- a/community/release-notes/index.html +++ b/community/release-notes/index.html @@ -505,6 +505,13 @@

    3.9.x series

    +

    3.9.1

    +

    Date: 16th Janurary 2019

    +
      +
    • Resolve XSS issue in browsable API. #6330
    • +
    • Resolve issues with composable permissions. #6299
    • +
    • Respect limit_choices_to on foreign keys. #6371
    • +

    3.9.0

    Date: 18th October 2018

    +

    We highly recommend and only officially support the latest patch release of +each Python and Django series.

    The following packages are optional:

    • coreapi (1.32.0+) - Schema generation support.
    • @@ -570,7 +572,7 @@ pip install markdown # Markdown support for the browsable API. pip install django-filter # Filtering support

    ...or clone the project from github.

    -
    git clone git@github.com:encode/django-rest-framework.git
    +
    git clone https://github.com/encode/django-rest-framework
     

    Add 'rest_framework' to your INSTALLED_APPS setting.

    INSTALLED_APPS = (
    diff --git a/mkdocs/search_index.json b/mkdocs/search_index.json
    index ccde7ce44..65d4fbb1f 100644
    --- a/mkdocs/search_index.json
    +++ b/mkdocs/search_index.json
    @@ -2,7 +2,7 @@
         "docs": [
             {
                 "location": "/",
    -            "text": ".promo li a {\n    float: left;\n    width: 130px;\n    height: 20px;\n    text-align: center;\n    margin: 10px 30px;\n    padding: 150px 0 0 0;\n    background-position: 0 50%;\n    background-size: 130px auto;\n    background-repeat: no-repeat;\n    font-size: 120%;\n    color: black;\n}\n.promo li {\n    list-style: none;\n}\n\n\n\n\n\n    \n\n\n    \n\n        \n\n    \n\n\n    \n\n        \n\n    \n\n\n\n\n\n\n\n\n\nDjango REST Framework\n\n\n\n\n\n\n\n\nDjango REST framework is a powerful and flexible toolkit for building Web APIs.\n\n\nSome reasons you might want to use REST framework:\n\n\n\n\nThe \nWeb browsable API\n is a huge usability win for your developers.\n\n\nAuthentication policies\n including packages for \nOAuth1a\n and \nOAuth2\n.\n\n\nSerialization\n that supports both \nORM\n and \nnon-ORM\n data sources.\n\n\nCustomizable all the way down - just use \nregular function-based views\n if you don't need the \nmore\n \npowerful\n \nfeatures\n.\n\n\nExtensive documentation\n, and \ngreat community support\n.\n\n\nUsed and trusted by internationally recognised companies including \nMozilla\n, \nRed Hat\n, \nHeroku\n, and \nEventbrite\n.\n\n\n\n\n\n\nFunding\n\n\nREST framework is a \ncollaboratively funded project\n. If you use\nREST framework commercially we strongly encourage you to invest in its\ncontinued development by \nsigning up for a paid plan\n.\n\n\nEvery single sign-up helps us make REST framework long-term financially sustainable.\n\n\n\n    \nRover.com\n\n    \nSentry\n\n    \nStream\n\n    \nAuklet\n\n    \nRollbar\n\n    \nCadre\n\n    \nLoad Impact\n\n    \nKloudless\n\n    \nLights On Software\n\n\n\n\n\n\n\n\nMany thanks to all our \nwonderful sponsors\n, and in particular to our premium backers, \nRover\n, \nSentry\n, \nStream\n, \nAuklet\n, \nRollbar\n, \nCadre\n, \nLoad Impact\n, \nKloudless\n, and \nLights On Software\n.\n\n\n\n\nRequirements\n\n\nREST framework requires the following:\n\n\n\n\nPython (2.7, 3.4, 3.5, 3.6, 3.7)\n\n\nDjango (1.11, 2.0, 2.1)\n\n\n\n\nThe following packages are optional:\n\n\n\n\ncoreapi\n (1.32.0+) - Schema generation support.\n\n\nMarkdown\n (2.1.0+) - Markdown support for the browsable API.\n\n\ndjango-filter\n (1.0.1+) - Filtering support.\n\n\ndjango-crispy-forms\n - Improved HTML display for filtering.\n\n\ndjango-guardian\n (1.1.1+) - Object level permissions support.\n\n\n\n\nInstallation\n\n\nInstall using \npip\n, including any optional packages you want...\n\n\npip install djangorestframework\npip install markdown       # Markdown support for the browsable API.\npip install django-filter  # Filtering support\n\n\n\n...or clone the project from github.\n\n\ngit clone git@github.com:encode/django-rest-framework.git\n\n\n\nAdd \n'rest_framework'\n to your \nINSTALLED_APPS\n setting.\n\n\nINSTALLED_APPS = (\n    ...\n    'rest_framework',\n)\n\n\n\nIf you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views.  Add the following to your root \nurls.py\n file.\n\n\nurlpatterns = [\n    ...\n    url(r'^api-auth/', include('rest_framework.urls'))\n]\n\n\n\nNote that the URL path can be whatever you want.\n\n\nExample\n\n\nLet's take a look at a quick example of using REST framework to build a simple model-backed API.\n\n\nWe'll create a read-write API for accessing information on the users of our project.\n\n\nAny global settings for a REST framework API are kept in a single configuration dictionary named \nREST_FRAMEWORK\n.  Start off by adding the following to your \nsettings.py\n module:\n\n\nREST_FRAMEWORK = {\n    # Use Django's standard `django.contrib.auth` permissions,\n    # or allow read-only access for unauthenticated users.\n    'DEFAULT_PERMISSION_CLASSES': [\n        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'\n    ]\n}\n\n\n\nDon't forget to make sure you've also added \nrest_framework\n to your \nINSTALLED_APPS\n.\n\n\nWe're ready to create our API now.\nHere's our project's root \nurls.py\n module:\n\n\nfrom django.conf.urls import url, include\nfrom django.contrib.auth.models import User\nfrom rest_framework import routers, serializers, viewsets\n\n# Serializers define the API representation.\nclass UserSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = User\n        fields = ('url', 'username', 'email', 'is_staff')\n\n# ViewSets define the view behavior.\nclass UserViewSet(viewsets.ModelViewSet):\n    queryset = User.objects.all()\n    serializer_class = UserSerializer\n\n# Routers provide an easy way of automatically determining the URL conf.\nrouter = routers.DefaultRouter()\nrouter.register(r'users', UserViewSet)\n\n# Wire up our API using automatic URL routing.\n# Additionally, we include login URLs for the browsable API.\nurlpatterns = [\n    url(r'^', include(router.urls)),\n    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))\n]\n\n\n\nYou can now open the API in your browser at \nhttp://127.0.0.1:8000/\n, and view your new 'users' API. If you use the login control in the top right corner you'll also be able to add, create and delete users from the system.\n\n\nQuickstart\n\n\nCan't wait to get started? The \nquickstart guide\n is the fastest way to get up and running, and building APIs with REST framework.\n\n\nDevelopment\n\n\nSee the \nContribution guidelines\n for information on how to clone\nthe repository, run the test suite and contribute changes back to REST\nFramework.\n\n\nSupport\n\n\nFor support please see the \nREST framework discussion group\n, try the  \n#restframework\n channel on \nirc.freenode.net\n, search \nthe IRC archives\n, or raise a  question on \nStack Overflow\n, making sure to include the \n'django-rest-framework'\n tag.\n\n\nFor priority support please sign up for a \nprofessional or premium sponsorship plan\n.\n\n\nFor updates on REST framework development, you may also want to follow \nthe author\n on Twitter.\n\n\nFollow @_tomchristie\n\n\n!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=\"//platform.twitter.com/widgets.js\";fjs.parentNode.insertBefore(js,fjs);}}(document,\"script\",\"twitter-wjs\");\n\n\nSecurity\n\n\nIf you believe you\u2019ve found something in Django REST framework which has security implications, please \ndo not raise the issue in a public forum\n.\n\n\nSend a description of the issue via email to \nrest-framework-security@googlegroups.com\n.  The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure.\n\n\nLicense\n\n\nCopyright \u00a9 2011-present, \nEncode OSS Ltd\n.\nAll rights reserved.\n\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n\n\n\n\n\nRedistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n\n\n\n\n\nRedistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n\n\n\n\n\nNeither the name of the copyright holder nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\n\n\n\n\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
    +            "text": ".promo li a {\n    float: left;\n    width: 130px;\n    height: 20px;\n    text-align: center;\n    margin: 10px 30px;\n    padding: 150px 0 0 0;\n    background-position: 0 50%;\n    background-size: 130px auto;\n    background-repeat: no-repeat;\n    font-size: 120%;\n    color: black;\n}\n.promo li {\n    list-style: none;\n}\n\n\n\n\n\n    \n\n\n    \n\n        \n\n    \n\n\n    \n\n        \n\n    \n\n\n\n\n\n\n\n\n\nDjango REST Framework\n\n\n\n\n\n\n\n\nDjango REST framework is a powerful and flexible toolkit for building Web APIs.\n\n\nSome reasons you might want to use REST framework:\n\n\n\n\nThe \nWeb browsable API\n is a huge usability win for your developers.\n\n\nAuthentication policies\n including packages for \nOAuth1a\n and \nOAuth2\n.\n\n\nSerialization\n that supports both \nORM\n and \nnon-ORM\n data sources.\n\n\nCustomizable all the way down - just use \nregular function-based views\n if you don't need the \nmore\n \npowerful\n \nfeatures\n.\n\n\nExtensive documentation\n, and \ngreat community support\n.\n\n\nUsed and trusted by internationally recognised companies including \nMozilla\n, \nRed Hat\n, \nHeroku\n, and \nEventbrite\n.\n\n\n\n\n\n\nFunding\n\n\nREST framework is a \ncollaboratively funded project\n. If you use\nREST framework commercially we strongly encourage you to invest in its\ncontinued development by \nsigning up for a paid plan\n.\n\n\nEvery single sign-up helps us make REST framework long-term financially sustainable.\n\n\n\n    \nRover.com\n\n    \nSentry\n\n    \nStream\n\n    \nAuklet\n\n    \nRollbar\n\n    \nCadre\n\n    \nLoad Impact\n\n    \nKloudless\n\n    \nLights On Software\n\n\n\n\n\n\n\n\nMany thanks to all our \nwonderful sponsors\n, and in particular to our premium backers, \nRover\n, \nSentry\n, \nStream\n, \nAuklet\n, \nRollbar\n, \nCadre\n, \nLoad Impact\n, \nKloudless\n, and \nLights On Software\n.\n\n\n\n\nRequirements\n\n\nREST framework requires the following:\n\n\n\n\nPython (2.7, 3.4, 3.5, 3.6, 3.7)\n\n\nDjango (1.11, 2.0, 2.1)\n\n\n\n\nWe \nhighly recommend\n and only officially support the latest patch release of\neach Python and Django series.\n\n\nThe following packages are optional:\n\n\n\n\ncoreapi\n (1.32.0+) - Schema generation support.\n\n\nMarkdown\n (2.1.0+) - Markdown support for the browsable API.\n\n\ndjango-filter\n (1.0.1+) - Filtering support.\n\n\ndjango-crispy-forms\n - Improved HTML display for filtering.\n\n\ndjango-guardian\n (1.1.1+) - Object level permissions support.\n\n\n\n\nInstallation\n\n\nInstall using \npip\n, including any optional packages you want...\n\n\npip install djangorestframework\npip install markdown       # Markdown support for the browsable API.\npip install django-filter  # Filtering support\n\n\n\n...or clone the project from github.\n\n\ngit clone https://github.com/encode/django-rest-framework\n\n\n\nAdd \n'rest_framework'\n to your \nINSTALLED_APPS\n setting.\n\n\nINSTALLED_APPS = (\n    ...\n    'rest_framework',\n)\n\n\n\nIf you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views.  Add the following to your root \nurls.py\n file.\n\n\nurlpatterns = [\n    ...\n    url(r'^api-auth/', include('rest_framework.urls'))\n]\n\n\n\nNote that the URL path can be whatever you want.\n\n\nExample\n\n\nLet's take a look at a quick example of using REST framework to build a simple model-backed API.\n\n\nWe'll create a read-write API for accessing information on the users of our project.\n\n\nAny global settings for a REST framework API are kept in a single configuration dictionary named \nREST_FRAMEWORK\n.  Start off by adding the following to your \nsettings.py\n module:\n\n\nREST_FRAMEWORK = {\n    # Use Django's standard `django.contrib.auth` permissions,\n    # or allow read-only access for unauthenticated users.\n    'DEFAULT_PERMISSION_CLASSES': [\n        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'\n    ]\n}\n\n\n\nDon't forget to make sure you've also added \nrest_framework\n to your \nINSTALLED_APPS\n.\n\n\nWe're ready to create our API now.\nHere's our project's root \nurls.py\n module:\n\n\nfrom django.conf.urls import url, include\nfrom django.contrib.auth.models import User\nfrom rest_framework import routers, serializers, viewsets\n\n# Serializers define the API representation.\nclass UserSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = User\n        fields = ('url', 'username', 'email', 'is_staff')\n\n# ViewSets define the view behavior.\nclass UserViewSet(viewsets.ModelViewSet):\n    queryset = User.objects.all()\n    serializer_class = UserSerializer\n\n# Routers provide an easy way of automatically determining the URL conf.\nrouter = routers.DefaultRouter()\nrouter.register(r'users', UserViewSet)\n\n# Wire up our API using automatic URL routing.\n# Additionally, we include login URLs for the browsable API.\nurlpatterns = [\n    url(r'^', include(router.urls)),\n    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))\n]\n\n\n\nYou can now open the API in your browser at \nhttp://127.0.0.1:8000/\n, and view your new 'users' API. If you use the login control in the top right corner you'll also be able to add, create and delete users from the system.\n\n\nQuickstart\n\n\nCan't wait to get started? The \nquickstart guide\n is the fastest way to get up and running, and building APIs with REST framework.\n\n\nDevelopment\n\n\nSee the \nContribution guidelines\n for information on how to clone\nthe repository, run the test suite and contribute changes back to REST\nFramework.\n\n\nSupport\n\n\nFor support please see the \nREST framework discussion group\n, try the  \n#restframework\n channel on \nirc.freenode.net\n, search \nthe IRC archives\n, or raise a  question on \nStack Overflow\n, making sure to include the \n'django-rest-framework'\n tag.\n\n\nFor priority support please sign up for a \nprofessional or premium sponsorship plan\n.\n\n\nFor updates on REST framework development, you may also want to follow \nthe author\n on Twitter.\n\n\nFollow @_tomchristie\n\n\n!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=\"//platform.twitter.com/widgets.js\";fjs.parentNode.insertBefore(js,fjs);}}(document,\"script\",\"twitter-wjs\");\n\n\nSecurity\n\n\nIf you believe you\u2019ve found something in Django REST framework which has security implications, please \ndo not raise the issue in a public forum\n.\n\n\nSend a description of the issue via email to \nrest-framework-security@googlegroups.com\n.  The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure.\n\n\nLicense\n\n\nCopyright \u00a9 2011-present, \nEncode OSS Ltd\n.\nAll rights reserved.\n\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n\n\n\n\n\nRedistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n\n\n\n\n\nRedistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n\n\n\n\n\nNeither the name of the copyright holder nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\n\n\n\n\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
                 "title": "Home"
             },
             {
    @@ -12,12 +12,12 @@
             },
             {
                 "location": "/#requirements",
    -            "text": "REST framework requires the following:   Python (2.7, 3.4, 3.5, 3.6, 3.7)  Django (1.11, 2.0, 2.1)   The following packages are optional:   coreapi  (1.32.0+) - Schema generation support.  Markdown  (2.1.0+) - Markdown support for the browsable API.  django-filter  (1.0.1+) - Filtering support.  django-crispy-forms  - Improved HTML display for filtering.  django-guardian  (1.1.1+) - Object level permissions support.",
    +            "text": "REST framework requires the following:   Python (2.7, 3.4, 3.5, 3.6, 3.7)  Django (1.11, 2.0, 2.1)   We  highly recommend  and only officially support the latest patch release of\neach Python and Django series.  The following packages are optional:   coreapi  (1.32.0+) - Schema generation support.  Markdown  (2.1.0+) - Markdown support for the browsable API.  django-filter  (1.0.1+) - Filtering support.  django-crispy-forms  - Improved HTML display for filtering.  django-guardian  (1.1.1+) - Object level permissions support.",
                 "title": "Requirements"
             },
             {
                 "location": "/#installation",
    -            "text": "Install using  pip , including any optional packages you want...  pip install djangorestframework\npip install markdown       # Markdown support for the browsable API.\npip install django-filter  # Filtering support  ...or clone the project from github.  git clone git@github.com:encode/django-rest-framework.git  Add  'rest_framework'  to your  INSTALLED_APPS  setting.  INSTALLED_APPS = (\n    ...\n    'rest_framework',\n)  If you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views.  Add the following to your root  urls.py  file.  urlpatterns = [\n    ...\n    url(r'^api-auth/', include('rest_framework.urls'))\n]  Note that the URL path can be whatever you want.",
    +            "text": "Install using  pip , including any optional packages you want...  pip install djangorestframework\npip install markdown       # Markdown support for the browsable API.\npip install django-filter  # Filtering support  ...or clone the project from github.  git clone https://github.com/encode/django-rest-framework  Add  'rest_framework'  to your  INSTALLED_APPS  setting.  INSTALLED_APPS = (\n    ...\n    'rest_framework',\n)  If you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views.  Add the following to your root  urls.py  file.  urlpatterns = [\n    ...\n    url(r'^api-auth/', include('rest_framework.urls'))\n]  Note that the URL path can be whatever you want.",
                 "title": "Installation"
             },
             {
    @@ -52,7 +52,7 @@
             },
             {
                 "location": "/tutorial/quickstart/",
    -            "text": "Quickstart\n\n\nWe're going to create a simple API to allow admin users to view and edit the users and groups in the system.\n\n\nProject setup\n\n\nCreate a new Django project named \ntutorial\n, then start a new app called \nquickstart\n.\n\n\n# Create the project directory\nmkdir tutorial\ncd tutorial\n\n# Create a virtualenv to isolate our package dependencies locally\nvirtualenv env\nsource env/bin/activate  # On Windows use `env\\Scripts\\activate`\n\n# Install Django and Django REST framework into the virtualenv\npip install django\npip install djangorestframework\n\n# Set up a new project with a single application\ndjango-admin startproject tutorial .  # Note the trailing '.' character\ncd tutorial\ndjango-admin startapp quickstart\ncd ..\n\n\n\nThe project layout should look like:\n\n\n$ pwd\n/tutorial\n$ find .\n.\n./manage.py\n./tutorial\n./tutorial/__init__.py\n./tutorial/quickstart\n./tutorial/quickstart/__init__.py\n./tutorial/quickstart/admin.py\n./tutorial/quickstart/apps.py\n./tutorial/quickstart/migrations\n./tutorial/quickstart/migrations/__init__.py\n./tutorial/quickstart/models.py\n./tutorial/quickstart/tests.py\n./tutorial/quickstart/views.py\n./tutorial/settings.py\n./tutorial/urls.py\n./tutorial/wsgi.py\n\n\n\nIt may look unusual that the application has been created within the project directory. Using the project's namespace avoids name clashes with external module (topic goes outside the scope of the quickstart).\n\n\nNow sync your database for the first time:\n\n\npython manage.py migrate\n\n\n\nWe'll also create an initial user named \nadmin\n with a password of \npassword123\n. We'll authenticate as that user later in our example.\n\n\npython manage.py createsuperuser --email admin@example.com --username admin\n\n\n\nOnce you've set up a database and the initial user is created and ready to go, open up the app's directory and we'll get coding...\n\n\nSerializers\n\n\nFirst up we're going to define some serializers. Let's create a new module named \ntutorial/quickstart/serializers.py\n that we'll use for our data representations.\n\n\nfrom django.contrib.auth.models import User, Group\nfrom rest_framework import serializers\n\n\nclass UserSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = User\n        fields = ('url', 'username', 'email', 'groups')\n\n\nclass GroupSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = Group\n        fields = ('url', 'name')\n\n\n\nNotice that we're using hyperlinked relations in this case, with \nHyperlinkedModelSerializer\n.  You can also use primary key and various other relationships, but hyperlinking is good RESTful design.\n\n\nViews\n\n\nRight, we'd better write some views then.  Open \ntutorial/quickstart/views.py\n and get typing.\n\n\nfrom django.contrib.auth.models import User, Group\nfrom rest_framework import viewsets\nfrom tutorial.quickstart.serializers import UserSerializer, GroupSerializer\n\n\nclass UserViewSet(viewsets.ModelViewSet):\n    \"\"\"\n    API endpoint that allows users to be viewed or edited.\n    \"\"\"\n    queryset = User.objects.all().order_by('-date_joined')\n    serializer_class = UserSerializer\n\n\nclass GroupViewSet(viewsets.ModelViewSet):\n    \"\"\"\n    API endpoint that allows groups to be viewed or edited.\n    \"\"\"\n    queryset = Group.objects.all()\n    serializer_class = GroupSerializer\n\n\n\nRather than write multiple views we're grouping together all the common behavior into classes called \nViewSets\n.\n\n\nWe can easily break these down into individual views if we need to, but using viewsets keeps the view logic nicely organized as well as being very concise.\n\n\nURLs\n\n\nOkay, now let's wire up the API URLs.  On to \ntutorial/urls.py\n...\n\n\nfrom django.conf.urls import url, include\nfrom rest_framework import routers\nfrom tutorial.quickstart import views\n\nrouter = routers.DefaultRouter()\nrouter.register(r'users', views.UserViewSet)\nrouter.register(r'groups', views.GroupViewSet)\n\n# Wire up our API using automatic URL routing.\n# Additionally, we include login URLs for the browsable API.\nurlpatterns = [\n    url(r'^', include(router.urls)),\n    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))\n]\n\n\n\nBecause we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.\n\n\nAgain, if we need more control over the API URLs we can simply drop down to using regular class-based views, and writing the URL conf explicitly.\n\n\nFinally, we're including default login and logout views for use with the browsable API.  That's optional, but useful if your API requires authentication and you want to use the browsable API.\n\n\nPagination\n\n\nPagination allows you to control how many objects per page are returned. To enable it add following lines to the \ntutorial/settings.py\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',\n    'PAGE_SIZE': 10\n}\n\n\n\nSettings\n\n\nAdd \n'rest_framework'\n to \nINSTALLED_APPS\n. The settings module will be in \ntutorial/settings.py\n\n\nINSTALLED_APPS = (\n    ...\n    'rest_framework',\n)\n\n\n\nOkay, we're done.\n\n\n\n\nTesting our API\n\n\nWe're now ready to test the API we've built.  Let's fire up the server from the command line.\n\n\npython manage.py runserver\n\n\n\nWe can now access our API, both from the command-line, using tools like \ncurl\n...\n\n\nbash: curl -H 'Accept: application/json; indent=4' -u admin:password123 http://127.0.0.1:8000/users/\n{\n    \"count\": 2,\n    \"next\": null,\n    \"previous\": null,\n    \"results\": [\n        {\n            \"email\": \"admin@example.com\",\n            \"groups\": [],\n            \"url\": \"http://127.0.0.1:8000/users/1/\",\n            \"username\": \"admin\"\n        },\n        {\n            \"email\": \"tom@example.com\",\n            \"groups\": [                ],\n            \"url\": \"http://127.0.0.1:8000/users/2/\",\n            \"username\": \"tom\"\n        }\n    ]\n}\n\n\n\nOr using the \nhttpie\n, command line tool...\n\n\nbash: http -a admin:password123 http://127.0.0.1:8000/users/\n\nHTTP/1.1 200 OK\n...\n{\n    \"count\": 2,\n    \"next\": null,\n    \"previous\": null,\n    \"results\": [\n        {\n            \"email\": \"admin@example.com\",\n            \"groups\": [],\n            \"url\": \"http://localhost:8000/users/1/\",\n            \"username\": \"paul\"\n        },\n        {\n            \"email\": \"tom@example.com\",\n            \"groups\": [                ],\n            \"url\": \"http://127.0.0.1:8000/users/2/\",\n            \"username\": \"tom\"\n        }\n    ]\n}\n\n\n\nOr directly through the browser, by going to the URL \nhttp://127.0.0.1:8000/users/\n...\n\n\n\n\nIf you're working through the browser, make sure to login using the control in the top right corner.\n\n\nGreat, that was easy!\n\n\nIf you want to get a more in depth understanding of how REST framework fits together head on over to \nthe tutorial\n, or start browsing the \nAPI guide\n.",
    +            "text": "Quickstart\n\n\nWe're going to create a simple API to allow admin users to view and edit the users and groups in the system.\n\n\nProject setup\n\n\nCreate a new Django project named \ntutorial\n, then start a new app called \nquickstart\n.\n\n\n# Create the project directory\nmkdir tutorial\ncd tutorial\n\n# Create a virtualenv to isolate our package dependencies locally\nvirtualenv env\nsource env/bin/activate  # On Windows use `env\\Scripts\\activate`\n\n# Install Django and Django REST framework into the virtualenv\npip install django\npip install djangorestframework\n\n# Set up a new project with a single application\ndjango-admin startproject tutorial .  # Note the trailing '.' character\ncd tutorial\ndjango-admin startapp quickstart\ncd ..\n\n\n\nThe project layout should look like:\n\n\n$ pwd\n/tutorial\n$ find .\n.\n./manage.py\n./tutorial\n./tutorial/__init__.py\n./tutorial/quickstart\n./tutorial/quickstart/__init__.py\n./tutorial/quickstart/admin.py\n./tutorial/quickstart/apps.py\n./tutorial/quickstart/migrations\n./tutorial/quickstart/migrations/__init__.py\n./tutorial/quickstart/models.py\n./tutorial/quickstart/tests.py\n./tutorial/quickstart/views.py\n./tutorial/settings.py\n./tutorial/urls.py\n./tutorial/wsgi.py\n\n\n\nIt may look unusual that the application has been created within the project directory. Using the project's namespace avoids name clashes with external modules (a topic that goes outside the scope of the quickstart).\n\n\nNow sync your database for the first time:\n\n\npython manage.py migrate\n\n\n\nWe'll also create an initial user named \nadmin\n with a password of \npassword123\n. We'll authenticate as that user later in our example.\n\n\npython manage.py createsuperuser --email admin@example.com --username admin\n\n\n\nOnce you've set up a database and the initial user is created and ready to go, open up the app's directory and we'll get coding...\n\n\nSerializers\n\n\nFirst up we're going to define some serializers. Let's create a new module named \ntutorial/quickstart/serializers.py\n that we'll use for our data representations.\n\n\nfrom django.contrib.auth.models import User, Group\nfrom rest_framework import serializers\n\n\nclass UserSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = User\n        fields = ('url', 'username', 'email', 'groups')\n\n\nclass GroupSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = Group\n        fields = ('url', 'name')\n\n\n\nNotice that we're using hyperlinked relations in this case with \nHyperlinkedModelSerializer\n.  You can also use primary key and various other relationships, but hyperlinking is good RESTful design.\n\n\nViews\n\n\nRight, we'd better write some views then.  Open \ntutorial/quickstart/views.py\n and get typing.\n\n\nfrom django.contrib.auth.models import User, Group\nfrom rest_framework import viewsets\nfrom tutorial.quickstart.serializers import UserSerializer, GroupSerializer\n\n\nclass UserViewSet(viewsets.ModelViewSet):\n    \"\"\"\n    API endpoint that allows users to be viewed or edited.\n    \"\"\"\n    queryset = User.objects.all().order_by('-date_joined')\n    serializer_class = UserSerializer\n\n\nclass GroupViewSet(viewsets.ModelViewSet):\n    \"\"\"\n    API endpoint that allows groups to be viewed or edited.\n    \"\"\"\n    queryset = Group.objects.all()\n    serializer_class = GroupSerializer\n\n\n\nRather than write multiple views we're grouping together all the common behavior into classes called \nViewSets\n.\n\n\nWe can easily break these down into individual views if we need to, but using viewsets keeps the view logic nicely organized as well as being very concise.\n\n\nURLs\n\n\nOkay, now let's wire up the API URLs.  On to \ntutorial/urls.py\n...\n\n\nfrom django.urls import include, path\nfrom rest_framework import routers\nfrom tutorial.quickstart import views\n\nrouter = routers.DefaultRouter()\nrouter.register(r'users', views.UserViewSet)\nrouter.register(r'groups', views.GroupViewSet)\n\n# Wire up our API using automatic URL routing.\n# Additionally, we include login URLs for the browsable API.\nurlpatterns = [\n    path('', include(router.urls)),\n    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))\n]\n\n\n\nBecause we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.\n\n\nAgain, if we need more control over the API URLs we can simply drop down to using regular class-based views, and writing the URL conf explicitly.\n\n\nFinally, we're including default login and logout views for use with the browsable API.  That's optional, but useful if your API requires authentication and you want to use the browsable API.\n\n\nPagination\n\n\nPagination allows you to control how many objects per page are returned. To enable it add the following lines to \ntutorial/settings.py\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',\n    'PAGE_SIZE': 10\n}\n\n\n\nSettings\n\n\nAdd \n'rest_framework'\n to \nINSTALLED_APPS\n. The settings module will be in \ntutorial/settings.py\n\n\nINSTALLED_APPS = (\n    ...\n    'rest_framework',\n)\n\n\n\nOkay, we're done.\n\n\n\n\nTesting our API\n\n\nWe're now ready to test the API we've built.  Let's fire up the server from the command line.\n\n\npython manage.py runserver\n\n\n\nWe can now access our API, both from the command-line, using tools like \ncurl\n...\n\n\nbash: curl -H 'Accept: application/json; indent=4' -u admin:password123 http://127.0.0.1:8000/users/\n{\n    \"count\": 2,\n    \"next\": null,\n    \"previous\": null,\n    \"results\": [\n        {\n            \"email\": \"admin@example.com\",\n            \"groups\": [],\n            \"url\": \"http://127.0.0.1:8000/users/1/\",\n            \"username\": \"admin\"\n        },\n        {\n            \"email\": \"tom@example.com\",\n            \"groups\": [                ],\n            \"url\": \"http://127.0.0.1:8000/users/2/\",\n            \"username\": \"tom\"\n        }\n    ]\n}\n\n\n\nOr using the \nhttpie\n, command line tool...\n\n\nbash: http -a admin:password123 http://127.0.0.1:8000/users/\n\nHTTP/1.1 200 OK\n...\n{\n    \"count\": 2,\n    \"next\": null,\n    \"previous\": null,\n    \"results\": [\n        {\n            \"email\": \"admin@example.com\",\n            \"groups\": [],\n            \"url\": \"http://localhost:8000/users/1/\",\n            \"username\": \"paul\"\n        },\n        {\n            \"email\": \"tom@example.com\",\n            \"groups\": [                ],\n            \"url\": \"http://127.0.0.1:8000/users/2/\",\n            \"username\": \"tom\"\n        }\n    ]\n}\n\n\n\nOr directly through the browser, by going to the URL \nhttp://127.0.0.1:8000/users/\n...\n\n\n\n\nIf you're working through the browser, make sure to login using the control in the top right corner.\n\n\nGreat, that was easy!\n\n\nIf you want to get a more in depth understanding of how REST framework fits together head on over to \nthe tutorial\n, or start browsing the \nAPI guide\n.",
                 "title": "Quickstart"
             },
             {
    @@ -62,12 +62,12 @@
             },
             {
                 "location": "/tutorial/quickstart/#project-setup",
    -            "text": "Create a new Django project named  tutorial , then start a new app called  quickstart .  # Create the project directory\nmkdir tutorial\ncd tutorial\n\n# Create a virtualenv to isolate our package dependencies locally\nvirtualenv env\nsource env/bin/activate  # On Windows use `env\\Scripts\\activate`\n\n# Install Django and Django REST framework into the virtualenv\npip install django\npip install djangorestframework\n\n# Set up a new project with a single application\ndjango-admin startproject tutorial .  # Note the trailing '.' character\ncd tutorial\ndjango-admin startapp quickstart\ncd ..  The project layout should look like:  $ pwd\n/tutorial\n$ find .\n.\n./manage.py\n./tutorial\n./tutorial/__init__.py\n./tutorial/quickstart\n./tutorial/quickstart/__init__.py\n./tutorial/quickstart/admin.py\n./tutorial/quickstart/apps.py\n./tutorial/quickstart/migrations\n./tutorial/quickstart/migrations/__init__.py\n./tutorial/quickstart/models.py\n./tutorial/quickstart/tests.py\n./tutorial/quickstart/views.py\n./tutorial/settings.py\n./tutorial/urls.py\n./tutorial/wsgi.py  It may look unusual that the application has been created within the project directory. Using the project's namespace avoids name clashes with external module (topic goes outside the scope of the quickstart).  Now sync your database for the first time:  python manage.py migrate  We'll also create an initial user named  admin  with a password of  password123 . We'll authenticate as that user later in our example.  python manage.py createsuperuser --email admin@example.com --username admin  Once you've set up a database and the initial user is created and ready to go, open up the app's directory and we'll get coding...",
    +            "text": "Create a new Django project named  tutorial , then start a new app called  quickstart .  # Create the project directory\nmkdir tutorial\ncd tutorial\n\n# Create a virtualenv to isolate our package dependencies locally\nvirtualenv env\nsource env/bin/activate  # On Windows use `env\\Scripts\\activate`\n\n# Install Django and Django REST framework into the virtualenv\npip install django\npip install djangorestframework\n\n# Set up a new project with a single application\ndjango-admin startproject tutorial .  # Note the trailing '.' character\ncd tutorial\ndjango-admin startapp quickstart\ncd ..  The project layout should look like:  $ pwd\n/tutorial\n$ find .\n.\n./manage.py\n./tutorial\n./tutorial/__init__.py\n./tutorial/quickstart\n./tutorial/quickstart/__init__.py\n./tutorial/quickstart/admin.py\n./tutorial/quickstart/apps.py\n./tutorial/quickstart/migrations\n./tutorial/quickstart/migrations/__init__.py\n./tutorial/quickstart/models.py\n./tutorial/quickstart/tests.py\n./tutorial/quickstart/views.py\n./tutorial/settings.py\n./tutorial/urls.py\n./tutorial/wsgi.py  It may look unusual that the application has been created within the project directory. Using the project's namespace avoids name clashes with external modules (a topic that goes outside the scope of the quickstart).  Now sync your database for the first time:  python manage.py migrate  We'll also create an initial user named  admin  with a password of  password123 . We'll authenticate as that user later in our example.  python manage.py createsuperuser --email admin@example.com --username admin  Once you've set up a database and the initial user is created and ready to go, open up the app's directory and we'll get coding...",
                 "title": "Project setup"
             },
             {
                 "location": "/tutorial/quickstart/#serializers",
    -            "text": "First up we're going to define some serializers. Let's create a new module named  tutorial/quickstart/serializers.py  that we'll use for our data representations.  from django.contrib.auth.models import User, Group\nfrom rest_framework import serializers\n\n\nclass UserSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = User\n        fields = ('url', 'username', 'email', 'groups')\n\n\nclass GroupSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = Group\n        fields = ('url', 'name')  Notice that we're using hyperlinked relations in this case, with  HyperlinkedModelSerializer .  You can also use primary key and various other relationships, but hyperlinking is good RESTful design.",
    +            "text": "First up we're going to define some serializers. Let's create a new module named  tutorial/quickstart/serializers.py  that we'll use for our data representations.  from django.contrib.auth.models import User, Group\nfrom rest_framework import serializers\n\n\nclass UserSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = User\n        fields = ('url', 'username', 'email', 'groups')\n\n\nclass GroupSerializer(serializers.HyperlinkedModelSerializer):\n    class Meta:\n        model = Group\n        fields = ('url', 'name')  Notice that we're using hyperlinked relations in this case with  HyperlinkedModelSerializer .  You can also use primary key and various other relationships, but hyperlinking is good RESTful design.",
                 "title": "Serializers"
             },
             {
    @@ -77,12 +77,12 @@
             },
             {
                 "location": "/tutorial/quickstart/#urls",
    -            "text": "Okay, now let's wire up the API URLs.  On to  tutorial/urls.py ...  from django.conf.urls import url, include\nfrom rest_framework import routers\nfrom tutorial.quickstart import views\n\nrouter = routers.DefaultRouter()\nrouter.register(r'users', views.UserViewSet)\nrouter.register(r'groups', views.GroupViewSet)\n\n# Wire up our API using automatic URL routing.\n# Additionally, we include login URLs for the browsable API.\nurlpatterns = [\n    url(r'^', include(router.urls)),\n    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))\n]  Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.  Again, if we need more control over the API URLs we can simply drop down to using regular class-based views, and writing the URL conf explicitly.  Finally, we're including default login and logout views for use with the browsable API.  That's optional, but useful if your API requires authentication and you want to use the browsable API.",
    +            "text": "Okay, now let's wire up the API URLs.  On to  tutorial/urls.py ...  from django.urls import include, path\nfrom rest_framework import routers\nfrom tutorial.quickstart import views\n\nrouter = routers.DefaultRouter()\nrouter.register(r'users', views.UserViewSet)\nrouter.register(r'groups', views.GroupViewSet)\n\n# Wire up our API using automatic URL routing.\n# Additionally, we include login URLs for the browsable API.\nurlpatterns = [\n    path('', include(router.urls)),\n    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))\n]  Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.  Again, if we need more control over the API URLs we can simply drop down to using regular class-based views, and writing the URL conf explicitly.  Finally, we're including default login and logout views for use with the browsable API.  That's optional, but useful if your API requires authentication and you want to use the browsable API.",
                 "title": "URLs"
             },
             {
                 "location": "/tutorial/quickstart/#pagination",
    -            "text": "Pagination allows you to control how many objects per page are returned. To enable it add following lines to the  tutorial/settings.py  REST_FRAMEWORK = {\n    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',\n    'PAGE_SIZE': 10\n}",
    +            "text": "Pagination allows you to control how many objects per page are returned. To enable it add the following lines to  tutorial/settings.py  REST_FRAMEWORK = {\n    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',\n    'PAGE_SIZE': 10\n}",
                 "title": "Pagination"
             },
             {
    @@ -237,7 +237,7 @@
             },
             {
                 "location": "/tutorial/4-authentication-and-permissions/",
    -            "text": "Tutorial 4: Authentication & Permissions\n\n\nCurrently our API doesn't have any restrictions on who can edit or delete code snippets.  We'd like to have some more advanced behavior in order to make sure that:\n\n\n\n\nCode snippets are always associated with a creator.\n\n\nOnly authenticated users may create snippets.\n\n\nOnly the creator of a snippet may update or delete it.\n\n\nUnauthenticated requests should have full read-only access.\n\n\n\n\nAdding information to our model\n\n\nWe're going to make a couple of changes to our \nSnippet\n model class.\nFirst, let's add a couple of fields.  One of those fields will be used to represent the user who created the code snippet.  The other field will be used to store the highlighted HTML representation of the code.\n\n\nAdd the following two fields to the \nSnippet\n model in \nmodels.py\n.\n\n\nowner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)\nhighlighted = models.TextField()\n\n\n\nWe'd also need to make sure that when the model is saved, that we populate the highlighted field, using the \npygments\n code highlighting library.\n\n\nWe'll need some extra imports:\n\n\nfrom pygments.lexers import get_lexer_by_name\nfrom pygments.formatters.html import HtmlFormatter\nfrom pygments import highlight\n\n\n\nAnd now we can add a \n.save()\n method to our model class:\n\n\ndef save(self, *args, **kwargs):\n    \"\"\"\n    Use the `pygments` library to create a highlighted HTML\n    representation of the code snippet.\n    \"\"\"\n    lexer = get_lexer_by_name(self.language)\n    linenos = 'table' if self.linenos else False\n    options = {'title': self.title} if self.title else {}\n    formatter = HtmlFormatter(style=self.style, linenos=linenos,\n                              full=True, **options)\n    self.highlighted = highlight(self.code, lexer, formatter)\n    super(Snippet, self).save(*args, **kwargs)\n\n\n\nWhen that's all done we'll need to update our database tables.\nNormally we'd create a database migration in order to do that, but for the purposes of this tutorial, let's just delete the database and start again.\n\n\nrm -f db.sqlite3\nrm -r snippets/migrations\npython manage.py makemigrations snippets\npython manage.py migrate\n\n\n\nYou might also want to create a few different users, to use for testing the API.  The quickest way to do this will be with the \ncreatesuperuser\n command.\n\n\npython manage.py createsuperuser\n\n\n\nAdding endpoints for our User models\n\n\nNow that we've got some users to work with, we'd better add representations of those users to our API.  Creating a new serializer is easy. In \nserializers.py\n add:\n\n\nfrom django.contrib.auth.models import User\n\nclass UserSerializer(serializers.ModelSerializer):\n    snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())\n\n    class Meta:\n        model = User\n        fields = ('id', 'username', 'snippets')\n\n\n\nBecause \n'snippets'\n is a \nreverse\n relationship on the User model, it will not be included by default when using the \nModelSerializer\n class, so we needed to add an explicit field for it.\n\n\nWe'll also add a couple of views to \nviews.py\n.  We'd like to just use read-only views for the user representations, so we'll use the \nListAPIView\n and \nRetrieveAPIView\n generic class-based views.\n\n\nfrom django.contrib.auth.models import User\n\n\nclass UserList(generics.ListAPIView):\n    queryset = User.objects.all()\n    serializer_class = UserSerializer\n\n\nclass UserDetail(generics.RetrieveAPIView):\n    queryset = User.objects.all()\n    serializer_class = UserSerializer\n\n\n\nMake sure to also import the \nUserSerializer\n class\n\n\nfrom snippets.serializers import UserSerializer\n\n\n\nFinally we need to add those views into the API, by referencing them from the URL conf. Add the following to the patterns in \nsnippets/urls.py\n.\n\n\npath('users/', views.UserList.as_view()),\npath('users//', views.UserDetail.as_view()),\n\n\n\nAssociating Snippets with Users\n\n\nRight now, if we created a code snippet, there'd be no way of associating the user that created the snippet, with the snippet instance.  The user isn't sent as part of the serialized representation, but is instead a property of the incoming request.\n\n\nThe way we deal with that is by overriding a \n.perform_create()\n method on our snippet views, that allows us to modify how the instance save is managed, and handle any information that is implicit in the incoming request or requested URL.\n\n\nOn the \nSnippetList\n view class, add the following method:\n\n\ndef perform_create(self, serializer):\n    serializer.save(owner=self.request.user)\n\n\n\nThe \ncreate()\n method of our serializer will now be passed an additional \n'owner'\n field, along with the validated data from the request.\n\n\nUpdating our serializer\n\n\nNow that snippets are associated with the user that created them, let's update our \nSnippetSerializer\n to reflect that.  Add the following field to the serializer definition in \nserializers.py\n:\n\n\nowner = serializers.ReadOnlyField(source='owner.username')\n\n\n\nNote\n: Make sure you also add \n'owner',\n to the list of fields in the inner \nMeta\n class.\n\n\nThis field is doing something quite interesting.  The \nsource\n argument controls which attribute is used to populate a field, and can point at any attribute on the serialized instance.  It can also take the dotted notation shown above, in which case it will traverse the given attributes, in a similar way as it is used with Django's template language.\n\n\nThe field we've added is the untyped \nReadOnlyField\n class, in contrast to the other typed fields, such as \nCharField\n, \nBooleanField\n etc...  The untyped \nReadOnlyField\n is always read-only, and will be used for serialized representations, but will not be used for updating model instances when they are deserialized. We could have also used \nCharField(read_only=True)\n here.\n\n\nAdding required permissions to views\n\n\nNow that code snippets are associated with users, we want to make sure that only authenticated users are able to create, update and delete code snippets.\n\n\nREST framework includes a number of permission classes that we can use to restrict who can access a given view.  In this case the one we're looking for is \nIsAuthenticatedOrReadOnly\n, which will ensure that authenticated requests get read-write access, and unauthenticated requests get read-only access.\n\n\nFirst add the following import in the views module\n\n\nfrom rest_framework import permissions\n\n\n\nThen, add the following property to \nboth\n the \nSnippetList\n and \nSnippetDetail\n view classes.\n\n\npermission_classes = (permissions.IsAuthenticatedOrReadOnly,)\n\n\n\nAdding login to the Browsable API\n\n\nIf you open a browser and navigate to the browsable API at the moment, you'll find that you're no longer able to create new code snippets.  In order to do so we'd need to be able to login as a user.\n\n\nWe can add a login view for use with the browsable API, by editing the URLconf in our project-level \nurls.py\n file.\n\n\nAdd the following import at the top of the file:\n\n\nfrom django.conf.urls import include\n\n\n\nAnd, at the end of the file, add a pattern to include the login and logout views for the browsable API.\n\n\nurlpatterns += [\n    path('api-auth/', include('rest_framework.urls')),\n]\n\n\n\nThe \n'api-auth/'\n part of pattern can actually be whatever URL you want to use.\n\n\nNow if you open up the browser again and refresh the page you'll see a 'Login' link in the top right of the page.  If you log in as one of the users you created earlier, you'll be able to create code snippets again.\n\n\nOnce you've created a few code snippets, navigate to the '/users/' endpoint, and notice that the representation includes a list of the snippet ids that are associated with each user, in each user's 'snippets' field.\n\n\nObject level permissions\n\n\nReally we'd like all code snippets to be visible to anyone, but also make sure that only the user that created a code snippet is able to update or delete it.\n\n\nTo do that we're going to need to create a custom permission.\n\n\nIn the snippets app, create a new file, \npermissions.py\n\n\nfrom rest_framework import permissions\n\n\nclass IsOwnerOrReadOnly(permissions.BasePermission):\n    \"\"\"\n    Custom permission to only allow owners of an object to edit it.\n    \"\"\"\n\n    def has_object_permission(self, request, view, obj):\n        # Read permissions are allowed to any request,\n        # so we'll always allow GET, HEAD or OPTIONS requests.\n        if request.method in permissions.SAFE_METHODS:\n            return True\n\n        # Write permissions are only allowed to the owner of the snippet.\n        return obj.owner == request.user\n\n\n\nNow we can add that custom permission to our snippet instance endpoint, by editing the \npermission_classes\n property on the \nSnippetDetail\n view class:\n\n\npermission_classes = (permissions.IsAuthenticatedOrReadOnly,\n                      IsOwnerOrReadOnly,)\n\n\n\nMake sure to also import the \nIsOwnerOrReadOnly\n class.\n\n\nfrom snippets.permissions import IsOwnerOrReadOnly\n\n\n\nNow, if you open a browser again, you find that the 'DELETE' and 'PUT' actions only appear on a snippet instance endpoint if you're logged in as the same user that created the code snippet.\n\n\nAuthenticating with the API\n\n\nBecause we now have a set of permissions on the API, we need to authenticate our requests to it if we want to edit any snippets.  We haven't set up any \nauthentication classes\n, so the defaults are currently applied, which are \nSessionAuthentication\n and \nBasicAuthentication\n.\n\n\nWhen we interact with the API through the web browser, we can login, and the browser session will then provide the required authentication for the requests.\n\n\nIf we're interacting with the API programmatically we need to explicitly provide the authentication credentials on each request.\n\n\nIf we try to create a snippet without authenticating, we'll get an error:\n\n\nhttp POST http://127.0.0.1:8000/snippets/ code=\"print 123\"\n\n{\n    \"detail\": \"Authentication credentials were not provided.\"\n}\n\n\n\nWe can make a successful request by including the username and password of one of the users we created earlier.\n\n\nhttp -a admin:password123 POST http://127.0.0.1:8000/snippets/ code=\"print 789\"\n\n{\n    \"id\": 1,\n    \"owner\": \"admin\",\n    \"title\": \"foo\",\n    \"code\": \"print 789\",\n    \"linenos\": false,\n    \"language\": \"python\",\n    \"style\": \"friendly\"\n}\n\n\n\nSummary\n\n\nWe've now got a fairly fine-grained set of permissions on our Web API, and end points for users of the system and for the code snippets that they have created.\n\n\nIn \npart 5\n of the tutorial we'll look at how we can tie everything together by creating an HTML endpoint for our highlighted snippets, and improve the cohesion of our API by using hyperlinking for the relationships within the system.",
    +            "text": "Tutorial 4: Authentication & Permissions\n\n\nCurrently our API doesn't have any restrictions on who can edit or delete code snippets.  We'd like to have some more advanced behavior in order to make sure that:\n\n\n\n\nCode snippets are always associated with a creator.\n\n\nOnly authenticated users may create snippets.\n\n\nOnly the creator of a snippet may update or delete it.\n\n\nUnauthenticated requests should have full read-only access.\n\n\n\n\nAdding information to our model\n\n\nWe're going to make a couple of changes to our \nSnippet\n model class.\nFirst, let's add a couple of fields.  One of those fields will be used to represent the user who created the code snippet.  The other field will be used to store the highlighted HTML representation of the code.\n\n\nAdd the following two fields to the \nSnippet\n model in \nmodels.py\n.\n\n\nowner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)\nhighlighted = models.TextField()\n\n\n\nWe'd also need to make sure that when the model is saved, that we populate the highlighted field, using the \npygments\n code highlighting library.\n\n\nWe'll need some extra imports:\n\n\nfrom pygments.lexers import get_lexer_by_name\nfrom pygments.formatters.html import HtmlFormatter\nfrom pygments import highlight\n\n\n\nAnd now we can add a \n.save()\n method to our model class:\n\n\ndef save(self, *args, **kwargs):\n    \"\"\"\n    Use the `pygments` library to create a highlighted HTML\n    representation of the code snippet.\n    \"\"\"\n    lexer = get_lexer_by_name(self.language)\n    linenos = 'table' if self.linenos else False\n    options = {'title': self.title} if self.title else {}\n    formatter = HtmlFormatter(style=self.style, linenos=linenos,\n                              full=True, **options)\n    self.highlighted = highlight(self.code, lexer, formatter)\n    super(Snippet, self).save(*args, **kwargs)\n\n\n\nWhen that's all done we'll need to update our database tables.\nNormally we'd create a database migration in order to do that, but for the purposes of this tutorial, let's just delete the database and start again.\n\n\nrm -f db.sqlite3\nrm -r snippets/migrations\npython manage.py makemigrations snippets\npython manage.py migrate\n\n\n\nYou might also want to create a few different users, to use for testing the API.  The quickest way to do this will be with the \ncreatesuperuser\n command.\n\n\npython manage.py createsuperuser\n\n\n\nAdding endpoints for our User models\n\n\nNow that we've got some users to work with, we'd better add representations of those users to our API.  Creating a new serializer is easy. In \nserializers.py\n add:\n\n\nfrom django.contrib.auth.models import User\n\nclass UserSerializer(serializers.ModelSerializer):\n    snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())\n\n    class Meta:\n        model = User\n        fields = ('id', 'username', 'snippets')\n\n\n\nBecause \n'snippets'\n is a \nreverse\n relationship on the User model, it will not be included by default when using the \nModelSerializer\n class, so we needed to add an explicit field for it.\n\n\nWe'll also add a couple of views to \nviews.py\n.  We'd like to just use read-only views for the user representations, so we'll use the \nListAPIView\n and \nRetrieveAPIView\n generic class-based views.\n\n\nfrom django.contrib.auth.models import User\n\n\nclass UserList(generics.ListAPIView):\n    queryset = User.objects.all()\n    serializer_class = UserSerializer\n\n\nclass UserDetail(generics.RetrieveAPIView):\n    queryset = User.objects.all()\n    serializer_class = UserSerializer\n\n\n\nMake sure to also import the \nUserSerializer\n class\n\n\nfrom snippets.serializers import UserSerializer\n\n\n\nFinally we need to add those views into the API, by referencing them from the URL conf. Add the following to the patterns in \nsnippets/urls.py\n.\n\n\npath('users/', views.UserList.as_view()),\npath('users//', views.UserDetail.as_view()),\n\n\n\nAssociating Snippets with Users\n\n\nRight now, if we created a code snippet, there'd be no way of associating the user that created the snippet, with the snippet instance.  The user isn't sent as part of the serialized representation, but is instead a property of the incoming request.\n\n\nThe way we deal with that is by overriding a \n.perform_create()\n method on our snippet views, that allows us to modify how the instance save is managed, and handle any information that is implicit in the incoming request or requested URL.\n\n\nOn the \nSnippetList\n view class, add the following method:\n\n\ndef perform_create(self, serializer):\n    serializer.save(owner=self.request.user)\n\n\n\nThe \ncreate()\n method of our serializer will now be passed an additional \n'owner'\n field, along with the validated data from the request.\n\n\nUpdating our serializer\n\n\nNow that snippets are associated with the user that created them, let's update our \nSnippetSerializer\n to reflect that.  Add the following field to the serializer definition in \nserializers.py\n:\n\n\nowner = serializers.ReadOnlyField(source='owner.username')\n\n\n\nNote\n: Make sure you also add \n'owner',\n to the list of fields in the inner \nMeta\n class.\n\n\nThis field is doing something quite interesting.  The \nsource\n argument controls which attribute is used to populate a field, and can point at any attribute on the serialized instance.  It can also take the dotted notation shown above, in which case it will traverse the given attributes, in a similar way as it is used with Django's template language.\n\n\nThe field we've added is the untyped \nReadOnlyField\n class, in contrast to the other typed fields, such as \nCharField\n, \nBooleanField\n etc...  The untyped \nReadOnlyField\n is always read-only, and will be used for serialized representations, but will not be used for updating model instances when they are deserialized. We could have also used \nCharField(read_only=True)\n here.\n\n\nAdding required permissions to views\n\n\nNow that code snippets are associated with users, we want to make sure that only authenticated users are able to create, update and delete code snippets.\n\n\nREST framework includes a number of permission classes that we can use to restrict who can access a given view.  In this case the one we're looking for is \nIsAuthenticatedOrReadOnly\n, which will ensure that authenticated requests get read-write access, and unauthenticated requests get read-only access.\n\n\nFirst add the following import in the views module\n\n\nfrom rest_framework import permissions\n\n\n\nThen, add the following property to \nboth\n the \nSnippetList\n and \nSnippetDetail\n view classes.\n\n\npermission_classes = (permissions.IsAuthenticatedOrReadOnly,)\n\n\n\nAdding login to the Browsable API\n\n\nIf you open a browser and navigate to the browsable API at the moment, you'll find that you're no longer able to create new code snippets.  In order to do so we'd need to be able to login as a user.\n\n\nWe can add a login view for use with the browsable API, by editing the URLconf in our project-level \nurls.py\n file.\n\n\nAdd the following import at the top of the file:\n\n\nfrom django.conf.urls import include\n\n\n\nAnd, at the end of the file, add a pattern to include the login and logout views for the browsable API.\n\n\nurlpatterns += [\n    path('api-auth/', include('rest_framework.urls')),\n]\n\n\n\nThe \n'api-auth/'\n part of pattern can actually be whatever URL you want to use.\n\n\nNow if you open up the browser again and refresh the page you'll see a 'Login' link in the top right of the page.  If you log in as one of the users you created earlier, you'll be able to create code snippets again.\n\n\nOnce you've created a few code snippets, navigate to the '/users/' endpoint, and notice that the representation includes a list of the snippet ids that are associated with each user, in each user's 'snippets' field.\n\n\nObject level permissions\n\n\nReally we'd like all code snippets to be visible to anyone, but also make sure that only the user that created a code snippet is able to update or delete it.\n\n\nTo do that we're going to need to create a custom permission.\n\n\nIn the snippets app, create a new file, \npermissions.py\n\n\nfrom rest_framework import permissions\n\n\nclass IsOwnerOrReadOnly(permissions.BasePermission):\n    \"\"\"\n    Custom permission to only allow owners of an object to edit it.\n    \"\"\"\n\n    def has_object_permission(self, request, view, obj):\n        # Read permissions are allowed to any request,\n        # so we'll always allow GET, HEAD or OPTIONS requests.\n        if request.method in permissions.SAFE_METHODS:\n            return True\n\n        # Write permissions are only allowed to the owner of the snippet.\n        return obj.owner == request.user\n\n\n\nNow we can add that custom permission to our snippet instance endpoint, by editing the \npermission_classes\n property on the \nSnippetDetail\n view class:\n\n\npermission_classes = (permissions.IsAuthenticatedOrReadOnly,\n                      IsOwnerOrReadOnly,)\n\n\n\nMake sure to also import the \nIsOwnerOrReadOnly\n class.\n\n\nfrom snippets.permissions import IsOwnerOrReadOnly\n\n\n\nNow, if you open a browser again, you find that the 'DELETE' and 'PUT' actions only appear on a snippet instance endpoint if you're logged in as the same user that created the code snippet.\n\n\nAuthenticating with the API\n\n\nBecause we now have a set of permissions on the API, we need to authenticate our requests to it if we want to edit any snippets.  We haven't set up any \nauthentication classes\n, so the defaults are currently applied, which are \nSessionAuthentication\n and \nBasicAuthentication\n.\n\n\nWhen we interact with the API through the web browser, we can login, and the browser session will then provide the required authentication for the requests.\n\n\nIf we're interacting with the API programmatically we need to explicitly provide the authentication credentials on each request.\n\n\nIf we try to create a snippet without authenticating, we'll get an error:\n\n\nhttp POST http://127.0.0.1:8000/snippets/ code=\"print(123)\"\n\n{\n    \"detail\": \"Authentication credentials were not provided.\"\n}\n\n\n\nWe can make a successful request by including the username and password of one of the users we created earlier.\n\n\nhttp -a admin:password123 POST http://127.0.0.1:8000/snippets/ code=\"print(789)\"\n\n{\n    \"id\": 1,\n    \"owner\": \"admin\",\n    \"title\": \"foo\",\n    \"code\": \"print(789)\",\n    \"linenos\": false,\n    \"language\": \"python\",\n    \"style\": \"friendly\"\n}\n\n\n\nSummary\n\n\nWe've now got a fairly fine-grained set of permissions on our Web API, and end points for users of the system and for the code snippets that they have created.\n\n\nIn \npart 5\n of the tutorial we'll look at how we can tie everything together by creating an HTML endpoint for our highlighted snippets, and improve the cohesion of our API by using hyperlinking for the relationships within the system.",
                 "title": "4 - Authentication and permissions"
             },
             {
    @@ -282,7 +282,7 @@
             },
             {
                 "location": "/tutorial/4-authentication-and-permissions/#authenticating-with-the-api",
    -            "text": "Because we now have a set of permissions on the API, we need to authenticate our requests to it if we want to edit any snippets.  We haven't set up any  authentication classes , so the defaults are currently applied, which are  SessionAuthentication  and  BasicAuthentication .  When we interact with the API through the web browser, we can login, and the browser session will then provide the required authentication for the requests.  If we're interacting with the API programmatically we need to explicitly provide the authentication credentials on each request.  If we try to create a snippet without authenticating, we'll get an error:  http POST http://127.0.0.1:8000/snippets/ code=\"print 123\"\n\n{\n    \"detail\": \"Authentication credentials were not provided.\"\n}  We can make a successful request by including the username and password of one of the users we created earlier.  http -a admin:password123 POST http://127.0.0.1:8000/snippets/ code=\"print 789\"\n\n{\n    \"id\": 1,\n    \"owner\": \"admin\",\n    \"title\": \"foo\",\n    \"code\": \"print 789\",\n    \"linenos\": false,\n    \"language\": \"python\",\n    \"style\": \"friendly\"\n}",
    +            "text": "Because we now have a set of permissions on the API, we need to authenticate our requests to it if we want to edit any snippets.  We haven't set up any  authentication classes , so the defaults are currently applied, which are  SessionAuthentication  and  BasicAuthentication .  When we interact with the API through the web browser, we can login, and the browser session will then provide the required authentication for the requests.  If we're interacting with the API programmatically we need to explicitly provide the authentication credentials on each request.  If we try to create a snippet without authenticating, we'll get an error:  http POST http://127.0.0.1:8000/snippets/ code=\"print(123)\"\n\n{\n    \"detail\": \"Authentication credentials were not provided.\"\n}  We can make a successful request by including the username and password of one of the users we created earlier.  http -a admin:password123 POST http://127.0.0.1:8000/snippets/ code=\"print(789)\"\n\n{\n    \"id\": 1,\n    \"owner\": \"admin\",\n    \"title\": \"foo\",\n    \"code\": \"print(789)\",\n    \"linenos\": false,\n    \"language\": \"python\",\n    \"style\": \"friendly\"\n}",
                 "title": "Authenticating with the API"
             },
             {
    @@ -1047,7 +1047,7 @@
             },
             {
                 "location": "/api-guide/parsers/",
    -            "text": "Parsers\n\n\n\n\nMachine interacting web services tend to use more\nstructured formats for sending data than form-encoded, since they're\nsending more complex data than simple forms\n\n\n\u2014 Malcom Tredinnick, \nDjango developers group\n\n\n\n\nREST framework includes a number of built in Parser classes, that allow you to accept requests with various media types.  There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts.\n\n\nHow the parser is determined\n\n\nThe set of valid parsers for a view is always defined as a list of classes.  When  \nrequest.data\n is accessed, REST framework will examine the \nContent-Type\n header on the incoming request, and determine which parser to use to parse the request content.\n\n\n\n\nNote\n: When developing client applications always remember to make sure you're setting the \nContent-Type\n header when sending data in an HTTP request.\n\n\nIf you don't set the content type, most clients will default to using \n'application/x-www-form-urlencoded'\n, which may not be what you wanted.\n\n\nAs an example, if you are sending \njson\n encoded data using jQuery with the \n.ajax() method\n, you should make sure to include the \ncontentType: 'application/json'\n setting.\n\n\n\n\nSetting the parsers\n\n\nThe default set of parsers may be set globally, using the \nDEFAULT_PARSER_CLASSES\n setting. For example, the following settings would allow only requests with \nJSON\n content, instead of the default of JSON or form data.\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_PARSER_CLASSES': (\n        'rest_framework.parsers.JSONParser',\n    )\n}\n\n\n\nYou can also set the parsers used for an individual view, or viewset,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.parsers import JSONParser\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n    \"\"\"\n    A view that can accept POST requests with JSON content.\n    \"\"\"\n    parser_classes = (JSONParser,)\n\n    def post(self, request, format=None):\n        return Response({'received data': request.data})\n\n\n\nOr, if you're using the \n@api_view\n decorator with function based views.\n\n\nfrom rest_framework.decorators import api_view\nfrom rest_framework.decorators import parser_classes\nfrom rest_framework.parsers import JSONParser\n\n@api_view(['POST'])\n@parser_classes((JSONParser,))\ndef example_view(request, format=None):\n    \"\"\"\n    A view that can accept POST requests with JSON content.\n    \"\"\"\n    return Response({'received data': request.data})\n\n\n\n\n\nAPI Reference\n\n\nJSONParser\n\n\nParses \nJSON\n request content.\n\n\n.media_type\n: \napplication/json\n\n\nFormParser\n\n\nParses HTML form content.  \nrequest.data\n will be populated with a \nQueryDict\n of data.\n\n\nYou will typically want to use both \nFormParser\n and \nMultiPartParser\n together in order to fully support HTML form data.\n\n\n.media_type\n: \napplication/x-www-form-urlencoded\n\n\nMultiPartParser\n\n\nParses multipart HTML form content, which supports file uploads.  Both \nrequest.data\n will be populated with a \nQueryDict\n.\n\n\nYou will typically want to use both \nFormParser\n and \nMultiPartParser\n together in order to fully support HTML form data.\n\n\n.media_type\n: \nmultipart/form-data\n\n\nFileUploadParser\n\n\nParses raw file upload content.  The \nrequest.data\n property will be a dictionary with a single key \n'file'\n containing the uploaded file.\n\n\nIf the view used with \nFileUploadParser\n is called with a \nfilename\n URL keyword argument, then that argument will be used as the filename.\n\n\nIf it is called without a \nfilename\n URL keyword argument, then the client must set the filename in the \nContent-Disposition\n HTTP header.  For example \nContent-Disposition: attachment; filename=upload.jpg\n.\n\n\n.media_type\n: \n*/*\n\n\nNotes:\n\n\n\n\nThe \nFileUploadParser\n is for usage with native clients that can upload the file as a raw data request.  For web-based uploads, or for native clients with multipart upload support, you should use the \nMultiPartParser\n parser instead.\n\n\nSince this parser's \nmedia_type\n matches any content type, \nFileUploadParser\n should generally be the only parser set on an API view.\n\n\nFileUploadParser\n respects Django's standard \nFILE_UPLOAD_HANDLERS\n setting, and the \nrequest.upload_handlers\n attribute.  See the \nDjango documentation\n for more details.\n\n\n\n\nBasic usage example:\n\n\n# views.py\nclass FileUploadView(views.APIView):\n    parser_classes = (FileUploadParser,)\n\n    def put(self, request, filename, format=None):\n        file_obj = request.data['file']\n        # ...\n        # do some stuff with uploaded file\n        # ...\n        return Response(status=204)\n\n# urls.py\nurlpatterns = [\n    # ...\n    url(r'^upload/(?P[^/]+)$', FileUploadView.as_view())\n]\n\n\n\n\n\nCustom parsers\n\n\nTo implement a custom parser, you should override \nBaseParser\n, set the \n.media_type\n property, and implement the \n.parse(self, stream, media_type, parser_context)\n method.\n\n\nThe method should return the data that will be used to populate the \nrequest.data\n property.\n\n\nThe arguments passed to \n.parse()\n are:\n\n\nstream\n\n\nA stream-like object representing the body of the request.\n\n\nmedia_type\n\n\nOptional.  If provided, this is the media type of the incoming request content.\n\n\nDepending on the request's \nContent-Type:\n header, this may be more specific than the renderer's \nmedia_type\n attribute, and may include media type parameters.  For example \n\"text/plain; charset=utf-8\"\n.\n\n\nparser_context\n\n\nOptional.  If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content.\n\n\nBy default this will include the following keys: \nview\n, \nrequest\n, \nargs\n, \nkwargs\n.\n\n\nExample\n\n\nThe following is an example plaintext parser that will populate the \nrequest.data\n property with a string representing the body of the request.\n\n\nclass PlainTextParser(BaseParser):\n    \"\"\"\n    Plain text parser.\n    \"\"\"\n    media_type = 'text/plain'\n\n    def parse(self, stream, media_type=None, parser_context=None):\n        \"\"\"\n        Simply return a string representing the body of the request.\n        \"\"\"\n        return stream.read()\n\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nYAML\n\n\nREST framework YAML\n provides \nYAML\n parsing and rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-yaml\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_PARSER_CLASSES': (\n        'rest_framework_yaml.parsers.YAMLParser',\n    ),\n    'DEFAULT_RENDERER_CLASSES': (\n        'rest_framework_yaml.renderers.YAMLRenderer',\n    ),\n}\n\n\n\nXML\n\n\nREST Framework XML\n 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.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-xml\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_PARSER_CLASSES': (\n        'rest_framework_xml.parsers.XMLParser',\n    ),\n    'DEFAULT_RENDERER_CLASSES': (\n        'rest_framework_xml.renderers.XMLRenderer',\n    ),\n}\n\n\n\nMessagePack\n\n\nMessagePack\n is a fast, efficient binary serialization format.  \nJuan Riaza\n maintains the \ndjangorestframework-msgpack\n package which provides MessagePack renderer and parser support for REST framework.\n\n\nCamelCase JSON\n\n\ndjangorestframework-camel-case\n provides camel case JSON renderers and parsers for REST framework.  This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names.  It is maintained by \nVitaly Babiy\n.",
    +            "text": "Parsers\n\n\n\n\nMachine interacting web services tend to use more\nstructured formats for sending data than form-encoded, since they're\nsending more complex data than simple forms\n\n\n\u2014 Malcom Tredinnick, \nDjango developers group\n\n\n\n\nREST framework includes a number of built in Parser classes, that allow you to accept requests with various media types.  There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts.\n\n\nHow the parser is determined\n\n\nThe set of valid parsers for a view is always defined as a list of classes.  When  \nrequest.data\n is accessed, REST framework will examine the \nContent-Type\n header on the incoming request, and determine which parser to use to parse the request content.\n\n\n\n\nNote\n: When developing client applications always remember to make sure you're setting the \nContent-Type\n header when sending data in an HTTP request.\n\n\nIf you don't set the content type, most clients will default to using \n'application/x-www-form-urlencoded'\n, which may not be what you wanted.\n\n\nAs an example, if you are sending \njson\n encoded data using jQuery with the \n.ajax() method\n, you should make sure to include the \ncontentType: 'application/json'\n setting.\n\n\n\n\nSetting the parsers\n\n\nThe default set of parsers may be set globally, using the \nDEFAULT_PARSER_CLASSES\n setting. For example, the following settings would allow only requests with \nJSON\n content, instead of the default of JSON or form data.\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_PARSER_CLASSES': (\n        'rest_framework.parsers.JSONParser',\n    )\n}\n\n\n\nYou can also set the parsers used for an individual view, or viewset,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.parsers import JSONParser\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n    \"\"\"\n    A view that can accept POST requests with JSON content.\n    \"\"\"\n    parser_classes = (JSONParser,)\n\n    def post(self, request, format=None):\n        return Response({'received data': request.data})\n\n\n\nOr, if you're using the \n@api_view\n decorator with function based views.\n\n\nfrom rest_framework.decorators import api_view\nfrom rest_framework.decorators import parser_classes\nfrom rest_framework.parsers import JSONParser\n\n@api_view(['POST'])\n@parser_classes((JSONParser,))\ndef example_view(request, format=None):\n    \"\"\"\n    A view that can accept POST requests with JSON content.\n    \"\"\"\n    return Response({'received data': request.data})\n\n\n\n\n\nAPI Reference\n\n\nJSONParser\n\n\nParses \nJSON\n request content.\n\n\n.media_type\n: \napplication/json\n\n\nFormParser\n\n\nParses HTML form content.  \nrequest.data\n will be populated with a \nQueryDict\n of data.\n\n\nYou will typically want to use both \nFormParser\n and \nMultiPartParser\n together in order to fully support HTML form data.\n\n\n.media_type\n: \napplication/x-www-form-urlencoded\n\n\nMultiPartParser\n\n\nParses multipart HTML form content, which supports file uploads.  Both \nrequest.data\n will be populated with a \nQueryDict\n.\n\n\nYou will typically want to use both \nFormParser\n and \nMultiPartParser\n together in order to fully support HTML form data.\n\n\n.media_type\n: \nmultipart/form-data\n\n\nFileUploadParser\n\n\nParses raw file upload content.  The \nrequest.data\n property will be a dictionary with a single key \n'file'\n containing the uploaded file.\n\n\nIf the view used with \nFileUploadParser\n is called with a \nfilename\n URL keyword argument, then that argument will be used as the filename.\n\n\nIf it is called without a \nfilename\n URL keyword argument, then the client must set the filename in the \nContent-Disposition\n HTTP header.  For example \nContent-Disposition: attachment; filename=upload.jpg\n.\n\n\n.media_type\n: \n*/*\n\n\nNotes:\n\n\n\n\nThe \nFileUploadParser\n is for usage with native clients that can upload the file as a raw data request.  For web-based uploads, or for native clients with multipart upload support, you should use the \nMultiPartParser\n instead.\n\n\nSince this parser's \nmedia_type\n matches any content type, \nFileUploadParser\n should generally be the only parser set on an API view.\n\n\nFileUploadParser\n respects Django's standard \nFILE_UPLOAD_HANDLERS\n setting, and the \nrequest.upload_handlers\n attribute.  See the \nDjango documentation\n for more details.\n\n\n\n\nBasic usage example:\n\n\n# views.py\nclass FileUploadView(views.APIView):\n    parser_classes = (FileUploadParser,)\n\n    def put(self, request, filename, format=None):\n        file_obj = request.data['file']\n        # ...\n        # do some stuff with uploaded file\n        # ...\n        return Response(status=204)\n\n# urls.py\nurlpatterns = [\n    # ...\n    url(r'^upload/(?P[^/]+)$', FileUploadView.as_view())\n]\n\n\n\n\n\nCustom parsers\n\n\nTo implement a custom parser, you should override \nBaseParser\n, set the \n.media_type\n property, and implement the \n.parse(self, stream, media_type, parser_context)\n method.\n\n\nThe method should return the data that will be used to populate the \nrequest.data\n property.\n\n\nThe arguments passed to \n.parse()\n are:\n\n\nstream\n\n\nA stream-like object representing the body of the request.\n\n\nmedia_type\n\n\nOptional.  If provided, this is the media type of the incoming request content.\n\n\nDepending on the request's \nContent-Type:\n header, this may be more specific than the renderer's \nmedia_type\n attribute, and may include media type parameters.  For example \n\"text/plain; charset=utf-8\"\n.\n\n\nparser_context\n\n\nOptional.  If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content.\n\n\nBy default this will include the following keys: \nview\n, \nrequest\n, \nargs\n, \nkwargs\n.\n\n\nExample\n\n\nThe following is an example plaintext parser that will populate the \nrequest.data\n property with a string representing the body of the request.\n\n\nclass PlainTextParser(BaseParser):\n    \"\"\"\n    Plain text parser.\n    \"\"\"\n    media_type = 'text/plain'\n\n    def parse(self, stream, media_type=None, parser_context=None):\n        \"\"\"\n        Simply return a string representing the body of the request.\n        \"\"\"\n        return stream.read()\n\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nYAML\n\n\nREST framework YAML\n provides \nYAML\n parsing and rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-yaml\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_PARSER_CLASSES': (\n        'rest_framework_yaml.parsers.YAMLParser',\n    ),\n    'DEFAULT_RENDERER_CLASSES': (\n        'rest_framework_yaml.renderers.YAMLRenderer',\n    ),\n}\n\n\n\nXML\n\n\nREST Framework XML\n 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.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-xml\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_PARSER_CLASSES': (\n        'rest_framework_xml.parsers.XMLParser',\n    ),\n    'DEFAULT_RENDERER_CLASSES': (\n        'rest_framework_xml.renderers.XMLRenderer',\n    ),\n}\n\n\n\nMessagePack\n\n\nMessagePack\n is a fast, efficient binary serialization format.  \nJuan Riaza\n maintains the \ndjangorestframework-msgpack\n package which provides MessagePack renderer and parser support for REST framework.\n\n\nCamelCase JSON\n\n\ndjangorestframework-camel-case\n provides camel case JSON renderers and parsers for REST framework.  This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names.  It is maintained by \nVitaly Babiy\n.",
                 "title": "Parsers"
             },
             {
    @@ -1092,7 +1092,7 @@
             },
             {
                 "location": "/api-guide/parsers/#notes",
    -            "text": "The  FileUploadParser  is for usage with native clients that can upload the file as a raw data request.  For web-based uploads, or for native clients with multipart upload support, you should use the  MultiPartParser  parser instead.  Since this parser's  media_type  matches any content type,  FileUploadParser  should generally be the only parser set on an API view.  FileUploadParser  respects Django's standard  FILE_UPLOAD_HANDLERS  setting, and the  request.upload_handlers  attribute.  See the  Django documentation  for more details.",
    +            "text": "The  FileUploadParser  is for usage with native clients that can upload the file as a raw data request.  For web-based uploads, or for native clients with multipart upload support, you should use the  MultiPartParser  instead.  Since this parser's  media_type  matches any content type,  FileUploadParser  should generally be the only parser set on an API view.  FileUploadParser  respects Django's standard  FILE_UPLOAD_HANDLERS  setting, and the  request.upload_handlers  attribute.  See the  Django documentation  for more details.",
                 "title": "Notes:"
             },
             {
    @@ -1162,7 +1162,7 @@
             },
             {
                 "location": "/api-guide/renderers/",
    -            "text": "Renderers\n\n\n\n\nBefore a TemplateResponse instance can be returned to the client, it must be rendered. The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client.\n\n\n\u2014 \nDjango documentation\n\n\n\n\nREST framework includes a number of built in Renderer classes, that allow you to return responses with various media types.  There is also support for defining your own custom renderers, which gives you the flexibility to design your own media types.\n\n\nHow the renderer is determined\n\n\nThe set of valid renderers for a view is always defined as a list of classes.  When a view is entered REST framework will perform content negotiation on the incoming request, and determine the most appropriate renderer to satisfy the request.\n\n\nThe basic process of content negotiation involves examining the request's \nAccept\n 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 \nhttp://example.com/api/users_count.json\n might be an endpoint that always returns JSON data.\n\n\nFor more information see the documentation on \ncontent negotiation\n.\n\n\nSetting the renderers\n\n\nThe default set of renderers may be set globally, using the \nDEFAULT_RENDERER_CLASSES\n setting.  For example, the following settings would use \nJSON\n as the main media type and also include the self describing API.\n\n\nREST_FRAMEWORK = {\n    'DEFAULT_RENDERER_CLASSES': (\n        'rest_framework.renderers.JSONRenderer',\n        'rest_framework.renderers.BrowsableAPIRenderer',\n    )\n}\n\n\n\nYou can also set the renderers used for an individual view, or viewset,\nusing the \nAPIView\n class-based views.\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework.renderers import JSONRenderer\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass UserCountView(APIView):\n    \"\"\"\n    A view that returns the count of active users in JSON.\n    \"\"\"\n    renderer_classes = (JSONRenderer, )\n\n    def get(self, request, format=None):\n        user_count = User.objects.filter(active=True).count()\n        content = {'user_count': user_count}\n        return Response(content)\n\n\n\nOr, if you're using the \n@api_view\n decorator with function based views.\n\n\n@api_view(['GET'])\n@renderer_classes((JSONRenderer,))\ndef user_count_view(request, format=None):\n    \"\"\"\n    A view that returns the count of active users in JSON.\n    \"\"\"\n    user_count = User.objects.filter(active=True).count()\n    content = {'user_count': user_count}\n    return Response(content)\n\n\n\nOrdering of renderer classes\n\n\nIt's important when specifying the renderer classes for your API to think about what priority you want to assign to each media type.  If a client underspecifies the representations it can accept, such as sending an \nAccept: */*\n header, or not including an \nAccept\n header at all, then REST framework will select the first renderer in the list to use for the response.\n\n\nFor example if your API serves JSON responses and the HTML browsable API, you might want to make \nJSONRenderer\n your default renderer, in order to send \nJSON\n responses to clients that do not specify an \nAccept\n header.\n\n\nIf your API includes views that can serve both regular webpages and API responses depending on the request, then you might consider making \nTemplateHTMLRenderer\n your default renderer, in order to play nicely with older browsers that send \nbroken accept headers\n.\n\n\n\n\nAPI Reference\n\n\nJSONRenderer\n\n\nRenders the request data into \nJSON\n, using utf-8 encoding.\n\n\nNote that the default style is to include unicode characters, and render the response using a compact style with no unnecessary whitespace:\n\n\n{\"unicode black star\":\"\u2605\",\"value\":999}\n\n\n\nThe client may additionally include an \n'indent'\n media type parameter, in which case the returned \nJSON\n will be indented.  For example \nAccept: application/json; indent=4\n.\n\n\n{\n    \"unicode black star\": \"\u2605\",\n    \"value\": 999\n}\n\n\n\nThe default JSON encoding style can be altered using the \nUNICODE_JSON\n and \nCOMPACT_JSON\n settings keys.\n\n\n.media_type\n: \napplication/json\n\n\n.format\n: \n'.json'\n\n\n.charset\n: \nNone\n\n\nTemplateHTMLRenderer\n\n\nRenders data to HTML, using Django's standard template rendering.\nUnlike other renderers, the data passed to the \nResponse\n does not need to be serialized.  Also, unlike other renderers, you may want to include a \ntemplate_name\n argument when creating the \nResponse\n.\n\n\nThe TemplateHTMLRenderer will create a \nRequestContext\n, using the \nresponse.data\n as the context dict, and determine a template name to use to render the context.\n\n\nThe template name is determined by (in order of preference):\n\n\n\n\nAn explicit \ntemplate_name\n argument passed to the response.\n\n\nAn explicit \n.template_name\n attribute set on this class.\n\n\nThe return result of calling \nview.get_template_names()\n.\n\n\n\n\nAn example of a view that uses \nTemplateHTMLRenderer\n:\n\n\nclass UserDetail(generics.RetrieveAPIView):\n    \"\"\"\n    A view that returns a templated HTML representation of a given user.\n    \"\"\"\n    queryset = User.objects.all()\n    renderer_classes = (TemplateHTMLRenderer,)\n\n    def get(self, request, *args, **kwargs):\n        self.object = self.get_object()\n        return Response({'user': self.object}, template_name='user_detail.html')\n\n\n\nYou can use \nTemplateHTMLRenderer\n either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.\n\n\nIf you're building websites that use \nTemplateHTMLRenderer\n along with other renderer classes, you should consider listing \nTemplateHTMLRenderer\n as the first class in the \nrenderer_classes\n list, so that it will be prioritised first even for browsers that send poorly formed \nACCEPT:\n headers.\n\n\nSee the \nHTML & Forms\n Topic Page\n for further examples of \nTemplateHTMLRenderer\n usage.\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'.html'\n\n\n.charset\n: \nutf-8\n\n\nSee also: \nStaticHTMLRenderer\n\n\nStaticHTMLRenderer\n\n\nA simple renderer that simply returns pre-rendered HTML.  Unlike other renderers, the data passed to the response object should be a string representing the content to be returned.\n\n\nAn example of a view that uses \nStaticHTMLRenderer\n:\n\n\n@api_view(('GET',))\n@renderer_classes((StaticHTMLRenderer,))\ndef simple_html_view(request):\n    data = '

    Hello, world

    '\n return Response(data)\n\n\n\nYou can use \nStaticHTMLRenderer\n either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'.html'\n\n\n.charset\n: \nutf-8\n\n\nSee also: \nTemplateHTMLRenderer\n\n\nBrowsableAPIRenderer\n\n\nRenders data into HTML for the Browsable API:\n\n\n\n\nThis renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page.\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'.api'\n\n\n.charset\n: \nutf-8\n\n\n.template\n: \n'rest_framework/api.html'\n\n\nCustomizing BrowsableAPIRenderer\n\n\nBy default the response content will be rendered with the highest priority renderer apart from \nBrowsableAPIRenderer\n. If you need to customize this behavior, for example to use HTML as the default return format, but use JSON in the browsable API, you can do so by overriding the \nget_default_renderer()\n method. For example:\n\n\nclass CustomBrowsableAPIRenderer(BrowsableAPIRenderer):\n def get_default_renderer(self, view):\n return JSONRenderer()\n\n\n\nAdminRenderer\n\n\nRenders data into HTML for an admin-like display:\n\n\n\n\nThis renderer is suitable for CRUD-style web APIs that should also present a user-friendly interface for managing the data.\n\n\nNote that views that have nested or list serializers for their input won't work well with the \nAdminRenderer\n, as the HTML forms are unable to properly support them.\n\n\nNote\n: The \nAdminRenderer\n is only able to include links to detail pages when a properly configured \nURL_FIELD_NAME\n (\nurl\n by default) attribute is present in the data. For \nHyperlinkedModelSerializer\n this will be the case, but for \nModelSerializer\n or plain \nSerializer\n classes you'll need to make sure to include the field explicitly. For example here we use models \nget_absolute_url\n method:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n url = serializers.CharField(source='get_absolute_url', read_only=True)\n\n class Meta:\n model = Account\n\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'.admin'\n\n\n.charset\n: \nutf-8\n\n\n.template\n: \n'rest_framework/admin.html'\n\n\nHTMLFormRenderer\n\n\nRenders data returned by a serializer into an HTML form. The output of this renderer does not include the enclosing \n
    \n tags, a hidden CSRF input or any submit buttons.\n\n\nThis renderer is not intended to be used directly, but can instead be used in templates by passing a serializer instance to the \nrender_form\n template tag.\n\n\n{% load rest_framework %}\n\n\n {% csrf_token %}\n {% render_form serializer %}\n \n
    \n\n\n\nFor more information see the \nHTML & Forms\n documentation.\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'.form'\n\n\n.charset\n: \nutf-8\n\n\n.template\n: \n'rest_framework/horizontal/form.html'\n\n\nMultiPartRenderer\n\n\nThis renderer is used for rendering HTML multipart form data. \nIt is not suitable as a response renderer\n, but is instead used for creating test requests, using REST framework's \ntest client and test request factory\n.\n\n\n.media_type\n: \nmultipart/form-data; boundary=BoUnDaRyStRiNg\n\n\n.format\n: \n'.multipart'\n\n\n.charset\n: \nutf-8\n\n\n\n\nCustom renderers\n\n\nTo implement a custom renderer, you should override \nBaseRenderer\n, set the \n.media_type\n and \n.format\n properties, and implement the \n.render(self, data, media_type=None, renderer_context=None)\n method.\n\n\nThe method should return a bytestring, which will be used as the body of the HTTP response.\n\n\nThe arguments passed to the \n.render()\n method are:\n\n\ndata\n\n\nThe request data, as set by the \nResponse()\n instantiation.\n\n\nmedia_type=None\n\n\nOptional. If provided, this is the accepted media type, as determined by the content negotiation stage.\n\n\nDepending on the client's \nAccept:\n header, this may be more specific than the renderer's \nmedia_type\n attribute, and may include media type parameters. For example \n\"application/json; nested=true\"\n.\n\n\nrenderer_context=None\n\n\nOptional. If provided, this is a dictionary of contextual information provided by the view.\n\n\nBy default this will include the following keys: \nview\n, \nrequest\n, \nresponse\n, \nargs\n, \nkwargs\n.\n\n\nExample\n\n\nThe following is an example plaintext renderer that will return a response with the \ndata\n parameter as the content of the response.\n\n\nfrom django.utils.encoding import smart_unicode\nfrom rest_framework import renderers\n\n\nclass PlainTextRenderer(renderers.BaseRenderer):\n media_type = 'text/plain'\n format = 'txt'\n\n def render(self, data, media_type=None, renderer_context=None):\n return data.encode(self.charset)\n\n\n\nSetting the character set\n\n\nBy default renderer classes are assumed to be using the \nUTF-8\n encoding. To use a different encoding, set the \ncharset\n attribute on the renderer.\n\n\nclass PlainTextRenderer(renderers.BaseRenderer):\n media_type = 'text/plain'\n format = 'txt'\n charset = 'iso-8859-1'\n\n def render(self, data, media_type=None, renderer_context=None):\n return data.encode(self.charset)\n\n\n\nNote that if a renderer class returns a unicode string, then the response content will be coerced into a bytestring by the \nResponse\n class, with the \ncharset\n attribute set on the renderer used to determine the encoding.\n\n\nIf the renderer returns a bytestring representing raw binary content, you should set a charset value of \nNone\n, which will ensure the \nContent-Type\n header of the response will not have a \ncharset\n value set.\n\n\nIn some cases you may also want to set the \nrender_style\n attribute to \n'binary'\n. Doing so will also ensure that the browsable API will not attempt to display the binary content as a string.\n\n\nclass JPEGRenderer(renderers.BaseRenderer):\n media_type = 'image/jpeg'\n format = 'jpg'\n charset = None\n render_style = 'binary'\n\n def render(self, data, media_type=None, renderer_context=None):\n return data\n\n\n\n\n\nAdvanced renderer usage\n\n\nYou can do some pretty flexible things using REST framework's renderers. Some examples...\n\n\n\n\nProvide either flat or nested representations from the same endpoint, depending on the requested media type.\n\n\nServe both regular HTML webpages, and JSON based API responses from the same endpoints.\n\n\nSpecify multiple types of HTML representation for API clients to use.\n\n\nUnderspecify a renderer's media type, such as using \nmedia_type = 'image/*'\n, and use the \nAccept\n header to vary the encoding of the response.\n\n\n\n\nVarying behaviour by media type\n\n\nIn some cases you might want your view to use different serialization styles depending on the accepted media type. If you need to do this you can access \nrequest.accepted_renderer\n to determine the negotiated renderer that will be used for the response.\n\n\nFor example:\n\n\n@api_view(('GET',))\n@renderer_classes((TemplateHTMLRenderer, JSONRenderer))\ndef list_users(request):\n \"\"\"\n A view that can return JSON or HTML representations\n of the users in the system.\n \"\"\"\n queryset = Users.objects.filter(active=True)\n\n if request.accepted_renderer.format == 'html':\n # TemplateHTMLRenderer takes a context dict,\n # and additionally requires a 'template_name'.\n # It does not require serialization.\n data = {'users': queryset}\n return Response(data, template_name='list_users.html')\n\n # JSONRenderer requires serialized data as normal.\n serializer = UserSerializer(instance=queryset)\n data = serializer.data\n return Response(data)\n\n\n\nUnderspecifying the media type\n\n\nIn some cases you might want a renderer to serve a range of media types.\nIn this case you can underspecify the media types it should respond to, by using a \nmedia_type\n value such as \nimage/*\n, or \n*/*\n.\n\n\nIf you underspecify the renderer's media type, you should make sure to specify the media type explicitly when you return the response, using the \ncontent_type\n attribute. For example:\n\n\nreturn Response(data, content_type='image/png')\n\n\n\nDesigning your media types\n\n\nFor the purposes of many Web APIs, simple \nJSON\n responses with hyperlinked relations may be sufficient. If you want to fully embrace RESTful design and \nHATEOAS\n you'll need to consider the design and usage of your media types in more detail.\n\n\nIn \nthe words of Roy Fielding\n, \"A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types.\".\n\n\nFor good examples of custom media types, see GitHub's use of a custom \napplication/vnd.github+json\n media type, and Mike Amundsen's IANA approved \napplication/vnd.collection+json\n JSON-based hypermedia.\n\n\nHTML error views\n\n\nTypically a renderer will behave the same regardless of if it's dealing with a regular response, or with a response caused by an exception being raised, such as an \nHttp404\n or \nPermissionDenied\n exception, or a subclass of \nAPIException\n.\n\n\nIf you're using either the \nTemplateHTMLRenderer\n or the \nStaticHTMLRenderer\n and an exception is raised, the behavior is slightly different, and mirrors \nDjango's default handling of error views\n.\n\n\nExceptions raised and handled by an HTML renderer will attempt to render using one of the following methods, by order of precedence.\n\n\n\n\nLoad and render a template named \n{status_code}.html\n.\n\n\nLoad and render a template named \napi_exception.html\n.\n\n\nRender the HTTP status code and text, for example \"404 Not Found\".\n\n\n\n\nTemplates will render with a \nRequestContext\n which includes the \nstatus_code\n and \ndetails\n keys.\n\n\nNote\n: If \nDEBUG=True\n, Django's standard traceback error page will be displayed instead of rendering the HTTP status code and text.\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nYAML\n\n\nREST framework YAML\n provides \nYAML\n parsing and rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-yaml\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PARSER_CLASSES': (\n 'rest_framework_yaml.parsers.YAMLParser',\n ),\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework_yaml.renderers.YAMLRenderer',\n ),\n}\n\n\n\nXML\n\n\nREST Framework XML\n 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.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-xml\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PARSER_CLASSES': (\n 'rest_framework_xml.parsers.XMLParser',\n ),\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework_xml.renderers.XMLRenderer',\n ),\n}\n\n\n\nJSONP\n\n\nREST framework JSONP\n provides JSONP rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.\n\n\n\n\nWarning\n: If you require cross-domain AJAX requests, you should generally be using the more modern approach of \nCORS\n as an alternative to \nJSONP\n. See the \nCORS documentation\n for more details.\n\n\nThe \njsonp\n approach is essentially a browser hack, and is \nonly appropriate for globally readable API endpoints\n, where \nGET\n requests are unauthenticated and do not require any user permissions.\n\n\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-jsonp\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework_jsonp.renderers.JSONPRenderer',\n ),\n}\n\n\n\nMessagePack\n\n\nMessagePack\n is a fast, efficient binary serialization format. \nJuan Riaza\n maintains the \ndjangorestframework-msgpack\n package which provides MessagePack renderer and parser support for REST framework.\n\n\nXLSX (Binary Spreadsheet Endpoints)\n\n\nXLSX is the world's most popular binary spreadsheet format. \nTim Allen\n of \nThe Wharton School\n maintains \ndrf-renderer-xlsx\n, which renders an endpoint as an XLSX spreadsheet using OpenPyXL, and allows the client to download it. Spreadsheets can be styled on a per-view basis.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install drf-renderer-xlsx\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n ...\n\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n 'drf_renderer_xlsx.renderers.XLSXRenderer',\n ),\n}\n\n\n\nTo avoid having a file streamed without a filename (which the browser will often default to the filename \"download\", with no extension), we need to use a mixin to override the \nContent-Disposition\n header. If no filename is provided, it will default to \nexport.xlsx\n. For example:\n\n\nfrom rest_framework.viewsets import ReadOnlyModelViewSet\nfrom drf_renderer_xlsx.mixins import XLSXFileMixin\nfrom drf_renderer_xlsx.renderers import XLSXRenderer\n\nfrom .models import MyExampleModel\nfrom .serializers import MyExampleSerializer\n\nclass MyExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):\n queryset = MyExampleModel.objects.all()\n serializer_class = MyExampleSerializer\n renderer_classes = (XLSXRenderer,)\n filename = 'my_export.xlsx'\n\n\n\nCSV\n\n\nComma-separated values are a plain-text tabular data format, that can be easily imported into spreadsheet applications. \nMjumbe Poe\n maintains the \ndjangorestframework-csv\n package which provides CSV renderer support for REST framework.\n\n\nUltraJSON\n\n\nUltraJSON\n is an optimized C JSON encoder which can give significantly faster JSON rendering. \nJacob Haslehurst\n maintains the \ndrf-ujson-renderer\n package which implements JSON rendering using the UJSON package.\n\n\nCamelCase JSON\n\n\ndjangorestframework-camel-case\n provides camel case JSON renderers and parsers for REST framework. This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names. It is maintained by \nVitaly Babiy\n.\n\n\nPandas (CSV, Excel, PNG)\n\n\nDjango REST Pandas\n provides a serializer and renderers that support additional data processing and output via the \nPandas\n DataFrame API. Django REST Pandas includes renderers for Pandas-style CSV files, Excel workbooks (both \n.xls\n and \n.xlsx\n), and a number of \nother formats\n. It is maintained by \nS. Andrew Sheppard\n as part of the \nwq Project\n.\n\n\nLaTeX\n\n\nRest Framework Latex\n provides a renderer that outputs PDFs using Laulatex. It is maintained by \nPebble (S/F Software)\n.", + "text": "Renderers\n\n\n\n\nBefore a TemplateResponse instance can be returned to the client, it must be rendered. The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client.\n\n\n\u2014 \nDjango documentation\n\n\n\n\nREST framework includes a number of built in Renderer classes, that allow you to return responses with various media types. There is also support for defining your own custom renderers, which gives you the flexibility to design your own media types.\n\n\nHow the renderer is determined\n\n\nThe set of valid renderers for a view is always defined as a list of classes. When a view is entered REST framework will perform content negotiation on the incoming request, and determine the most appropriate renderer to satisfy the request.\n\n\nThe basic process of content negotiation involves examining the request's \nAccept\n 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 \nhttp://example.com/api/users_count.json\n might be an endpoint that always returns JSON data.\n\n\nFor more information see the documentation on \ncontent negotiation\n.\n\n\nSetting the renderers\n\n\nThe default set of renderers may be set globally, using the \nDEFAULT_RENDERER_CLASSES\n setting. For example, the following settings would use \nJSON\n as the main media type and also include the self describing API.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n )\n}\n\n\n\nYou can also set the renderers used for an individual view, or viewset,\nusing the \nAPIView\n class-based views.\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework.renderers import JSONRenderer\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass UserCountView(APIView):\n \"\"\"\n A view that returns the count of active users in JSON.\n \"\"\"\n renderer_classes = (JSONRenderer, )\n\n def get(self, request, format=None):\n user_count = User.objects.filter(active=True).count()\n content = {'user_count': user_count}\n return Response(content)\n\n\n\nOr, if you're using the \n@api_view\n decorator with function based views.\n\n\n@api_view(['GET'])\n@renderer_classes((JSONRenderer,))\ndef user_count_view(request, format=None):\n \"\"\"\n A view that returns the count of active users in JSON.\n \"\"\"\n user_count = User.objects.filter(active=True).count()\n content = {'user_count': user_count}\n return Response(content)\n\n\n\nOrdering of renderer classes\n\n\nIt's important when specifying the renderer classes for your API to think about what priority you want to assign to each media type. If a client underspecifies the representations it can accept, such as sending an \nAccept: */*\n header, or not including an \nAccept\n header at all, then REST framework will select the first renderer in the list to use for the response.\n\n\nFor example if your API serves JSON responses and the HTML browsable API, you might want to make \nJSONRenderer\n your default renderer, in order to send \nJSON\n responses to clients that do not specify an \nAccept\n header.\n\n\nIf your API includes views that can serve both regular webpages and API responses depending on the request, then you might consider making \nTemplateHTMLRenderer\n your default renderer, in order to play nicely with older browsers that send \nbroken accept headers\n.\n\n\n\n\nAPI Reference\n\n\nJSONRenderer\n\n\nRenders the request data into \nJSON\n, using utf-8 encoding.\n\n\nNote that the default style is to include unicode characters, and render the response using a compact style with no unnecessary whitespace:\n\n\n{\"unicode black star\":\"\u2605\",\"value\":999}\n\n\n\nThe client may additionally include an \n'indent'\n media type parameter, in which case the returned \nJSON\n will be indented. For example \nAccept: application/json; indent=4\n.\n\n\n{\n \"unicode black star\": \"\u2605\",\n \"value\": 999\n}\n\n\n\nThe default JSON encoding style can be altered using the \nUNICODE_JSON\n and \nCOMPACT_JSON\n settings keys.\n\n\n.media_type\n: \napplication/json\n\n\n.format\n: \n'json'\n\n\n.charset\n: \nNone\n\n\nTemplateHTMLRenderer\n\n\nRenders data to HTML, using Django's standard template rendering.\nUnlike other renderers, the data passed to the \nResponse\n does not need to be serialized. Also, unlike other renderers, you may want to include a \ntemplate_name\n argument when creating the \nResponse\n.\n\n\nThe TemplateHTMLRenderer will create a \nRequestContext\n, using the \nresponse.data\n as the context dict, and determine a template name to use to render the context.\n\n\nThe template name is determined by (in order of preference):\n\n\n\n\nAn explicit \ntemplate_name\n argument passed to the response.\n\n\nAn explicit \n.template_name\n attribute set on this class.\n\n\nThe return result of calling \nview.get_template_names()\n.\n\n\n\n\nAn example of a view that uses \nTemplateHTMLRenderer\n:\n\n\nclass UserDetail(generics.RetrieveAPIView):\n \"\"\"\n A view that returns a templated HTML representation of a given user.\n \"\"\"\n queryset = User.objects.all()\n renderer_classes = (TemplateHTMLRenderer,)\n\n def get(self, request, *args, **kwargs):\n self.object = self.get_object()\n return Response({'user': self.object}, template_name='user_detail.html')\n\n\n\nYou can use \nTemplateHTMLRenderer\n either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.\n\n\nIf you're building websites that use \nTemplateHTMLRenderer\n along with other renderer classes, you should consider listing \nTemplateHTMLRenderer\n as the first class in the \nrenderer_classes\n list, so that it will be prioritised first even for browsers that send poorly formed \nACCEPT:\n headers.\n\n\nSee the \nHTML & Forms\n Topic Page\n for further examples of \nTemplateHTMLRenderer\n usage.\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'html'\n\n\n.charset\n: \nutf-8\n\n\nSee also: \nStaticHTMLRenderer\n\n\nStaticHTMLRenderer\n\n\nA simple renderer that simply returns pre-rendered HTML. Unlike other renderers, the data passed to the response object should be a string representing the content to be returned.\n\n\nAn example of a view that uses \nStaticHTMLRenderer\n:\n\n\n@api_view(('GET',))\n@renderer_classes((StaticHTMLRenderer,))\ndef simple_html_view(request):\n data = '

    Hello, world

    '\n return Response(data)\n\n\n\nYou can use \nStaticHTMLRenderer\n either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'html'\n\n\n.charset\n: \nutf-8\n\n\nSee also: \nTemplateHTMLRenderer\n\n\nBrowsableAPIRenderer\n\n\nRenders data into HTML for the Browsable API:\n\n\n\n\nThis renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page.\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'api'\n\n\n.charset\n: \nutf-8\n\n\n.template\n: \n'rest_framework/api.html'\n\n\nCustomizing BrowsableAPIRenderer\n\n\nBy default the response content will be rendered with the highest priority renderer apart from \nBrowsableAPIRenderer\n. If you need to customize this behavior, for example to use HTML as the default return format, but use JSON in the browsable API, you can do so by overriding the \nget_default_renderer()\n method. For example:\n\n\nclass CustomBrowsableAPIRenderer(BrowsableAPIRenderer):\n def get_default_renderer(self, view):\n return JSONRenderer()\n\n\n\nAdminRenderer\n\n\nRenders data into HTML for an admin-like display:\n\n\n\n\nThis renderer is suitable for CRUD-style web APIs that should also present a user-friendly interface for managing the data.\n\n\nNote that views that have nested or list serializers for their input won't work well with the \nAdminRenderer\n, as the HTML forms are unable to properly support them.\n\n\nNote\n: The \nAdminRenderer\n is only able to include links to detail pages when a properly configured \nURL_FIELD_NAME\n (\nurl\n by default) attribute is present in the data. For \nHyperlinkedModelSerializer\n this will be the case, but for \nModelSerializer\n or plain \nSerializer\n classes you'll need to make sure to include the field explicitly. For example here we use models \nget_absolute_url\n method:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n url = serializers.CharField(source='get_absolute_url', read_only=True)\n\n class Meta:\n model = Account\n\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'admin'\n\n\n.charset\n: \nutf-8\n\n\n.template\n: \n'rest_framework/admin.html'\n\n\nHTMLFormRenderer\n\n\nRenders data returned by a serializer into an HTML form. The output of this renderer does not include the enclosing \n
    \n tags, a hidden CSRF input or any submit buttons.\n\n\nThis renderer is not intended to be used directly, but can instead be used in templates by passing a serializer instance to the \nrender_form\n template tag.\n\n\n{% load rest_framework %}\n\n\n {% csrf_token %}\n {% render_form serializer %}\n \n
    \n\n\n\nFor more information see the \nHTML & Forms\n documentation.\n\n\n.media_type\n: \ntext/html\n\n\n.format\n: \n'form'\n\n\n.charset\n: \nutf-8\n\n\n.template\n: \n'rest_framework/horizontal/form.html'\n\n\nMultiPartRenderer\n\n\nThis renderer is used for rendering HTML multipart form data. \nIt is not suitable as a response renderer\n, but is instead used for creating test requests, using REST framework's \ntest client and test request factory\n.\n\n\n.media_type\n: \nmultipart/form-data; boundary=BoUnDaRyStRiNg\n\n\n.format\n: \n'multipart'\n\n\n.charset\n: \nutf-8\n\n\n\n\nCustom renderers\n\n\nTo implement a custom renderer, you should override \nBaseRenderer\n, set the \n.media_type\n and \n.format\n properties, and implement the \n.render(self, data, media_type=None, renderer_context=None)\n method.\n\n\nThe method should return a bytestring, which will be used as the body of the HTTP response.\n\n\nThe arguments passed to the \n.render()\n method are:\n\n\ndata\n\n\nThe request data, as set by the \nResponse()\n instantiation.\n\n\nmedia_type=None\n\n\nOptional. If provided, this is the accepted media type, as determined by the content negotiation stage.\n\n\nDepending on the client's \nAccept:\n header, this may be more specific than the renderer's \nmedia_type\n attribute, and may include media type parameters. For example \n\"application/json; nested=true\"\n.\n\n\nrenderer_context=None\n\n\nOptional. If provided, this is a dictionary of contextual information provided by the view.\n\n\nBy default this will include the following keys: \nview\n, \nrequest\n, \nresponse\n, \nargs\n, \nkwargs\n.\n\n\nExample\n\n\nThe following is an example plaintext renderer that will return a response with the \ndata\n parameter as the content of the response.\n\n\nfrom django.utils.encoding import smart_unicode\nfrom rest_framework import renderers\n\n\nclass PlainTextRenderer(renderers.BaseRenderer):\n media_type = 'text/plain'\n format = 'txt'\n\n def render(self, data, media_type=None, renderer_context=None):\n return data.encode(self.charset)\n\n\n\nSetting the character set\n\n\nBy default renderer classes are assumed to be using the \nUTF-8\n encoding. To use a different encoding, set the \ncharset\n attribute on the renderer.\n\n\nclass PlainTextRenderer(renderers.BaseRenderer):\n media_type = 'text/plain'\n format = 'txt'\n charset = 'iso-8859-1'\n\n def render(self, data, media_type=None, renderer_context=None):\n return data.encode(self.charset)\n\n\n\nNote that if a renderer class returns a unicode string, then the response content will be coerced into a bytestring by the \nResponse\n class, with the \ncharset\n attribute set on the renderer used to determine the encoding.\n\n\nIf the renderer returns a bytestring representing raw binary content, you should set a charset value of \nNone\n, which will ensure the \nContent-Type\n header of the response will not have a \ncharset\n value set.\n\n\nIn some cases you may also want to set the \nrender_style\n attribute to \n'binary'\n. Doing so will also ensure that the browsable API will not attempt to display the binary content as a string.\n\n\nclass JPEGRenderer(renderers.BaseRenderer):\n media_type = 'image/jpeg'\n format = 'jpg'\n charset = None\n render_style = 'binary'\n\n def render(self, data, media_type=None, renderer_context=None):\n return data\n\n\n\n\n\nAdvanced renderer usage\n\n\nYou can do some pretty flexible things using REST framework's renderers. Some examples...\n\n\n\n\nProvide either flat or nested representations from the same endpoint, depending on the requested media type.\n\n\nServe both regular HTML webpages, and JSON based API responses from the same endpoints.\n\n\nSpecify multiple types of HTML representation for API clients to use.\n\n\nUnderspecify a renderer's media type, such as using \nmedia_type = 'image/*'\n, and use the \nAccept\n header to vary the encoding of the response.\n\n\n\n\nVarying behaviour by media type\n\n\nIn some cases you might want your view to use different serialization styles depending on the accepted media type. If you need to do this you can access \nrequest.accepted_renderer\n to determine the negotiated renderer that will be used for the response.\n\n\nFor example:\n\n\n@api_view(('GET',))\n@renderer_classes((TemplateHTMLRenderer, JSONRenderer))\ndef list_users(request):\n \"\"\"\n A view that can return JSON or HTML representations\n of the users in the system.\n \"\"\"\n queryset = Users.objects.filter(active=True)\n\n if request.accepted_renderer.format == 'html':\n # TemplateHTMLRenderer takes a context dict,\n # and additionally requires a 'template_name'.\n # It does not require serialization.\n data = {'users': queryset}\n return Response(data, template_name='list_users.html')\n\n # JSONRenderer requires serialized data as normal.\n serializer = UserSerializer(instance=queryset)\n data = serializer.data\n return Response(data)\n\n\n\nUnderspecifying the media type\n\n\nIn some cases you might want a renderer to serve a range of media types.\nIn this case you can underspecify the media types it should respond to, by using a \nmedia_type\n value such as \nimage/*\n, or \n*/*\n.\n\n\nIf you underspecify the renderer's media type, you should make sure to specify the media type explicitly when you return the response, using the \ncontent_type\n attribute. For example:\n\n\nreturn Response(data, content_type='image/png')\n\n\n\nDesigning your media types\n\n\nFor the purposes of many Web APIs, simple \nJSON\n responses with hyperlinked relations may be sufficient. If you want to fully embrace RESTful design and \nHATEOAS\n you'll need to consider the design and usage of your media types in more detail.\n\n\nIn \nthe words of Roy Fielding\n, \"A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types.\".\n\n\nFor good examples of custom media types, see GitHub's use of a custom \napplication/vnd.github+json\n media type, and Mike Amundsen's IANA approved \napplication/vnd.collection+json\n JSON-based hypermedia.\n\n\nHTML error views\n\n\nTypically a renderer will behave the same regardless of if it's dealing with a regular response, or with a response caused by an exception being raised, such as an \nHttp404\n or \nPermissionDenied\n exception, or a subclass of \nAPIException\n.\n\n\nIf you're using either the \nTemplateHTMLRenderer\n or the \nStaticHTMLRenderer\n and an exception is raised, the behavior is slightly different, and mirrors \nDjango's default handling of error views\n.\n\n\nExceptions raised and handled by an HTML renderer will attempt to render using one of the following methods, by order of precedence.\n\n\n\n\nLoad and render a template named \n{status_code}.html\n.\n\n\nLoad and render a template named \napi_exception.html\n.\n\n\nRender the HTTP status code and text, for example \"404 Not Found\".\n\n\n\n\nTemplates will render with a \nRequestContext\n which includes the \nstatus_code\n and \ndetails\n keys.\n\n\nNote\n: If \nDEBUG=True\n, Django's standard traceback error page will be displayed instead of rendering the HTTP status code and text.\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nYAML\n\n\nREST framework YAML\n provides \nYAML\n parsing and rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-yaml\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PARSER_CLASSES': (\n 'rest_framework_yaml.parsers.YAMLParser',\n ),\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework_yaml.renderers.YAMLRenderer',\n ),\n}\n\n\n\nXML\n\n\nREST Framework XML\n 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.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-xml\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PARSER_CLASSES': (\n 'rest_framework_xml.parsers.XMLParser',\n ),\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework_xml.renderers.XMLRenderer',\n ),\n}\n\n\n\nJSONP\n\n\nREST framework JSONP\n provides JSONP rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.\n\n\n\n\nWarning\n: If you require cross-domain AJAX requests, you should generally be using the more modern approach of \nCORS\n as an alternative to \nJSONP\n. See the \nCORS documentation\n for more details.\n\n\nThe \njsonp\n approach is essentially a browser hack, and is \nonly appropriate for globally readable API endpoints\n, where \nGET\n requests are unauthenticated and do not require any user permissions.\n\n\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install djangorestframework-jsonp\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework_jsonp.renderers.JSONPRenderer',\n ),\n}\n\n\n\nMessagePack\n\n\nMessagePack\n is a fast, efficient binary serialization format. \nJuan Riaza\n maintains the \ndjangorestframework-msgpack\n package which provides MessagePack renderer and parser support for REST framework.\n\n\nXLSX (Binary Spreadsheet Endpoints)\n\n\nXLSX is the world's most popular binary spreadsheet format. \nTim Allen\n of \nThe Wharton School\n maintains \ndrf-renderer-xlsx\n, which renders an endpoint as an XLSX spreadsheet using OpenPyXL, and allows the client to download it. Spreadsheets can be styled on a per-view basis.\n\n\nInstallation & configuration\n\n\nInstall using pip.\n\n\n$ pip install drf-renderer-xlsx\n\n\n\nModify your REST framework settings.\n\n\nREST_FRAMEWORK = {\n ...\n\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n 'drf_renderer_xlsx.renderers.XLSXRenderer',\n ),\n}\n\n\n\nTo avoid having a file streamed without a filename (which the browser will often default to the filename \"download\", with no extension), we need to use a mixin to override the \nContent-Disposition\n header. If no filename is provided, it will default to \nexport.xlsx\n. For example:\n\n\nfrom rest_framework.viewsets import ReadOnlyModelViewSet\nfrom drf_renderer_xlsx.mixins import XLSXFileMixin\nfrom drf_renderer_xlsx.renderers import XLSXRenderer\n\nfrom .models import MyExampleModel\nfrom .serializers import MyExampleSerializer\n\nclass MyExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):\n queryset = MyExampleModel.objects.all()\n serializer_class = MyExampleSerializer\n renderer_classes = (XLSXRenderer,)\n filename = 'my_export.xlsx'\n\n\n\nCSV\n\n\nComma-separated values are a plain-text tabular data format, that can be easily imported into spreadsheet applications. \nMjumbe Poe\n maintains the \ndjangorestframework-csv\n package which provides CSV renderer support for REST framework.\n\n\nUltraJSON\n\n\nUltraJSON\n is an optimized C JSON encoder which can give significantly faster JSON rendering. \nJacob Haslehurst\n maintains the \ndrf-ujson-renderer\n package which implements JSON rendering using the UJSON package.\n\n\nCamelCase JSON\n\n\ndjangorestframework-camel-case\n provides camel case JSON renderers and parsers for REST framework. This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names. It is maintained by \nVitaly Babiy\n.\n\n\nPandas (CSV, Excel, PNG)\n\n\nDjango REST Pandas\n provides a serializer and renderers that support additional data processing and output via the \nPandas\n DataFrame API. Django REST Pandas includes renderers for Pandas-style CSV files, Excel workbooks (both \n.xls\n and \n.xlsx\n), and a number of \nother formats\n. It is maintained by \nS. Andrew Sheppard\n as part of the \nwq Project\n.\n\n\nLaTeX\n\n\nRest Framework Latex\n provides a renderer that outputs PDFs using Laulatex. It is maintained by \nPebble (S/F Software)\n.", "title": "Renderers" }, { @@ -1192,22 +1192,22 @@ }, { "location": "/api-guide/renderers/#jsonrenderer", - "text": "Renders the request data into JSON , using utf-8 encoding. 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\",\"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 . {\n \"unicode black star\": \"\u2605\",\n \"value\": 999\n} The default JSON encoding style can be altered using the UNICODE_JSON and COMPACT_JSON settings keys. .media_type : application/json .format : '.json' .charset : None", + "text": "Renders the request data into JSON , using utf-8 encoding. 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\",\"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 . {\n \"unicode black star\": \"\u2605\",\n \"value\": 999\n} The default JSON encoding style can be altered using the UNICODE_JSON and COMPACT_JSON settings keys. .media_type : application/json .format : 'json' .charset : None", "title": "JSONRenderer" }, { "location": "/api-guide/renderers/#templatehtmlrenderer", - "text": "Renders data to HTML, using Django's standard template rendering.\nUnlike 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 . The TemplateHTMLRenderer will create a RequestContext , using the response.data as the context dict, and determine a template name to use to render the context. The template name is determined by (in order of preference): An explicit template_name argument passed to the response. An explicit .template_name attribute set on this class. The return result of calling view.get_template_names() . An example of a view that uses TemplateHTMLRenderer : class UserDetail(generics.RetrieveAPIView):\n \"\"\"\n A view that returns a templated HTML representation of a given user.\n \"\"\"\n queryset = User.objects.all()\n renderer_classes = (TemplateHTMLRenderer,)\n\n def get(self, request, *args, **kwargs):\n self.object = self.get_object()\n return Response({'user': self.object}, template_name='user_detail.html') You can use TemplateHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint. If you're building websites that use TemplateHTMLRenderer along with other renderer classes, you should consider listing TemplateHTMLRenderer as the first class in the renderer_classes list, so that it will be prioritised first even for browsers that send poorly formed ACCEPT: headers. See the HTML & Forms Topic Page for further examples of TemplateHTMLRenderer usage. .media_type : text/html .format : '.html' .charset : utf-8 See also: StaticHTMLRenderer", + "text": "Renders data to HTML, using Django's standard template rendering.\nUnlike 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 . The TemplateHTMLRenderer will create a RequestContext , using the response.data as the context dict, and determine a template name to use to render the context. The template name is determined by (in order of preference): An explicit template_name argument passed to the response. An explicit .template_name attribute set on this class. The return result of calling view.get_template_names() . An example of a view that uses TemplateHTMLRenderer : class UserDetail(generics.RetrieveAPIView):\n \"\"\"\n A view that returns a templated HTML representation of a given user.\n \"\"\"\n queryset = User.objects.all()\n renderer_classes = (TemplateHTMLRenderer,)\n\n def get(self, request, *args, **kwargs):\n self.object = self.get_object()\n return Response({'user': self.object}, template_name='user_detail.html') You can use TemplateHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint. If you're building websites that use TemplateHTMLRenderer along with other renderer classes, you should consider listing TemplateHTMLRenderer as the first class in the renderer_classes list, so that it will be prioritised first even for browsers that send poorly formed ACCEPT: headers. See the HTML & Forms Topic Page for further examples of TemplateHTMLRenderer usage. .media_type : text/html .format : 'html' .charset : utf-8 See also: StaticHTMLRenderer", "title": "TemplateHTMLRenderer" }, { "location": "/api-guide/renderers/#statichtmlrenderer", - "text": "A simple renderer that simply returns pre-rendered HTML. Unlike other renderers, the data passed to the response object should be a string representing the content to be returned. An example of a view that uses StaticHTMLRenderer : @api_view(('GET',))\n@renderer_classes((StaticHTMLRenderer,))\ndef simple_html_view(request):\n data = '

    Hello, world

    '\n return Response(data) You can use StaticHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint. .media_type : text/html .format : '.html' .charset : utf-8 See also: TemplateHTMLRenderer", + "text": "A simple renderer that simply returns pre-rendered HTML. Unlike other renderers, the data passed to the response object should be a string representing the content to be returned. An example of a view that uses StaticHTMLRenderer : @api_view(('GET',))\n@renderer_classes((StaticHTMLRenderer,))\ndef simple_html_view(request):\n data = '

    Hello, world

    '\n return Response(data) You can use StaticHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint. .media_type : text/html .format : 'html' .charset : utf-8 See also: TemplateHTMLRenderer", "title": "StaticHTMLRenderer" }, { "location": "/api-guide/renderers/#browsableapirenderer", - "text": "Renders data into HTML for the Browsable API: This renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page. .media_type : text/html .format : '.api' .charset : utf-8 .template : 'rest_framework/api.html'", + "text": "Renders data into HTML for the Browsable API: This renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page. .media_type : text/html .format : 'api' .charset : utf-8 .template : 'rest_framework/api.html'", "title": "BrowsableAPIRenderer" }, { @@ -1217,17 +1217,17 @@ }, { "location": "/api-guide/renderers/#adminrenderer", - "text": "Renders data into HTML for an admin-like display: This renderer is suitable for CRUD-style web APIs that should also present a user-friendly interface for managing the data. Note that views that have nested or list serializers for their input won't work well with the AdminRenderer , as the HTML forms are unable to properly support them. Note : The AdminRenderer is only able to include links to detail pages when a properly configured URL_FIELD_NAME ( url by default) attribute is present in the data. For HyperlinkedModelSerializer this will be the case, but for ModelSerializer or plain Serializer classes you'll need to make sure to include the field explicitly. For example here we use models get_absolute_url method: class AccountSerializer(serializers.ModelSerializer):\n url = serializers.CharField(source='get_absolute_url', read_only=True)\n\n class Meta:\n model = Account .media_type : text/html .format : '.admin' .charset : utf-8 .template : 'rest_framework/admin.html'", + "text": "Renders data into HTML for an admin-like display: This renderer is suitable for CRUD-style web APIs that should also present a user-friendly interface for managing the data. Note that views that have nested or list serializers for their input won't work well with the AdminRenderer , as the HTML forms are unable to properly support them. Note : The AdminRenderer is only able to include links to detail pages when a properly configured URL_FIELD_NAME ( url by default) attribute is present in the data. For HyperlinkedModelSerializer this will be the case, but for ModelSerializer or plain Serializer classes you'll need to make sure to include the field explicitly. For example here we use models get_absolute_url method: class AccountSerializer(serializers.ModelSerializer):\n url = serializers.CharField(source='get_absolute_url', read_only=True)\n\n class Meta:\n model = Account .media_type : text/html .format : 'admin' .charset : utf-8 .template : 'rest_framework/admin.html'", "title": "AdminRenderer" }, { "location": "/api-guide/renderers/#htmlformrenderer", - "text": "Renders data returned by a serializer into an HTML form. The output of this renderer does not include the enclosing
    tags, a hidden CSRF input or any submit buttons. This renderer is not intended to be used directly, but can instead be used in templates by passing a serializer instance to the render_form template tag. {% load rest_framework %}\n\n\n {% csrf_token %}\n {% render_form serializer %}\n \n
    For more information see the HTML & Forms documentation. .media_type : text/html .format : '.form' .charset : utf-8 .template : 'rest_framework/horizontal/form.html'", + "text": "Renders data returned by a serializer into an HTML form. The output of this renderer does not include the enclosing
    tags, a hidden CSRF input or any submit buttons. This renderer is not intended to be used directly, but can instead be used in templates by passing a serializer instance to the render_form template tag. {% load rest_framework %}\n\n\n {% csrf_token %}\n {% render_form serializer %}\n \n
    For more information see the HTML & Forms documentation. .media_type : text/html .format : 'form' .charset : utf-8 .template : 'rest_framework/horizontal/form.html'", "title": "HTMLFormRenderer" }, { "location": "/api-guide/renderers/#multipartrenderer", - "text": "This renderer is used for rendering HTML multipart form data. It is not suitable as a response renderer , but is instead used for creating test requests, using REST framework's test client and test request factory . .media_type : multipart/form-data; boundary=BoUnDaRyStRiNg .format : '.multipart' .charset : utf-8", + "text": "This renderer is used for rendering HTML multipart form data. It is not suitable as a response renderer , but is instead used for creating test requests, using REST framework's test client and test request factory . .media_type : multipart/form-data; boundary=BoUnDaRyStRiNg .format : 'multipart' .charset : utf-8", "title": "MultiPartRenderer" }, { @@ -2107,17 +2107,17 @@ }, { "location": "/api-guide/relations/", - "text": "Serializer relations\n\n\n\n\nBad programmers worry about the code.\nGood programmers worry about data structures and their relationships.\n\n\n\u2014 \nLinus Torvalds\n\n\n\n\nRelational fields are used to represent model relationships. They can be applied to \nForeignKey\n, \nManyToManyField\n and \nOneToOneField\n relationships, as well as to reverse relationships, and custom relationships such as \nGenericForeignKey\n.\n\n\n\n\nNote:\n The relational fields are declared in \nrelations.py\n, but by convention you should import them from the \nserializers\n module, using \nfrom rest_framework import serializers\n and refer to fields as \nserializers.\n.\n\n\n\n\nInspecting relationships.\n\n\nWhen using the \nModelSerializer\n class, serializer fields and relationships will be automatically generated for you. Inspecting these automatically generated fields can be a useful tool for determining how to customize the relationship style.\n\n\nTo do so, open the Django shell, using \npython manage.py shell\n, then import the serializer class, instantiate it, and print the object representation\u2026\n\n\n>>> from myapp.serializers import AccountSerializer\n>>> serializer = AccountSerializer()\n>>> print repr(serializer) # Or `print(repr(serializer))` in Python 3.x.\nAccountSerializer():\n id = IntegerField(label='ID', read_only=True)\n name = CharField(allow_blank=True, max_length=100, required=False)\n owner = PrimaryKeyRelatedField(queryset=User.objects.all())\n\n\n\nAPI Reference\n\n\nIn order to explain the various types of relational fields, we'll use a couple of simple models for our examples. Our models will be for music albums, and the tracks listed on each album.\n\n\nclass Album(models.Model):\n album_name = models.CharField(max_length=100)\n artist = models.CharField(max_length=100)\n\nclass Track(models.Model):\n album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)\n order = models.IntegerField()\n title = models.CharField(max_length=100)\n duration = models.IntegerField()\n\n class Meta:\n unique_together = ('album', 'order')\n ordering = ['order']\n\n def __unicode__(self):\n return '%d: %s' % (self.order, self.title)\n\n\n\nStringRelatedField\n\n\nStringRelatedField\n may be used to represent the target of the relationship using its \n__unicode__\n method.\n\n\nFor example, the following serializer.\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = serializers.StringRelatedField(many=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to the following representation.\n\n\n{\n 'album_name': 'Things We Lost In The Fire',\n 'artist': 'Low',\n 'tracks': [\n '1: Sunflower',\n '2: Whitetail',\n '3: Dinosaur Act',\n ...\n ]\n}\n\n\n\nThis field is read only.\n\n\nArguments\n:\n\n\n\n\nmany\n - If applied to a to-many relationship, you should set this argument to \nTrue\n.\n\n\n\n\nPrimaryKeyRelatedField\n\n\nPrimaryKeyRelatedField\n may be used to represent the target of the relationship using its primary key.\n\n\nFor example, the following serializer:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to a representation like this:\n\n\n{\n 'album_name': 'Undun',\n 'artist': 'The Roots',\n 'tracks': [\n 89,\n 90,\n 91,\n ...\n ]\n}\n\n\n\nBy default this field is read-write, although you can change this behavior using the \nread_only\n flag.\n\n\nArguments\n:\n\n\n\n\nqueryset\n - The queryset used for model instance lookups when validating the field input. Relationships must either set a queryset explicitly, or set \nread_only=True\n.\n\n\nmany\n - If applied to a to-many relationship, you should set this argument to \nTrue\n.\n\n\nallow_null\n - If set to \nTrue\n, the field will accept values of \nNone\n or the empty string for nullable relationships. Defaults to \nFalse\n.\n\n\npk_field\n - Set to a field to control serialization/deserialization of the primary key's value. For example, \npk_field=UUIDField(format='hex')\n would serialize a UUID primary key into its compact hex representation.\n\n\n\n\nHyperlinkedRelatedField\n\n\nHyperlinkedRelatedField\n may be used to represent the target of the relationship using a hyperlink.\n\n\nFor example, the following serializer:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = serializers.HyperlinkedRelatedField(\n many=True,\n read_only=True,\n view_name='track-detail'\n )\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to a representation like this:\n\n\n{\n 'album_name': 'Graceland',\n 'artist': 'Paul Simon',\n 'tracks': [\n 'http://www.example.com/api/tracks/45/',\n 'http://www.example.com/api/tracks/46/',\n 'http://www.example.com/api/tracks/47/',\n ...\n ]\n}\n\n\n\nBy default this field is read-write, although you can change this behavior using the \nread_only\n flag.\n\n\n\n\nNote\n: This field is designed for objects that map to a URL that accepts a single URL keyword argument, as set using the \nlookup_field\n and \nlookup_url_kwarg\n arguments.\n\n\nThis is suitable for URLs that contain a single primary key or slug argument as part of the URL.\n\n\nIf you require more complex hyperlinked representation you'll need to customize the field, as described in the \ncustom hyperlinked fields\n section, below.\n\n\n\n\nArguments\n:\n\n\n\n\nview_name\n - The view name that should be used as the target of the relationship. If you're using \nthe standard router classes\n this will be a string with the format \n-detail\n. \nrequired\n.\n\n\nqueryset\n - The queryset used for model instance lookups when validating the field input. Relationships must either set a queryset explicitly, or set \nread_only=True\n.\n\n\nmany\n - If applied to a to-many relationship, you should set this argument to \nTrue\n.\n\n\nallow_null\n - If set to \nTrue\n, the field will accept values of \nNone\n or the empty string for nullable relationships. Defaults to \nFalse\n.\n\n\nlookup_field\n - 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 \n'pk'\n.\n\n\nlookup_url_kwarg\n - The name of the keyword argument defined in the URL conf that corresponds to the lookup field. Defaults to using the same value as \nlookup_field\n.\n\n\nformat\n - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the \nformat\n argument.\n\n\n\n\nSlugRelatedField\n\n\nSlugRelatedField\n may be used to represent the target of the relationship using a field on the target.\n\n\nFor example, the following serializer:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = serializers.SlugRelatedField(\n many=True,\n read_only=True,\n slug_field='title'\n )\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to a representation like this:\n\n\n{\n 'album_name': 'Dear John',\n 'artist': 'Loney Dear',\n 'tracks': [\n 'Airport Surroundings',\n 'Everything Turns to You',\n 'I Was Only Going Out',\n ...\n ]\n}\n\n\n\nBy default this field is read-write, although you can change this behavior using the \nread_only\n flag.\n\n\nWhen using \nSlugRelatedField\n as a read-write field, you will normally want to ensure that the slug field corresponds to a model field with \nunique=True\n.\n\n\nArguments\n:\n\n\n\n\nslug_field\n - The field on the target that should be used to represent it. This should be a field that uniquely identifies any given instance. For example, \nusername\n. \nrequired\n\n\nqueryset\n - The queryset used for model instance lookups when validating the field input. Relationships must either set a queryset explicitly, or set \nread_only=True\n.\n\n\nmany\n - If applied to a to-many relationship, you should set this argument to \nTrue\n.\n\n\nallow_null\n - If set to \nTrue\n, the field will accept values of \nNone\n or the empty string for nullable relationships. Defaults to \nFalse\n.\n\n\n\n\nHyperlinkedIdentityField\n\n\nThis field can be applied as an identity relationship, such as the \n'url'\n field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer:\n\n\nclass AlbumSerializer(serializers.HyperlinkedModelSerializer):\n track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'track_listing')\n\n\n\nWould serialize to a representation like this:\n\n\n{\n 'album_name': 'The Eraser',\n 'artist': 'Thom Yorke',\n 'track_listing': 'http://www.example.com/api/track_list/12/',\n}\n\n\n\nThis field is always read-only.\n\n\nArguments\n:\n\n\n\n\nview_name\n - The view name that should be used as the target of the relationship. If you're using \nthe standard router classes\n this will be a string with the format \n-detail\n. \nrequired\n.\n\n\nlookup_field\n - 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 \n'pk'\n.\n\n\nlookup_url_kwarg\n - The name of the keyword argument defined in the URL conf that corresponds to the lookup field. Defaults to using the same value as \nlookup_field\n.\n\n\nformat\n - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the \nformat\n argument.\n\n\n\n\n\n\nNested relationships\n\n\nNested relationships can be expressed by using serializers as fields.\n\n\nIf the field is used to represent a to-many relationship, you should add the \nmany=True\n flag to the serializer field.\n\n\nExample\n\n\nFor example, the following serializer:\n\n\nclass TrackSerializer(serializers.ModelSerializer):\n class Meta:\n model = Track\n fields = ('order', 'title', 'duration')\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = TrackSerializer(many=True, read_only=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to a nested representation like this:\n\n\n>>> album = Album.objects.create(album_name=\"The Grey Album\", artist='Danger Mouse')\n>>> Track.objects.create(album=album, order=1, title='Public Service Announcement', duration=245)\n\n>>> Track.objects.create(album=album, order=2, title='What More Can I Say', duration=264)\n\n>>> Track.objects.create(album=album, order=3, title='Encore', duration=159)\n\n>>> serializer = AlbumSerializer(instance=album)\n>>> serializer.data\n{\n 'album_name': 'The Grey Album',\n 'artist': 'Danger Mouse',\n 'tracks': [\n {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},\n {'order': 2, 'title': 'What More Can I Say', 'duration': 264},\n {'order': 3, 'title': 'Encore', 'duration': 159},\n ...\n ],\n}\n\n\n\nWritable nested serializers\n\n\nBy default nested serializers are read-only. If you want to support write-operations to a nested serializer field you'll need to create \ncreate()\n and/or \nupdate()\n methods in order to explicitly specify how the child relationships should be saved.\n\n\nclass TrackSerializer(serializers.ModelSerializer):\n class Meta:\n model = Track\n fields = ('order', 'title', 'duration')\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = TrackSerializer(many=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n def create(self, validated_data):\n tracks_data = validated_data.pop('tracks')\n album = Album.objects.create(**validated_data)\n for track_data in tracks_data:\n Track.objects.create(album=album, **track_data)\n return album\n\n>>> data = {\n 'album_name': 'The Grey Album',\n 'artist': 'Danger Mouse',\n 'tracks': [\n {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},\n {'order': 2, 'title': 'What More Can I Say', 'duration': 264},\n {'order': 3, 'title': 'Encore', 'duration': 159},\n ],\n}\n>>> serializer = AlbumSerializer(data=data)\n>>> serializer.is_valid()\nTrue\n>>> serializer.save()\n\n\n\n\n\n\nCustom relational fields\n\n\nIn rare cases where none of the existing relational styles fit the representation you need,\nyou can implement a completely custom relational field, that describes exactly how the\noutput representation should be generated from the model instance.\n\n\nTo implement a custom relational field, you should override \nRelatedField\n, and implement the \n.to_representation(self, value)\n method. This method takes the target of the field as the \nvalue\n argument, and should return the representation that should be used to serialize the target. The \nvalue\n argument will typically be a model instance.\n\n\nIf you want to implement a read-write relational field, you must also implement the \n.to_internal_value(self, data)\n method.\n\n\nTo provide a dynamic queryset based on the \ncontext\n, you can also override \n.get_queryset(self)\n instead of specifying \n.queryset\n on the class or when initializing the field.\n\n\nExample\n\n\nFor example, we could define a relational field to serialize a track to a custom string representation, using its ordering, title, and duration.\n\n\nimport time\n\nclass TrackListingField(serializers.RelatedField):\n def to_representation(self, value):\n duration = time.strftime('%M:%S', time.gmtime(value.duration))\n return 'Track %d: %s (%s)' % (value.order, value.name, duration)\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = TrackListingField(many=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nThis custom field would then serialize to the following representation.\n\n\n{\n 'album_name': 'Sometimes I Wish We Were an Eagle',\n 'artist': 'Bill Callahan',\n 'tracks': [\n 'Track 1: Jim Cain (04:39)',\n 'Track 2: Eid Ma Clack Shaw (04:19)',\n 'Track 3: The Wind and the Dove (04:34)',\n ...\n ]\n}\n\n\n\n\n\nCustom hyperlinked fields\n\n\nIn some cases you may need to customize the behavior of a hyperlinked field, in order to represent URLs that require more than a single lookup field.\n\n\nYou can achieve this by overriding \nHyperlinkedRelatedField\n. There are two methods that may be overridden:\n\n\nget_url(self, obj, view_name, request, format)\n\n\nThe \nget_url\n method is used to map the object instance to its URL representation.\n\n\nMay raise a \nNoReverseMatch\n if the \nview_name\n and \nlookup_field\n\nattributes are not configured to correctly match the URL conf.\n\n\nget_object(self, view_name, view_args, view_kwargs)\n\n\nIf you want to support a writable hyperlinked field then you'll also want to override \nget_object\n, in order to map incoming URLs back to the object they represent. For read-only hyperlinked fields there is no need to override this method.\n\n\nThe return value of this method should the object that corresponds to the matched URL conf arguments.\n\n\nMay raise an \nObjectDoesNotExist\n exception.\n\n\nExample\n\n\nSay we have a URL for a customer object that takes two keyword arguments, like so:\n\n\n/api//customers//\n\n\n\nThis cannot be represented with the default implementation, which accepts only a single lookup field.\n\n\nIn this case we'd need to override \nHyperlinkedRelatedField\n to get the behavior we want:\n\n\nfrom rest_framework import serializers\nfrom rest_framework.reverse import reverse\n\nclass CustomerHyperlink(serializers.HyperlinkedRelatedField):\n # We define these as class attributes, so we don't need to pass them as arguments.\n view_name = 'customer-detail'\n queryset = Customer.objects.all()\n\n def get_url(self, obj, view_name, request, format):\n url_kwargs = {\n 'organization_slug': obj.organization.slug,\n 'customer_pk': obj.pk\n }\n return reverse(view_name, kwargs=url_kwargs, request=request, format=format)\n\n def get_object(self, view_name, view_args, view_kwargs):\n lookup_kwargs = {\n 'organization__slug': view_kwargs['organization_slug'],\n 'pk': view_kwargs['customer_pk']\n }\n return self.get_queryset().get(**lookup_kwargs)\n\n\n\nNote that if you wanted to use this style together with the generic views then you'd also need to override \n.get_object\n on the view in order to get the correct lookup behavior.\n\n\nGenerally we recommend a flat style for API representations where possible, but the nested URL style can also be reasonable when used in moderation.\n\n\n\n\nFurther notes\n\n\nThe \nqueryset\n argument\n\n\nThe \nqueryset\n argument is only ever required for \nwritable\n relationship field, in which case it is used for performing the model instance lookup, that maps from the primitive user input, into a model instance.\n\n\nIn version 2.x a serializer class could \nsometimes\n automatically determine the \nqueryset\n argument \nif\n a \nModelSerializer\n class was being used.\n\n\nThis behavior is now replaced with \nalways\n using an explicit \nqueryset\n argument for writable relational fields.\n\n\nDoing so reduces the amount of hidden 'magic' that \nModelSerializer\n provides, makes the behavior of the field more clear, and ensures that it is trivial to move between using the \nModelSerializer\n shortcut, or using fully explicit \nSerializer\n classes.\n\n\nCustomizing the HTML display\n\n\nThe built-in \n__str__\n method of the model will be used to generate string representations of the objects used to populate the \nchoices\n property. These choices are used to populate select HTML inputs in the browsable API.\n\n\nTo provide customized representations for such inputs, override \ndisplay_value()\n of a \nRelatedField\n subclass. This method will receive a model object, and should return a string suitable for representing it. For example:\n\n\nclass TrackPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):\n def display_value(self, instance):\n return 'Track: %s' % (instance.title)\n\n\n\nSelect field cutoffs\n\n\nWhen rendered in the browsable API relational fields will default to only displaying a maximum of 1000 selectable items. If more items are present then a disabled option with \"More than 1000 items\u2026\" will be displayed.\n\n\nThis behavior is intended to prevent a template from being unable to render in an acceptable timespan due to a very large number of relationships being displayed.\n\n\nThere are two keyword arguments you can use to control this behavior:\n\n\n\n\nhtml_cutoff\n - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Set to \nNone\n to disable any limiting. Defaults to \n1000\n.\n\n\nhtml_cutoff_text\n - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to \n\"More than {count} items\u2026\"\n\n\n\n\nYou can also control these globally using the settings \nHTML_SELECT_CUTOFF\n and \nHTML_SELECT_CUTOFF_TEXT\n.\n\n\nIn cases where the cutoff is being enforced you may want to instead use a plain input field in the HTML form. You can do so using the \nstyle\n keyword argument. For example:\n\n\nassigned_to = serializers.SlugRelatedField(\n queryset=User.objects.all(),\n slug_field='username',\n style={'base_template': 'input.html'}\n)\n\n\n\nReverse relations\n\n\nNote that reverse relationships are not automatically included by the \nModelSerializer\n and \nHyperlinkedModelSerializer\n classes. To include a reverse relationship, you must explicitly add it to the fields list. For example:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n class Meta:\n fields = ('tracks', ...)\n\n\n\nYou'll normally want to ensure that you've set an appropriate \nrelated_name\n argument on the relationship, that you can use as the field name. For example:\n\n\nclass Track(models.Model):\n album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)\n ...\n\n\n\nIf you have not set a related name for the reverse relationship, you'll need to use the automatically generated related name in the \nfields\n argument. For example:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n class Meta:\n fields = ('track_set', ...)\n\n\n\nSee the Django documentation on \nreverse relationships\n for more details.\n\n\nGeneric relationships\n\n\nIf you want to serialize a generic foreign key, you need to define a custom field, to determine explicitly how you want to serialize the targets of the relationship.\n\n\nFor example, given the following model for a tag, which has a generic relationship with other arbitrary models:\n\n\nclass TaggedItem(models.Model):\n \"\"\"\n Tags arbitrary model instances using a generic relation.\n\n See: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/\n \"\"\"\n tag_name = models.SlugField()\n content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)\n object_id = models.PositiveIntegerField()\n tagged_object = GenericForeignKey('content_type', 'object_id')\n\n def __unicode__(self):\n return self.tag_name\n\n\n\nAnd the following two models, which may have associated tags:\n\n\nclass Bookmark(models.Model):\n \"\"\"\n A bookmark consists of a URL, and 0 or more descriptive tags.\n \"\"\"\n url = models.URLField()\n tags = GenericRelation(TaggedItem)\n\n\nclass Note(models.Model):\n \"\"\"\n A note consists of some text, and 0 or more descriptive tags.\n \"\"\"\n text = models.CharField(max_length=1000)\n tags = GenericRelation(TaggedItem)\n\n\n\nWe could define a custom field that could be used to serialize tagged instances, using the type of each instance to determine how it should be serialized.\n\n\nclass TaggedObjectRelatedField(serializers.RelatedField):\n \"\"\"\n A custom field to use for the `tagged_object` generic relationship.\n \"\"\"\n\n def to_representation(self, value):\n \"\"\"\n Serialize tagged objects to a simple textual representation.\n \"\"\"\n if isinstance(value, Bookmark):\n return 'Bookmark: ' + value.url\n elif isinstance(value, Note):\n return 'Note: ' + value.text\n raise Exception('Unexpected type of tagged object')\n\n\n\nIf you need the target of the relationship to have a nested representation, you can use the required serializers inside the \n.to_representation()\n method:\n\n\n def to_representation(self, value):\n \"\"\"\n Serialize bookmark instances using a bookmark serializer,\n and note instances using a note serializer.\n \"\"\"\n if isinstance(value, Bookmark):\n serializer = BookmarkSerializer(value)\n elif isinstance(value, Note):\n serializer = NoteSerializer(value)\n else:\n raise Exception('Unexpected type of tagged object')\n\n return serializer.data\n\n\n\nNote that reverse generic keys, expressed using the \nGenericRelation\n field, can be serialized using the regular relational field types, since the type of the target in the relationship is always known.\n\n\nFor more information see \nthe Django documentation on generic relations\n.\n\n\nManyToManyFields with a Through Model\n\n\nBy default, relational fields that target a \nManyToManyField\n with a\n\nthrough\n model specified are set to read-only.\n\n\nIf you explicitly specify a relational field pointing to a\n\nManyToManyField\n with a through model, be sure to set \nread_only\n\nto \nTrue\n.\n\n\n\n\nThird Party Packages\n\n\nThe following third party packages are also available.\n\n\nDRF Nested Routers\n\n\nThe \ndrf-nested-routers package\n provides routers and relationship fields for working with nested resources.\n\n\nRest Framework Generic Relations\n\n\nThe \nrest-framework-generic-relations\n library provides read/write serialization for generic foreign keys.", + "text": "Serializer relations\n\n\n\n\nData structures, not algorithms, are central to programming.\n\n\n\u2014 \nRob Pike\n\n\n\n\nRelational fields are used to represent model relationships. They can be applied to \nForeignKey\n, \nManyToManyField\n and \nOneToOneField\n relationships, as well as to reverse relationships, and custom relationships such as \nGenericForeignKey\n.\n\n\n\n\nNote:\n The relational fields are declared in \nrelations.py\n, but by convention you should import them from the \nserializers\n module, using \nfrom rest_framework import serializers\n and refer to fields as \nserializers.\n.\n\n\n\n\nInspecting relationships.\n\n\nWhen using the \nModelSerializer\n class, serializer fields and relationships will be automatically generated for you. Inspecting these automatically generated fields can be a useful tool for determining how to customize the relationship style.\n\n\nTo do so, open the Django shell, using \npython manage.py shell\n, then import the serializer class, instantiate it, and print the object representation\u2026\n\n\n>>> from myapp.serializers import AccountSerializer\n>>> serializer = AccountSerializer()\n>>> print(repr(serializer))\nAccountSerializer():\n id = IntegerField(label='ID', read_only=True)\n name = CharField(allow_blank=True, max_length=100, required=False)\n owner = PrimaryKeyRelatedField(queryset=User.objects.all())\n\n\n\nAPI Reference\n\n\nIn order to explain the various types of relational fields, we'll use a couple of simple models for our examples. Our models will be for music albums, and the tracks listed on each album.\n\n\nclass Album(models.Model):\n album_name = models.CharField(max_length=100)\n artist = models.CharField(max_length=100)\n\nclass Track(models.Model):\n album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)\n order = models.IntegerField()\n title = models.CharField(max_length=100)\n duration = models.IntegerField()\n\n class Meta:\n unique_together = ('album', 'order')\n ordering = ['order']\n\n def __unicode__(self):\n return '%d: %s' % (self.order, self.title)\n\n\n\nStringRelatedField\n\n\nStringRelatedField\n may be used to represent the target of the relationship using its \n__unicode__\n method.\n\n\nFor example, the following serializer.\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = serializers.StringRelatedField(many=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to the following representation.\n\n\n{\n 'album_name': 'Things We Lost In The Fire',\n 'artist': 'Low',\n 'tracks': [\n '1: Sunflower',\n '2: Whitetail',\n '3: Dinosaur Act',\n ...\n ]\n}\n\n\n\nThis field is read only.\n\n\nArguments\n:\n\n\n\n\nmany\n - If applied to a to-many relationship, you should set this argument to \nTrue\n.\n\n\n\n\nPrimaryKeyRelatedField\n\n\nPrimaryKeyRelatedField\n may be used to represent the target of the relationship using its primary key.\n\n\nFor example, the following serializer:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to a representation like this:\n\n\n{\n 'album_name': 'Undun',\n 'artist': 'The Roots',\n 'tracks': [\n 89,\n 90,\n 91,\n ...\n ]\n}\n\n\n\nBy default this field is read-write, although you can change this behavior using the \nread_only\n flag.\n\n\nArguments\n:\n\n\n\n\nqueryset\n - The queryset used for model instance lookups when validating the field input. Relationships must either set a queryset explicitly, or set \nread_only=True\n.\n\n\nmany\n - If applied to a to-many relationship, you should set this argument to \nTrue\n.\n\n\nallow_null\n - If set to \nTrue\n, the field will accept values of \nNone\n or the empty string for nullable relationships. Defaults to \nFalse\n.\n\n\npk_field\n - Set to a field to control serialization/deserialization of the primary key's value. For example, \npk_field=UUIDField(format='hex')\n would serialize a UUID primary key into its compact hex representation.\n\n\n\n\nHyperlinkedRelatedField\n\n\nHyperlinkedRelatedField\n may be used to represent the target of the relationship using a hyperlink.\n\n\nFor example, the following serializer:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = serializers.HyperlinkedRelatedField(\n many=True,\n read_only=True,\n view_name='track-detail'\n )\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to a representation like this:\n\n\n{\n 'album_name': 'Graceland',\n 'artist': 'Paul Simon',\n 'tracks': [\n 'http://www.example.com/api/tracks/45/',\n 'http://www.example.com/api/tracks/46/',\n 'http://www.example.com/api/tracks/47/',\n ...\n ]\n}\n\n\n\nBy default this field is read-write, although you can change this behavior using the \nread_only\n flag.\n\n\n\n\nNote\n: This field is designed for objects that map to a URL that accepts a single URL keyword argument, as set using the \nlookup_field\n and \nlookup_url_kwarg\n arguments.\n\n\nThis is suitable for URLs that contain a single primary key or slug argument as part of the URL.\n\n\nIf you require more complex hyperlinked representation you'll need to customize the field, as described in the \ncustom hyperlinked fields\n section, below.\n\n\n\n\nArguments\n:\n\n\n\n\nview_name\n - The view name that should be used as the target of the relationship. If you're using \nthe standard router classes\n this will be a string with the format \n-detail\n. \nrequired\n.\n\n\nqueryset\n - The queryset used for model instance lookups when validating the field input. Relationships must either set a queryset explicitly, or set \nread_only=True\n.\n\n\nmany\n - If applied to a to-many relationship, you should set this argument to \nTrue\n.\n\n\nallow_null\n - If set to \nTrue\n, the field will accept values of \nNone\n or the empty string for nullable relationships. Defaults to \nFalse\n.\n\n\nlookup_field\n - 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 \n'pk'\n.\n\n\nlookup_url_kwarg\n - The name of the keyword argument defined in the URL conf that corresponds to the lookup field. Defaults to using the same value as \nlookup_field\n.\n\n\nformat\n - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the \nformat\n argument.\n\n\n\n\nSlugRelatedField\n\n\nSlugRelatedField\n may be used to represent the target of the relationship using a field on the target.\n\n\nFor example, the following serializer:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = serializers.SlugRelatedField(\n many=True,\n read_only=True,\n slug_field='title'\n )\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to a representation like this:\n\n\n{\n 'album_name': 'Dear John',\n 'artist': 'Loney Dear',\n 'tracks': [\n 'Airport Surroundings',\n 'Everything Turns to You',\n 'I Was Only Going Out',\n ...\n ]\n}\n\n\n\nBy default this field is read-write, although you can change this behavior using the \nread_only\n flag.\n\n\nWhen using \nSlugRelatedField\n as a read-write field, you will normally want to ensure that the slug field corresponds to a model field with \nunique=True\n.\n\n\nArguments\n:\n\n\n\n\nslug_field\n - The field on the target that should be used to represent it. This should be a field that uniquely identifies any given instance. For example, \nusername\n. \nrequired\n\n\nqueryset\n - The queryset used for model instance lookups when validating the field input. Relationships must either set a queryset explicitly, or set \nread_only=True\n.\n\n\nmany\n - If applied to a to-many relationship, you should set this argument to \nTrue\n.\n\n\nallow_null\n - If set to \nTrue\n, the field will accept values of \nNone\n or the empty string for nullable relationships. Defaults to \nFalse\n.\n\n\n\n\nHyperlinkedIdentityField\n\n\nThis field can be applied as an identity relationship, such as the \n'url'\n field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer:\n\n\nclass AlbumSerializer(serializers.HyperlinkedModelSerializer):\n track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'track_listing')\n\n\n\nWould serialize to a representation like this:\n\n\n{\n 'album_name': 'The Eraser',\n 'artist': 'Thom Yorke',\n 'track_listing': 'http://www.example.com/api/track_list/12/',\n}\n\n\n\nThis field is always read-only.\n\n\nArguments\n:\n\n\n\n\nview_name\n - The view name that should be used as the target of the relationship. If you're using \nthe standard router classes\n this will be a string with the format \n-detail\n. \nrequired\n.\n\n\nlookup_field\n - 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 \n'pk'\n.\n\n\nlookup_url_kwarg\n - The name of the keyword argument defined in the URL conf that corresponds to the lookup field. Defaults to using the same value as \nlookup_field\n.\n\n\nformat\n - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the \nformat\n argument.\n\n\n\n\n\n\nNested relationships\n\n\nNested relationships can be expressed by using serializers as fields.\n\n\nIf the field is used to represent a to-many relationship, you should add the \nmany=True\n flag to the serializer field.\n\n\nExample\n\n\nFor example, the following serializer:\n\n\nclass TrackSerializer(serializers.ModelSerializer):\n class Meta:\n model = Track\n fields = ('order', 'title', 'duration')\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = TrackSerializer(many=True, read_only=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nWould serialize to a nested representation like this:\n\n\n>>> album = Album.objects.create(album_name=\"The Grey Album\", artist='Danger Mouse')\n>>> Track.objects.create(album=album, order=1, title='Public Service Announcement', duration=245)\n\n>>> Track.objects.create(album=album, order=2, title='What More Can I Say', duration=264)\n\n>>> Track.objects.create(album=album, order=3, title='Encore', duration=159)\n\n>>> serializer = AlbumSerializer(instance=album)\n>>> serializer.data\n{\n 'album_name': 'The Grey Album',\n 'artist': 'Danger Mouse',\n 'tracks': [\n {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},\n {'order': 2, 'title': 'What More Can I Say', 'duration': 264},\n {'order': 3, 'title': 'Encore', 'duration': 159},\n ...\n ],\n}\n\n\n\nWritable nested serializers\n\n\nBy default nested serializers are read-only. If you want to support write-operations to a nested serializer field you'll need to create \ncreate()\n and/or \nupdate()\n methods in order to explicitly specify how the child relationships should be saved.\n\n\nclass TrackSerializer(serializers.ModelSerializer):\n class Meta:\n model = Track\n fields = ('order', 'title', 'duration')\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = TrackSerializer(many=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n def create(self, validated_data):\n tracks_data = validated_data.pop('tracks')\n album = Album.objects.create(**validated_data)\n for track_data in tracks_data:\n Track.objects.create(album=album, **track_data)\n return album\n\n>>> data = {\n 'album_name': 'The Grey Album',\n 'artist': 'Danger Mouse',\n 'tracks': [\n {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},\n {'order': 2, 'title': 'What More Can I Say', 'duration': 264},\n {'order': 3, 'title': 'Encore', 'duration': 159},\n ],\n}\n>>> serializer = AlbumSerializer(data=data)\n>>> serializer.is_valid()\nTrue\n>>> serializer.save()\n\n\n\n\n\n\nCustom relational fields\n\n\nIn rare cases where none of the existing relational styles fit the representation you need,\nyou can implement a completely custom relational field, that describes exactly how the\noutput representation should be generated from the model instance.\n\n\nTo implement a custom relational field, you should override \nRelatedField\n, and implement the \n.to_representation(self, value)\n method. This method takes the target of the field as the \nvalue\n argument, and should return the representation that should be used to serialize the target. The \nvalue\n argument will typically be a model instance.\n\n\nIf you want to implement a read-write relational field, you must also implement the \n.to_internal_value(self, data)\n method.\n\n\nTo provide a dynamic queryset based on the \ncontext\n, you can also override \n.get_queryset(self)\n instead of specifying \n.queryset\n on the class or when initializing the field.\n\n\nExample\n\n\nFor example, we could define a relational field to serialize a track to a custom string representation, using its ordering, title, and duration.\n\n\nimport time\n\nclass TrackListingField(serializers.RelatedField):\n def to_representation(self, value):\n duration = time.strftime('%M:%S', time.gmtime(value.duration))\n return 'Track %d: %s (%s)' % (value.order, value.name, duration)\n\nclass AlbumSerializer(serializers.ModelSerializer):\n tracks = TrackListingField(many=True)\n\n class Meta:\n model = Album\n fields = ('album_name', 'artist', 'tracks')\n\n\n\nThis custom field would then serialize to the following representation.\n\n\n{\n 'album_name': 'Sometimes I Wish We Were an Eagle',\n 'artist': 'Bill Callahan',\n 'tracks': [\n 'Track 1: Jim Cain (04:39)',\n 'Track 2: Eid Ma Clack Shaw (04:19)',\n 'Track 3: The Wind and the Dove (04:34)',\n ...\n ]\n}\n\n\n\n\n\nCustom hyperlinked fields\n\n\nIn some cases you may need to customize the behavior of a hyperlinked field, in order to represent URLs that require more than a single lookup field.\n\n\nYou can achieve this by overriding \nHyperlinkedRelatedField\n. There are two methods that may be overridden:\n\n\nget_url(self, obj, view_name, request, format)\n\n\nThe \nget_url\n method is used to map the object instance to its URL representation.\n\n\nMay raise a \nNoReverseMatch\n if the \nview_name\n and \nlookup_field\n\nattributes are not configured to correctly match the URL conf.\n\n\nget_object(self, view_name, view_args, view_kwargs)\n\n\nIf you want to support a writable hyperlinked field then you'll also want to override \nget_object\n, in order to map incoming URLs back to the object they represent. For read-only hyperlinked fields there is no need to override this method.\n\n\nThe return value of this method should the object that corresponds to the matched URL conf arguments.\n\n\nMay raise an \nObjectDoesNotExist\n exception.\n\n\nExample\n\n\nSay we have a URL for a customer object that takes two keyword arguments, like so:\n\n\n/api//customers//\n\n\n\nThis cannot be represented with the default implementation, which accepts only a single lookup field.\n\n\nIn this case we'd need to override \nHyperlinkedRelatedField\n to get the behavior we want:\n\n\nfrom rest_framework import serializers\nfrom rest_framework.reverse import reverse\n\nclass CustomerHyperlink(serializers.HyperlinkedRelatedField):\n # We define these as class attributes, so we don't need to pass them as arguments.\n view_name = 'customer-detail'\n queryset = Customer.objects.all()\n\n def get_url(self, obj, view_name, request, format):\n url_kwargs = {\n 'organization_slug': obj.organization.slug,\n 'customer_pk': obj.pk\n }\n return reverse(view_name, kwargs=url_kwargs, request=request, format=format)\n\n def get_object(self, view_name, view_args, view_kwargs):\n lookup_kwargs = {\n 'organization__slug': view_kwargs['organization_slug'],\n 'pk': view_kwargs['customer_pk']\n }\n return self.get_queryset().get(**lookup_kwargs)\n\n\n\nNote that if you wanted to use this style together with the generic views then you'd also need to override \n.get_object\n on the view in order to get the correct lookup behavior.\n\n\nGenerally we recommend a flat style for API representations where possible, but the nested URL style can also be reasonable when used in moderation.\n\n\n\n\nFurther notes\n\n\nThe \nqueryset\n argument\n\n\nThe \nqueryset\n argument is only ever required for \nwritable\n relationship field, in which case it is used for performing the model instance lookup, that maps from the primitive user input, into a model instance.\n\n\nIn version 2.x a serializer class could \nsometimes\n automatically determine the \nqueryset\n argument \nif\n a \nModelSerializer\n class was being used.\n\n\nThis behavior is now replaced with \nalways\n using an explicit \nqueryset\n argument for writable relational fields.\n\n\nDoing so reduces the amount of hidden 'magic' that \nModelSerializer\n provides, makes the behavior of the field more clear, and ensures that it is trivial to move between using the \nModelSerializer\n shortcut, or using fully explicit \nSerializer\n classes.\n\n\nCustomizing the HTML display\n\n\nThe built-in \n__str__\n method of the model will be used to generate string representations of the objects used to populate the \nchoices\n property. These choices are used to populate select HTML inputs in the browsable API.\n\n\nTo provide customized representations for such inputs, override \ndisplay_value()\n of a \nRelatedField\n subclass. This method will receive a model object, and should return a string suitable for representing it. For example:\n\n\nclass TrackPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):\n def display_value(self, instance):\n return 'Track: %s' % (instance.title)\n\n\n\nSelect field cutoffs\n\n\nWhen rendered in the browsable API relational fields will default to only displaying a maximum of 1000 selectable items. If more items are present then a disabled option with \"More than 1000 items\u2026\" will be displayed.\n\n\nThis behavior is intended to prevent a template from being unable to render in an acceptable timespan due to a very large number of relationships being displayed.\n\n\nThere are two keyword arguments you can use to control this behavior:\n\n\n\n\nhtml_cutoff\n - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Set to \nNone\n to disable any limiting. Defaults to \n1000\n.\n\n\nhtml_cutoff_text\n - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to \n\"More than {count} items\u2026\"\n\n\n\n\nYou can also control these globally using the settings \nHTML_SELECT_CUTOFF\n and \nHTML_SELECT_CUTOFF_TEXT\n.\n\n\nIn cases where the cutoff is being enforced you may want to instead use a plain input field in the HTML form. You can do so using the \nstyle\n keyword argument. For example:\n\n\nassigned_to = serializers.SlugRelatedField(\n queryset=User.objects.all(),\n slug_field='username',\n style={'base_template': 'input.html'}\n)\n\n\n\nReverse relations\n\n\nNote that reverse relationships are not automatically included by the \nModelSerializer\n and \nHyperlinkedModelSerializer\n classes. To include a reverse relationship, you must explicitly add it to the fields list. For example:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n class Meta:\n fields = ('tracks', ...)\n\n\n\nYou'll normally want to ensure that you've set an appropriate \nrelated_name\n argument on the relationship, that you can use as the field name. For example:\n\n\nclass Track(models.Model):\n album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)\n ...\n\n\n\nIf you have not set a related name for the reverse relationship, you'll need to use the automatically generated related name in the \nfields\n argument. For example:\n\n\nclass AlbumSerializer(serializers.ModelSerializer):\n class Meta:\n fields = ('track_set', ...)\n\n\n\nSee the Django documentation on \nreverse relationships\n for more details.\n\n\nGeneric relationships\n\n\nIf you want to serialize a generic foreign key, you need to define a custom field, to determine explicitly how you want to serialize the targets of the relationship.\n\n\nFor example, given the following model for a tag, which has a generic relationship with other arbitrary models:\n\n\nclass TaggedItem(models.Model):\n \"\"\"\n Tags arbitrary model instances using a generic relation.\n\n See: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/\n \"\"\"\n tag_name = models.SlugField()\n content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)\n object_id = models.PositiveIntegerField()\n tagged_object = GenericForeignKey('content_type', 'object_id')\n\n def __unicode__(self):\n return self.tag_name\n\n\n\nAnd the following two models, which may have associated tags:\n\n\nclass Bookmark(models.Model):\n \"\"\"\n A bookmark consists of a URL, and 0 or more descriptive tags.\n \"\"\"\n url = models.URLField()\n tags = GenericRelation(TaggedItem)\n\n\nclass Note(models.Model):\n \"\"\"\n A note consists of some text, and 0 or more descriptive tags.\n \"\"\"\n text = models.CharField(max_length=1000)\n tags = GenericRelation(TaggedItem)\n\n\n\nWe could define a custom field that could be used to serialize tagged instances, using the type of each instance to determine how it should be serialized.\n\n\nclass TaggedObjectRelatedField(serializers.RelatedField):\n \"\"\"\n A custom field to use for the `tagged_object` generic relationship.\n \"\"\"\n\n def to_representation(self, value):\n \"\"\"\n Serialize tagged objects to a simple textual representation.\n \"\"\"\n if isinstance(value, Bookmark):\n return 'Bookmark: ' + value.url\n elif isinstance(value, Note):\n return 'Note: ' + value.text\n raise Exception('Unexpected type of tagged object')\n\n\n\nIf you need the target of the relationship to have a nested representation, you can use the required serializers inside the \n.to_representation()\n method:\n\n\n def to_representation(self, value):\n \"\"\"\n Serialize bookmark instances using a bookmark serializer,\n and note instances using a note serializer.\n \"\"\"\n if isinstance(value, Bookmark):\n serializer = BookmarkSerializer(value)\n elif isinstance(value, Note):\n serializer = NoteSerializer(value)\n else:\n raise Exception('Unexpected type of tagged object')\n\n return serializer.data\n\n\n\nNote that reverse generic keys, expressed using the \nGenericRelation\n field, can be serialized using the regular relational field types, since the type of the target in the relationship is always known.\n\n\nFor more information see \nthe Django documentation on generic relations\n.\n\n\nManyToManyFields with a Through Model\n\n\nBy default, relational fields that target a \nManyToManyField\n with a\n\nthrough\n model specified are set to read-only.\n\n\nIf you explicitly specify a relational field pointing to a\n\nManyToManyField\n with a through model, be sure to set \nread_only\n\nto \nTrue\n.\n\n\n\n\nThird Party Packages\n\n\nThe following third party packages are also available.\n\n\nDRF Nested Routers\n\n\nThe \ndrf-nested-routers package\n provides routers and relationship fields for working with nested resources.\n\n\nRest Framework Generic Relations\n\n\nThe \nrest-framework-generic-relations\n library provides read/write serialization for generic foreign keys.", "title": "Serializer relations" }, { "location": "/api-guide/relations/#serializer-relations", - "text": "Bad programmers worry about the code.\nGood programmers worry about data structures and their relationships. \u2014 Linus Torvalds Relational fields are used to represent model relationships. They can be applied to ForeignKey , ManyToManyField and OneToOneField relationships, as well as to reverse relationships, and custom relationships such as GenericForeignKey . Note: The relational fields are declared in relations.py , but by convention you should import them from the serializers module, using from rest_framework import serializers and refer to fields as serializers. .", + "text": "Data structures, not algorithms, are central to programming. \u2014 Rob Pike Relational fields are used to represent model relationships. They can be applied to ForeignKey , ManyToManyField and OneToOneField relationships, as well as to reverse relationships, and custom relationships such as GenericForeignKey . Note: The relational fields are declared in relations.py , but by convention you should import them from the serializers module, using from rest_framework import serializers and refer to fields as serializers. .", "title": "Serializer relations" }, { "location": "/api-guide/relations/#inspecting-relationships", - "text": "When using the ModelSerializer class, serializer fields and relationships will be automatically generated for you. Inspecting these automatically generated fields can be a useful tool for determining how to customize the relationship style. To do so, open the Django shell, using python manage.py shell , then import the serializer class, instantiate it, and print the object representation\u2026 >>> from myapp.serializers import AccountSerializer\n>>> serializer = AccountSerializer()\n>>> print repr(serializer) # Or `print(repr(serializer))` in Python 3.x.\nAccountSerializer():\n id = IntegerField(label='ID', read_only=True)\n name = CharField(allow_blank=True, max_length=100, required=False)\n owner = PrimaryKeyRelatedField(queryset=User.objects.all())", + "text": "When using the ModelSerializer class, serializer fields and relationships will be automatically generated for you. Inspecting these automatically generated fields can be a useful tool for determining how to customize the relationship style. To do so, open the Django shell, using python manage.py shell , then import the serializer class, instantiate it, and print the object representation\u2026 >>> from myapp.serializers import AccountSerializer\n>>> serializer = AccountSerializer()\n>>> print(repr(serializer))\nAccountSerializer():\n id = IntegerField(label='ID', read_only=True)\n name = CharField(allow_blank=True, max_length=100, required=False)\n owner = PrimaryKeyRelatedField(queryset=User.objects.all())", "title": "Inspecting relationships." }, { @@ -2512,7 +2512,7 @@ }, { "location": "/api-guide/permissions/", - "text": "Permissions\n\n\n\n\nAuthentication or identification by itself is not usually sufficient to gain access to information or code. For that, the entity requesting access must have authorization.\n\n\n\u2014 \nApple Developer Documentation\n\n\n\n\nTogether with \nauthentication\n and \nthrottling\n, permissions determine whether a request should be granted or denied access.\n\n\nPermission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the \nrequest.user\n and \nrequest.auth\n properties to determine if the incoming request should be permitted.\n\n\nPermissions are used to grant or deny access different classes of users to different parts of the API.\n\n\nThe simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds the \nIsAuthenticated\n class in REST framework.\n\n\nA slightly less strict style of permission would be to allow full access to authenticated users, but allow read-only access to unauthenticated users. This corresponds to the \nIsAuthenticatedOrReadOnly\n class in REST framework.\n\n\nHow permissions are determined\n\n\nPermissions in REST framework are always defined as a list of permission classes.\n\n\nBefore running the main body of the view each permission in the list is checked.\nIf any permission check fails an \nexceptions.PermissionDenied\n or \nexceptions.NotAuthenticated\n exception will be raised, and the main body of the view will not run.\n\n\nWhen the permissions checks fail either a \"403 Forbidden\" or a \"401 Unauthorized\" response will be returned, according to the following rules:\n\n\n\n\nThe request was successfully authenticated, but permission was denied. \n\u2014 An HTTP 403 Forbidden response will be returned.\n\n\nThe request was not successfully authenticated, and the highest priority authentication class \ndoes not\n use \nWWW-Authenticate\n headers. \n\u2014 An HTTP 403 Forbidden response will be returned.\n\n\nThe request was not successfully authenticated, and the highest priority authentication class \ndoes\n use \nWWW-Authenticate\n headers. \n\u2014 An HTTP 401 Unauthorized response, with an appropriate \nWWW-Authenticate\n header will be returned.\n\n\n\n\nObject level permissions\n\n\nREST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.\n\n\nObject level permissions are run by REST framework's generic views when \n.get_object()\n is called.\nAs with view level permissions, an \nexceptions.PermissionDenied\n exception will be raised if the user is not allowed to act on the given object.\n\n\nIf you're writing your own views and want to enforce object level permissions,\nor if you override the \nget_object\n method on a generic view, then you'll need to explicitly call the \n.check_object_permissions(request, obj)\n method on the view at the point at which you've retrieved the object.\n\n\nThis will either raise a \nPermissionDenied\n or \nNotAuthenticated\n exception, or simply return if the view has the appropriate permissions.\n\n\nFor example:\n\n\ndef get_object(self):\n obj = get_object_or_404(self.get_queryset(), pk=self.kwargs[\"pk\"])\n self.check_object_permissions(self.request, obj)\n return obj\n\n\n\nLimitations of object level permissions\n\n\nFor performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.\n\n\nOften when you're using object level permissions you'll also want to \nfilter the queryset\n appropriately, to ensure that users only have visibility onto instances that they are permitted to view.\n\n\nSetting the permission policy\n\n\nThe default permission policy may be set globally, using the \nDEFAULT_PERMISSION_CLASSES\n setting. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PERMISSION_CLASSES': (\n 'rest_framework.permissions.IsAuthenticated',\n )\n}\n\n\n\nIf not specified, this setting defaults to allowing unrestricted access:\n\n\n'DEFAULT_PERMISSION_CLASSES': (\n 'rest_framework.permissions.AllowAny',\n)\n\n\n\nYou can also set the authentication policy on a per-view, or per-viewset basis,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n permission_classes = (IsAuthenticated,)\n\n def get(self, request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content)\n\n\n\nOr, if you're using the \n@api_view\n decorator with function based views.\n\n\nfrom rest_framework.decorators import api_view, permission_classes\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\n\n@api_view(['GET'])\n@permission_classes((IsAuthenticated, ))\ndef example_view(request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content)\n\n\n\nNote:\n when you set new permission classes through class attribute or decorators you're telling the view to ignore the default list set over the \nsettings.py\n file.\n\n\nProvided they inherit from \nrest_framework.permissions.BasePermission\n, permissions can be composed using standard Python bitwise operators. For example, \nIsAuthenticatedOrReadOnly\n could be written:\n\n\nfrom rest_framework.permissions import BasePermission, IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ReadOnly(BasePermission):\n def has_permission(self, request, view):\n return request.method in SAFE_METHODS\n\nclass ExampleView(APIView):\n permission_classes = (IsAuthenticated|ReadOnly,)\n\n def get(self, request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content)\n\n\n\nNote:\n it only supports & -and- and | -or-.\n\n\n\n\nAPI Reference\n\n\nAllowAny\n\n\nThe \nAllowAny\n permission class will allow unrestricted access, \nregardless of if the request was authenticated or unauthenticated\n.\n\n\nThis permission is not strictly required, since you can achieve the same result by using an empty list or tuple for the permissions setting, but you may find it useful to specify this class because it makes the intention explicit.\n\n\nIsAuthenticated\n\n\nThe \nIsAuthenticated\n permission class will deny permission to any unauthenticated user, and allow permission otherwise.\n\n\nThis permission is suitable if you want your API to only be accessible to registered users.\n\n\nIsAdminUser\n\n\nThe \nIsAdminUser\n permission class will deny permission to any user, unless \nuser.is_staff\n is \nTrue\n in which case permission will be allowed.\n\n\nThis permission is suitable if you want your API to only be accessible to a subset of trusted administrators.\n\n\nIsAuthenticatedOrReadOnly\n\n\nThe \nIsAuthenticatedOrReadOnly\n will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the \"safe\" methods; \nGET\n, \nHEAD\n or \nOPTIONS\n.\n\n\nThis permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users.\n\n\nDjangoModelPermissions\n\n\nThis permission class ties into Django's standard \ndjango.contrib.auth\n \nmodel permissions\n. This permission must only be applied to views that have a \n.queryset\n property set. Authorization will only be granted if the user \nis authenticated\n and has the \nrelevant model permissions\n assigned.\n\n\n\n\nPOST\n requests require the user to have the \nadd\n permission on the model.\n\n\nPUT\n and \nPATCH\n requests require the user to have the \nchange\n permission on the model.\n\n\nDELETE\n requests require the user to have the \ndelete\n permission on the model.\n\n\n\n\nThe default behaviour can also be overridden to support custom model permissions. For example, you might want to include a \nview\n model permission for \nGET\n requests.\n\n\nTo use custom model permissions, override \nDjangoModelPermissions\n and set the \n.perms_map\n property. Refer to the source code for details.\n\n\nUsing with views that do not include a \nqueryset\n attribute.\n\n\nIf you're using this permission with a view that uses an overridden \nget_queryset()\n method there may not be a \nqueryset\n attribute on the view. In this case we suggest also marking the view with a sentinel queryset, so that this class can determine the required permissions. For example:\n\n\nqueryset = User.objects.none() # Required for DjangoModelPermissions\n\n\n\nDjangoModelPermissionsOrAnonReadOnly\n\n\nSimilar to \nDjangoModelPermissions\n, but also allows unauthenticated users to have read-only access to the API.\n\n\nDjangoObjectPermissions\n\n\nThis permission class ties into Django's standard \nobject permissions framework\n that allows per-object permissions on models. In order to use this permission class, you'll also need to add a permission backend that supports object-level permissions, such as \ndjango-guardian\n.\n\n\nAs with \nDjangoModelPermissions\n, this permission must only be applied to views that have a \n.queryset\n property or \n.get_queryset()\n method. Authorization will only be granted if the user \nis authenticated\n and has the \nrelevant per-object permissions\n and \nrelevant model permissions\n assigned.\n\n\n\n\nPOST\n requests require the user to have the \nadd\n permission on the model instance.\n\n\nPUT\n and \nPATCH\n requests require the user to have the \nchange\n permission on the model instance.\n\n\nDELETE\n requests require the user to have the \ndelete\n permission on the model instance.\n\n\n\n\nNote that \nDjangoObjectPermissions\n \ndoes not\n require the \ndjango-guardian\n package, and should support other object-level backends equally well.\n\n\nAs with \nDjangoModelPermissions\n you can use custom model permissions by overriding \nDjangoObjectPermissions\n and setting the \n.perms_map\n property. Refer to the source code for details.\n\n\n\n\nNote\n: If you need object level \nview\n permissions for \nGET\n, \nHEAD\n and \nOPTIONS\n requests and are using django-guardian for your object-level permissions backend, you'll want to consider using the \nDjangoObjectPermissionsFilter\n class provided by the \ndjangorestframework-guardian\n package\n. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.\n\n\n\n\nCustom permissions\n\n\nTo implement a custom permission, override \nBasePermission\n and implement either, or both, of the following methods:\n\n\n\n\n.has_permission(self, request, view)\n\n\n.has_object_permission(self, request, view, obj)\n\n\n\n\nThe methods should return \nTrue\n if the request should be granted access, and \nFalse\n otherwise.\n\n\nIf you need to test if a request is a read operation or a write operation, you should check the request method against the constant \nSAFE_METHODS\n, which is a tuple containing \n'GET'\n, \n'OPTIONS'\n and \n'HEAD'\n. For example:\n\n\nif request.method in permissions.SAFE_METHODS:\n # Check permissions for read-only request\nelse:\n # Check permissions for write request\n\n\n\n\n\nNote\n: The instance-level \nhas_object_permission\n method will only be called if the view-level \nhas_permission\n checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call \n.check_object_permissions(request, obj)\n. If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising \nPermissionDenied\n on failure.)\n\n\n\n\nCustom permissions will raise a \nPermissionDenied\n exception if the test fails. To change the error message associated with the exception, implement a \nmessage\n attribute directly on your custom permission. Otherwise the \ndefault_detail\n attribute from \nPermissionDenied\n will be used.\n\n\nfrom rest_framework import permissions\n\nclass CustomerAccessPermission(permissions.BasePermission):\n message = 'Adding customers not allowed.'\n\n def has_permission(self, request, view):\n ...\n\n\n\nExamples\n\n\nThe following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted.\n\n\nfrom rest_framework import permissions\n\nclass BlacklistPermission(permissions.BasePermission):\n \"\"\"\n Global permission check for blacklisted IPs.\n \"\"\"\n\n def has_permission(self, request, view):\n ip_addr = request.META['REMOTE_ADDR']\n blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()\n return not blacklisted\n\n\n\nAs well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example:\n\n\nclass IsOwnerOrReadOnly(permissions.BasePermission):\n \"\"\"\n Object-level permission to only allow owners of an object to edit it.\n Assumes the model instance has an `owner` attribute.\n \"\"\"\n\n def has_object_permission(self, request, view, obj):\n # Read permissions are allowed to any request,\n # so we'll always allow GET, HEAD or OPTIONS requests.\n if request.method in permissions.SAFE_METHODS:\n return True\n\n # Instance must have an attribute named `owner`.\n return obj.owner == request.user\n\n\n\nNote that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself. You can do so by calling \nself.check_object_permissions(request, obj)\n from the view once you have the object instance. This call will raise an appropriate \nAPIException\n if any object-level permission checks fail, and will otherwise simply return.\n\n\nAlso note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you'll need to filter the queryset separately. See the \nfiltering documentation\n for more details.\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nComposed Permissions\n\n\nThe \nComposed Permissions\n package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components.\n\n\nREST Condition\n\n\nThe \nREST Condition\n package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.\n\n\nDRY Rest Permissions\n\n\nThe \nDRY Rest Permissions\n package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrieve per user.\n\n\nDjango Rest Framework Roles\n\n\nThe \nDjango Rest Framework Roles\n package makes it easier to parameterize your API over multiple types of users.\n\n\nDjango Rest Framework API Key\n\n\nThe \nDjango Rest Framework API Key\n package allows you to ensure that every request made to the server requires an API key header. You can generate one from the django admin interface.\n\n\nDjango Rest Framework Role Filters\n\n\nThe \nDjango Rest Framework Role Filters\n package provides simple filtering over multiple types of roles.", + "text": "Permissions\n\n\n\n\nAuthentication or identification by itself is not usually sufficient to gain access to information or code. For that, the entity requesting access must have authorization.\n\n\n\u2014 \nApple Developer Documentation\n\n\n\n\nTogether with \nauthentication\n and \nthrottling\n, permissions determine whether a request should be granted or denied access.\n\n\nPermission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the \nrequest.user\n and \nrequest.auth\n properties to determine if the incoming request should be permitted.\n\n\nPermissions are used to grant or deny access different classes of users to different parts of the API.\n\n\nThe simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds the \nIsAuthenticated\n class in REST framework.\n\n\nA slightly less strict style of permission would be to allow full access to authenticated users, but allow read-only access to unauthenticated users. This corresponds to the \nIsAuthenticatedOrReadOnly\n class in REST framework.\n\n\nHow permissions are determined\n\n\nPermissions in REST framework are always defined as a list of permission classes.\n\n\nBefore running the main body of the view each permission in the list is checked.\nIf any permission check fails an \nexceptions.PermissionDenied\n or \nexceptions.NotAuthenticated\n exception will be raised, and the main body of the view will not run.\n\n\nWhen the permissions checks fail either a \"403 Forbidden\" or a \"401 Unauthorized\" response will be returned, according to the following rules:\n\n\n\n\nThe request was successfully authenticated, but permission was denied. \n\u2014 An HTTP 403 Forbidden response will be returned.\n\n\nThe request was not successfully authenticated, and the highest priority authentication class \ndoes not\n use \nWWW-Authenticate\n headers. \n\u2014 An HTTP 403 Forbidden response will be returned.\n\n\nThe request was not successfully authenticated, and the highest priority authentication class \ndoes\n use \nWWW-Authenticate\n headers. \n\u2014 An HTTP 401 Unauthorized response, with an appropriate \nWWW-Authenticate\n header will be returned.\n\n\n\n\nObject level permissions\n\n\nREST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.\n\n\nObject level permissions are run by REST framework's generic views when \n.get_object()\n is called.\nAs with view level permissions, an \nexceptions.PermissionDenied\n exception will be raised if the user is not allowed to act on the given object.\n\n\nIf you're writing your own views and want to enforce object level permissions,\nor if you override the \nget_object\n method on a generic view, then you'll need to explicitly call the \n.check_object_permissions(request, obj)\n method on the view at the point at which you've retrieved the object.\n\n\nThis will either raise a \nPermissionDenied\n or \nNotAuthenticated\n exception, or simply return if the view has the appropriate permissions.\n\n\nFor example:\n\n\ndef get_object(self):\n obj = get_object_or_404(self.get_queryset(), pk=self.kwargs[\"pk\"])\n self.check_object_permissions(self.request, obj)\n return obj\n\n\n\nLimitations of object level permissions\n\n\nFor performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.\n\n\nOften when you're using object level permissions you'll also want to \nfilter the queryset\n appropriately, to ensure that users only have visibility onto instances that they are permitted to view.\n\n\nSetting the permission policy\n\n\nThe default permission policy may be set globally, using the \nDEFAULT_PERMISSION_CLASSES\n setting. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PERMISSION_CLASSES': (\n 'rest_framework.permissions.IsAuthenticated',\n )\n}\n\n\n\nIf not specified, this setting defaults to allowing unrestricted access:\n\n\n'DEFAULT_PERMISSION_CLASSES': (\n 'rest_framework.permissions.AllowAny',\n)\n\n\n\nYou can also set the authentication policy on a per-view, or per-viewset basis,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n permission_classes = (IsAuthenticated,)\n\n def get(self, request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content)\n\n\n\nOr, if you're using the \n@api_view\n decorator with function based views.\n\n\nfrom rest_framework.decorators import api_view, permission_classes\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\n\n@api_view(['GET'])\n@permission_classes((IsAuthenticated, ))\ndef example_view(request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content)\n\n\n\nNote:\n when you set new permission classes through class attribute or decorators you're telling the view to ignore the default list set over the \nsettings.py\n file.\n\n\nProvided they inherit from \nrest_framework.permissions.BasePermission\n, permissions can be composed using standard Python bitwise operators. For example, \nIsAuthenticatedOrReadOnly\n could be written:\n\n\nfrom rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ReadOnly(BasePermission):\n def has_permission(self, request, view):\n return request.method in SAFE_METHODS\n\nclass ExampleView(APIView):\n permission_classes = (IsAuthenticated|ReadOnly,)\n\n def get(self, request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content)\n\n\n\nNote:\n it only supports & -and- and | -or-.\n\n\n\n\nAPI Reference\n\n\nAllowAny\n\n\nThe \nAllowAny\n permission class will allow unrestricted access, \nregardless of if the request was authenticated or unauthenticated\n.\n\n\nThis permission is not strictly required, since you can achieve the same result by using an empty list or tuple for the permissions setting, but you may find it useful to specify this class because it makes the intention explicit.\n\n\nIsAuthenticated\n\n\nThe \nIsAuthenticated\n permission class will deny permission to any unauthenticated user, and allow permission otherwise.\n\n\nThis permission is suitable if you want your API to only be accessible to registered users.\n\n\nIsAdminUser\n\n\nThe \nIsAdminUser\n permission class will deny permission to any user, unless \nuser.is_staff\n is \nTrue\n in which case permission will be allowed.\n\n\nThis permission is suitable if you want your API to only be accessible to a subset of trusted administrators.\n\n\nIsAuthenticatedOrReadOnly\n\n\nThe \nIsAuthenticatedOrReadOnly\n will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the \"safe\" methods; \nGET\n, \nHEAD\n or \nOPTIONS\n.\n\n\nThis permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users.\n\n\nDjangoModelPermissions\n\n\nThis permission class ties into Django's standard \ndjango.contrib.auth\n \nmodel permissions\n. This permission must only be applied to views that have a \n.queryset\n property set. Authorization will only be granted if the user \nis authenticated\n and has the \nrelevant model permissions\n assigned.\n\n\n\n\nPOST\n requests require the user to have the \nadd\n permission on the model.\n\n\nPUT\n and \nPATCH\n requests require the user to have the \nchange\n permission on the model.\n\n\nDELETE\n requests require the user to have the \ndelete\n permission on the model.\n\n\n\n\nThe default behaviour can also be overridden to support custom model permissions. For example, you might want to include a \nview\n model permission for \nGET\n requests.\n\n\nTo use custom model permissions, override \nDjangoModelPermissions\n and set the \n.perms_map\n property. Refer to the source code for details.\n\n\nUsing with views that do not include a \nqueryset\n attribute.\n\n\nIf you're using this permission with a view that uses an overridden \nget_queryset()\n method there may not be a \nqueryset\n attribute on the view. In this case we suggest also marking the view with a sentinel queryset, so that this class can determine the required permissions. For example:\n\n\nqueryset = User.objects.none() # Required for DjangoModelPermissions\n\n\n\nDjangoModelPermissionsOrAnonReadOnly\n\n\nSimilar to \nDjangoModelPermissions\n, but also allows unauthenticated users to have read-only access to the API.\n\n\nDjangoObjectPermissions\n\n\nThis permission class ties into Django's standard \nobject permissions framework\n that allows per-object permissions on models. In order to use this permission class, you'll also need to add a permission backend that supports object-level permissions, such as \ndjango-guardian\n.\n\n\nAs with \nDjangoModelPermissions\n, this permission must only be applied to views that have a \n.queryset\n property or \n.get_queryset()\n method. Authorization will only be granted if the user \nis authenticated\n and has the \nrelevant per-object permissions\n and \nrelevant model permissions\n assigned.\n\n\n\n\nPOST\n requests require the user to have the \nadd\n permission on the model instance.\n\n\nPUT\n and \nPATCH\n requests require the user to have the \nchange\n permission on the model instance.\n\n\nDELETE\n requests require the user to have the \ndelete\n permission on the model instance.\n\n\n\n\nNote that \nDjangoObjectPermissions\n \ndoes not\n require the \ndjango-guardian\n package, and should support other object-level backends equally well.\n\n\nAs with \nDjangoModelPermissions\n you can use custom model permissions by overriding \nDjangoObjectPermissions\n and setting the \n.perms_map\n property. Refer to the source code for details.\n\n\n\n\nNote\n: If you need object level \nview\n permissions for \nGET\n, \nHEAD\n and \nOPTIONS\n requests and are using django-guardian for your object-level permissions backend, you'll want to consider using the \nDjangoObjectPermissionsFilter\n class provided by the \ndjangorestframework-guardian\n package\n. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.\n\n\n\n\nCustom permissions\n\n\nTo implement a custom permission, override \nBasePermission\n and implement either, or both, of the following methods:\n\n\n\n\n.has_permission(self, request, view)\n\n\n.has_object_permission(self, request, view, obj)\n\n\n\n\nThe methods should return \nTrue\n if the request should be granted access, and \nFalse\n otherwise.\n\n\nIf you need to test if a request is a read operation or a write operation, you should check the request method against the constant \nSAFE_METHODS\n, which is a tuple containing \n'GET'\n, \n'OPTIONS'\n and \n'HEAD'\n. For example:\n\n\nif request.method in permissions.SAFE_METHODS:\n # Check permissions for read-only request\nelse:\n # Check permissions for write request\n\n\n\n\n\nNote\n: The instance-level \nhas_object_permission\n method will only be called if the view-level \nhas_permission\n checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call \n.check_object_permissions(request, obj)\n. If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising \nPermissionDenied\n on failure.)\n\n\n\n\nCustom permissions will raise a \nPermissionDenied\n exception if the test fails. To change the error message associated with the exception, implement a \nmessage\n attribute directly on your custom permission. Otherwise the \ndefault_detail\n attribute from \nPermissionDenied\n will be used.\n\n\nfrom rest_framework import permissions\n\nclass CustomerAccessPermission(permissions.BasePermission):\n message = 'Adding customers not allowed.'\n\n def has_permission(self, request, view):\n ...\n\n\n\nExamples\n\n\nThe following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted.\n\n\nfrom rest_framework import permissions\n\nclass BlacklistPermission(permissions.BasePermission):\n \"\"\"\n Global permission check for blacklisted IPs.\n \"\"\"\n\n def has_permission(self, request, view):\n ip_addr = request.META['REMOTE_ADDR']\n blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()\n return not blacklisted\n\n\n\nAs well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example:\n\n\nclass IsOwnerOrReadOnly(permissions.BasePermission):\n \"\"\"\n Object-level permission to only allow owners of an object to edit it.\n Assumes the model instance has an `owner` attribute.\n \"\"\"\n\n def has_object_permission(self, request, view, obj):\n # Read permissions are allowed to any request,\n # so we'll always allow GET, HEAD or OPTIONS requests.\n if request.method in permissions.SAFE_METHODS:\n return True\n\n # Instance must have an attribute named `owner`.\n return obj.owner == request.user\n\n\n\nNote that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself. You can do so by calling \nself.check_object_permissions(request, obj)\n from the view once you have the object instance. This call will raise an appropriate \nAPIException\n if any object-level permission checks fail, and will otherwise simply return.\n\n\nAlso note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you'll need to filter the queryset separately. See the \nfiltering documentation\n for more details.\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nComposed Permissions\n\n\nThe \nComposed Permissions\n package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components.\n\n\nREST Condition\n\n\nThe \nREST Condition\n package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.\n\n\nDRY Rest Permissions\n\n\nThe \nDRY Rest Permissions\n package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrieve per user.\n\n\nDjango Rest Framework Roles\n\n\nThe \nDjango Rest Framework Roles\n package makes it easier to parameterize your API over multiple types of users.\n\n\nDjango Rest Framework API Key\n\n\nThe \nDjango Rest Framework API Key\n package allows you to ensure that every request made to the server requires an API key header. You can generate one from the django admin interface.\n\n\nDjango Rest Framework Role Filters\n\n\nThe \nDjango Rest Framework Role Filters\n package provides simple filtering over multiple types of roles.", "title": "Permissions" }, { @@ -2537,7 +2537,7 @@ }, { "location": "/api-guide/permissions/#setting-the-permission-policy", - "text": "The default permission policy may be set globally, using the DEFAULT_PERMISSION_CLASSES setting. For example. REST_FRAMEWORK = {\n 'DEFAULT_PERMISSION_CLASSES': (\n 'rest_framework.permissions.IsAuthenticated',\n )\n} If not specified, this setting defaults to allowing unrestricted access: 'DEFAULT_PERMISSION_CLASSES': (\n 'rest_framework.permissions.AllowAny',\n) You can also set the authentication policy on a per-view, or per-viewset basis,\nusing the APIView class-based views. from rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n permission_classes = (IsAuthenticated,)\n\n def get(self, request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content) Or, if you're using the @api_view decorator with function based views. from rest_framework.decorators import api_view, permission_classes\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\n\n@api_view(['GET'])\n@permission_classes((IsAuthenticated, ))\ndef example_view(request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content) Note: when you set new permission classes through class attribute or decorators you're telling the view to ignore the default list set over the settings.py file. Provided they inherit from rest_framework.permissions.BasePermission , permissions can be composed using standard Python bitwise operators. For example, IsAuthenticatedOrReadOnly could be written: from rest_framework.permissions import BasePermission, IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ReadOnly(BasePermission):\n def has_permission(self, request, view):\n return request.method in SAFE_METHODS\n\nclass ExampleView(APIView):\n permission_classes = (IsAuthenticated|ReadOnly,)\n\n def get(self, request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content) Note: it only supports & -and- and | -or-.", + "text": "The default permission policy may be set globally, using the DEFAULT_PERMISSION_CLASSES setting. For example. REST_FRAMEWORK = {\n 'DEFAULT_PERMISSION_CLASSES': (\n 'rest_framework.permissions.IsAuthenticated',\n )\n} If not specified, this setting defaults to allowing unrestricted access: 'DEFAULT_PERMISSION_CLASSES': (\n 'rest_framework.permissions.AllowAny',\n) You can also set the authentication policy on a per-view, or per-viewset basis,\nusing the APIView class-based views. from rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n permission_classes = (IsAuthenticated,)\n\n def get(self, request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content) Or, if you're using the @api_view decorator with function based views. from rest_framework.decorators import api_view, permission_classes\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\n\n@api_view(['GET'])\n@permission_classes((IsAuthenticated, ))\ndef example_view(request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content) Note: when you set new permission classes through class attribute or decorators you're telling the view to ignore the default list set over the settings.py file. Provided they inherit from rest_framework.permissions.BasePermission , permissions can be composed using standard Python bitwise operators. For example, IsAuthenticatedOrReadOnly could be written: from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ReadOnly(BasePermission):\n def has_permission(self, request, view):\n return request.method in SAFE_METHODS\n\nclass ExampleView(APIView):\n permission_classes = (IsAuthenticated|ReadOnly,)\n\n def get(self, request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content) Note: it only supports & -and- and | -or-.", "title": "Setting the permission policy" }, { @@ -2607,7 +2607,7 @@ }, { "location": "/api-guide/permissions/#rest-condition", - "text": "The REST Condition package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.", + "text": "The REST Condition package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.", "title": "REST Condition" }, { @@ -3117,7 +3117,7 @@ }, { "location": "/api-guide/schemas/", - "text": "Schemas\n\n\n\n\nA machine-readable [schema] describes what resources are available via the API, what their URLs are, how they are represented and what operations they support.\n\n\n\u2014 Heroku, \nJSON Schema for the Heroku Platform API\n\n\n\n\nAPI schemas are a useful tool that allow for a range of use cases, including\ngenerating reference documentation, or driving dynamic client libraries that\ncan interact with your API.\n\n\nInstall Core API & PyYAML\n\n\nYou'll need to install the \ncoreapi\n package in order to add schema support\nfor REST framework. You probably also want to install \npyyaml\n, so that you\ncan render the schema into the commonly used YAML-based OpenAPI format.\n\n\npip install coreapi pyyaml\n\n\n\nQuickstart\n\n\nThere are two different ways you can serve a schema description for you API.\n\n\nGenerating a schema with the \ngenerateschema\n management command\n\n\nTo generate a static API schema, use the \ngenerateschema\n management command.\n\n\n$ python manage.py generateschema > schema.yml\n\n\n\n\nOnce you've generated a schema in this way you can annotate it with any\nadditional information that cannot be automatically inferred by the schema\ngenerator.\n\n\nYou might want to check your API schema into version control and update it\nwith each new release, or serve the API schema from your site's static media.\n\n\nAdding a view with \nget_schema_view\n\n\nTo add a dynamically generated schema view to your API, use \nget_schema_view\n.\n\n\nfrom rest_framework.schemas import get_schema_view\n\nschema_view = get_schema_view(title=\"Example API\")\n\nurlpatterns = [\n url('^schema$', schema_view),\n ...\n]\n\n\n\n\nSee below \nfor more details\n on customizing a\ndynamically generated schema view.\n\n\nInternal schema representation\n\n\nREST framework uses \nCore API\n in order to model schema information in\na format-independent representation. This information can then be rendered\ninto various different schema formats, or used to generate API documentation.\n\n\nWhen using Core API, a schema is represented as a \nDocument\n which is the\ntop-level container object for information about the API. Available API\ninteractions are represented using \nLink\n objects. Each link includes a URL,\nHTTP method, and may include a list of \nField\n instances, which describe any\nparameters that may be accepted by the API endpoint. The \nLink\n and \nField\n\ninstances may also include descriptions, that allow an API schema to be\nrendered into user documentation.\n\n\nHere's an example of an API description that includes a single \nsearch\n\nendpoint:\n\n\ncoreapi.Document(\n title='Flight Search API',\n url='https://api.example.org/',\n content={\n 'search': coreapi.Link(\n url='/search/',\n action='get',\n fields=[\n coreapi.Field(\n name='from',\n required=True,\n location='query',\n description='City name or airport code.'\n ),\n coreapi.Field(\n name='to',\n required=True,\n location='query',\n description='City name or airport code.'\n ),\n coreapi.Field(\n name='date',\n required=True,\n location='query',\n description='Flight date in \"YYYY-MM-DD\" format.'\n )\n ],\n description='Return flight availability and prices.'\n )\n }\n)\n\n\n\nSchema output formats\n\n\nIn order to be presented in an HTTP response, the internal representation\nhas to be rendered into the actual bytes that are used in the response.\n\n\nREST framework includes a few different renderers that you can use for\nencoding the API schema.\n\n\n\n\nrenderers.OpenAPIRenderer\n - Renders into YAML-based [OpenAPI][openapi], the most widely used API schema format.\n\n\nrenderers.JSONOpenAPIRenderer\n - Renders into JSON-based [OpenAPI][openapi].\n\n\nrenderers.CoreJSONRenderer\n - Renders into \nCore JSON\n, a format designed for\nuse with the \ncoreapi\n client library.\n\n\n\n\nCore JSON\n is designed as a canonical format for use with Core API.\nREST framework includes a renderer class for handling this media type, which\nis available as \nrenderers.CoreJSONRenderer\n.\n\n\nSchemas vs Hypermedia\n\n\nIt's worth pointing out here that Core API can also be used to model hypermedia\nresponses, which present an alternative interaction style to API schemas.\n\n\nWith an API schema, the entire available interface is presented up-front\nas a single endpoint. Responses to individual API endpoints are then typically\npresented as plain data, without any further interactions contained in each\nresponse.\n\n\nWith Hypermedia, the client is instead presented with a document containing\nboth data and available interactions. Each interaction results in a new\ndocument, detailing both the current state and the available interactions.\n\n\nFurther information and support on building Hypermedia APIs with REST framework\nis planned for a future version.\n\n\n\n\nCreating a schema\n\n\nREST framework includes functionality for auto-generating a schema,\nor allows you to specify one explicitly.\n\n\nManual Schema Specification\n\n\nTo manually specify a schema you create a Core API \nDocument\n, similar to the\nexample above.\n\n\nschema = coreapi.Document(\n title='Flight Search API',\n content={\n ...\n }\n)\n\n\n\nAutomatic Schema Generation\n\n\nAutomatic schema generation is provided by the \nSchemaGenerator\n class.\n\n\nSchemaGenerator\n processes a list of routed URL patterns and compiles the\nappropriately structured Core API Document.\n\n\nBasic usage is just to provide the title for your schema and call\n\nget_schema()\n:\n\n\ngenerator = schemas.SchemaGenerator(title='Flight Search API')\nschema = generator.get_schema()\n\n\n\nPer-View Schema Customisation\n\n\nBy default, view introspection is performed by an \nAutoSchema\n instance\naccessible via the \nschema\n attribute on \nAPIView\n. This provides the\nappropriate Core API \nLink\n object for the view, request method and path:\n\n\nauto_schema = view.schema\ncoreapi_link = auto_schema.get_link(...)\n\n\n\n(In compiling the schema, \nSchemaGenerator\n calls \nview.schema.get_link()\n for\neach view, allowed method and path.)\n\n\n\n\nNote\n: For basic \nAPIView\n subclasses, default introspection is essentially\nlimited to the URL kwarg path parameters. For \nGenericAPIView\n\nsubclasses, which includes all the provided class based views, \nAutoSchema\n will\nattempt to introspect serialiser, pagination and filter fields, as well as\nprovide richer path field descriptions. (The key hooks here are the relevant\n\nGenericAPIView\n attributes and methods: \nget_serializer\n, \npagination_class\n,\n\nfilter_backends\n and so on.)\n\n\n\n\nTo customise the \nLink\n generation you may:\n\n\n\n\n\n\nInstantiate \nAutoSchema\n on your view with the \nmanual_fields\n kwarg:\n\n\nfrom rest_framework.views import APIView\nfrom rest_framework.schemas import AutoSchema\n\nclass CustomView(APIView):\n ...\n schema = AutoSchema(\n manual_fields=[\n coreapi.Field(\"extra_field\", ...),\n ]\n )\n\n\n\nThis allows extension for the most common case without subclassing.\n\n\n\n\n\n\nProvide an \nAutoSchema\n subclass with more complex customisation:\n\n\nfrom rest_framework.views import APIView\nfrom rest_framework.schemas import AutoSchema\n\nclass CustomSchema(AutoSchema):\n def get_link(...):\n # Implement custom introspection here (or in other sub-methods)\n\nclass CustomView(APIView):\n ...\n schema = CustomSchema()\n\n\n\nThis provides complete control over view introspection.\n\n\n\n\n\n\nInstantiate \nManualSchema\n on your view, providing the Core API \nFields\n for\n the view explicitly:\n\n\nfrom rest_framework.views import APIView\nfrom rest_framework.schemas import ManualSchema\n\nclass CustomView(APIView):\n ...\n schema = ManualSchema(fields=[\n coreapi.Field(\n \"first_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n coreapi.Field(\n \"second_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n ])\n\n\n\nThis allows manually specifying the schema for some views whilst maintaining\nautomatic generation elsewhere.\n\n\n\n\n\n\nYou may disable schema generation for a view by setting \nschema\n to \nNone\n:\n\n\n class CustomView(APIView):\n ...\n schema = None # Will not appear in schema\n\n\n\nThis also applies to extra actions for \nViewSet\ns:\n\n\n class CustomViewSet(viewsets.ModelViewSet):\n\n @action(detail=True, schema=None)\n def extra_action(self, request, pk=None):\n ...\n\n\n\n\n\nNote\n: For full details on \nSchemaGenerator\n plus the \nAutoSchema\n and\n\nManualSchema\n descriptors see the \nAPI Reference below\n.\n\n\n\n\nAdding a schema view\n\n\nThere are a few different ways to add a schema view to your API, depending on\nexactly what you need.\n\n\nThe get_schema_view shortcut\n\n\nThe simplest way to include a schema in your project is to use the\n\nget_schema_view()\n function.\n\n\nfrom rest_framework.schemas import get_schema_view\n\nschema_view = get_schema_view(title=\"Server Monitoring API\")\n\nurlpatterns = [\n url('^$', schema_view),\n ...\n]\n\n\n\nOnce the view has been added, you'll be able to make API requests to retrieve\nthe auto-generated schema definition.\n\n\n$ http http://127.0.0.1:8000/ Accept:application/coreapi+json\nHTTP/1.0 200 OK\nAllow: GET, HEAD, OPTIONS\nContent-Type: application/vnd.coreapi+json\n\n{\n \"_meta\": {\n \"title\": \"Server Monitoring API\"\n },\n \"_type\": \"document\",\n ...\n}\n\n\n\nThe arguments to \nget_schema_view()\n are:\n\n\ntitle\n\n\nMay be used to provide a descriptive title for the schema definition.\n\n\nurl\n\n\nMay be used to pass a canonical URL for the schema.\n\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/'\n)\n\n\n\nurlconf\n\n\nA string representing the import path to the URL conf that you want\nto generate an API schema for. This defaults to the value of Django's\nROOT_URLCONF setting.\n\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n urlconf='myproject.urls'\n)\n\n\n\nrenderer_classes\n\n\nMay be used to pass the set of renderer classes that can be used to render the API root endpoint.\n\n\nfrom rest_framework.schemas import get_schema_view\nfrom rest_framework.renderers import JSONOpenAPIRenderer\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n renderer_classes=[JSONOpenAPIRenderer]\n)\n\n\n\npatterns\n\n\nList of url patterns to limit the schema introspection to. If you only want the \nmyproject.api\n urls\nto be exposed in the schema:\n\n\nschema_url_patterns = [\n url(r'^api/', include('myproject.api.urls')),\n]\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n patterns=schema_url_patterns,\n)\n\n\n\ngenerator_class\n\n\nMay be used to specify a \nSchemaGenerator\n subclass to be passed to the\n\nSchemaView\n.\n\n\nauthentication_classes\n\n\nMay be used to specify the list of authentication classes that will apply to the schema endpoint.\nDefaults to \nsettings.DEFAULT_AUTHENTICATION_CLASSES\n\n\npermission_classes\n\n\nMay be used to specify the list of permission classes that will apply to the schema endpoint.\nDefaults to \nsettings.DEFAULT_PERMISSION_CLASSES\n\n\nUsing an explicit schema view\n\n\nIf you need a little more control than the \nget_schema_view()\n shortcut gives you,\nthen you can use the \nSchemaGenerator\n class directly to auto-generate the\n\nDocument\n instance, and to return that from a view.\n\n\nThis option gives you the flexibility of setting up the schema endpoint\nwith whatever behaviour you want. For example, you can apply different\npermission, throttling, or authentication policies to the schema endpoint.\n\n\nHere's an example of using \nSchemaGenerator\n together with a view to\nreturn the schema.\n\n\nviews.py:\n\n\nfrom rest_framework.decorators import api_view, renderer_classes\nfrom rest_framework import renderers, response, schemas\n\ngenerator = schemas.SchemaGenerator(title='Bookings API')\n\n@api_view()\n@renderer_classes([renderers.OpenAPIRenderer])\ndef schema_view(request):\n schema = generator.get_schema(request)\n return response.Response(schema)\n\n\n\nurls.py:\n\n\nurlpatterns = [\n url('/', schema_view),\n ...\n]\n\n\n\nYou can also serve different schemas to different users, depending on the\npermissions they have available. This approach can be used to ensure that\nunauthenticated requests are presented with a different schema to\nauthenticated requests, or to ensure that different parts of the API are\nmade visible to different users depending on their role.\n\n\nIn order to present a schema with endpoints filtered by user permissions,\nyou need to pass the \nrequest\n argument to the \nget_schema()\n method, like so:\n\n\n@api_view()\n@renderer_classes([renderers.OpenAPIRenderer])\ndef schema_view(request):\n generator = schemas.SchemaGenerator(title='Bookings API')\n return response.Response(generator.get_schema(request=request))\n\n\n\nExplicit schema definition\n\n\nAn alternative to the auto-generated approach is to specify the API schema\nexplicitly, by declaring a \nDocument\n object in your codebase. Doing so is a\nlittle more work, but ensures that you have full control over the schema\nrepresentation.\n\n\nimport coreapi\nfrom rest_framework.decorators import api_view, renderer_classes\nfrom rest_framework import renderers, response\n\nschema = coreapi.Document(\n title='Bookings API',\n content={\n ...\n }\n)\n\n@api_view()\n@renderer_classes([renderers.OpenAPIRenderer])\ndef schema_view(request):\n return response.Response(schema)\n\n\n\n\n\nSchemas as documentation\n\n\nOne common usage of API schemas is to use them to build documentation pages.\n\n\nThe schema generation in REST framework uses docstrings to automatically\npopulate descriptions in the schema document.\n\n\nThese descriptions will be based on:\n\n\n\n\nThe corresponding method docstring if one exists.\n\n\nA named section within the class docstring, which can be either single line or multi-line.\n\n\nThe class docstring.\n\n\n\n\nExamples\n\n\nAn \nAPIView\n, with an explicit method docstring.\n\n\nclass ListUsernames(APIView):\n def get(self, request):\n \"\"\"\n Return a list of all user names in the system.\n \"\"\"\n usernames = [user.username for user in User.objects.all()]\n return Response(usernames)\n\n\n\nA \nViewSet\n, with an explict action docstring.\n\n\nclass ListUsernames(ViewSet):\n def list(self, request):\n \"\"\"\n Return a list of all user names in the system.\n \"\"\"\n usernames = [user.username for user in User.objects.all()]\n return Response(usernames)\n\n\n\nA generic view with sections in the class docstring, using single-line style.\n\n\nclass UserList(generics.ListCreateAPIView):\n \"\"\"\n get: List all the users.\n post: Create a new user.\n \"\"\"\n queryset = User.objects.all()\n serializer_class = UserSerializer\n permission_classes = (IsAdminUser,)\n\n\n\nA generic viewset with sections in the class docstring, using multi-line style.\n\n\nclass UserViewSet(viewsets.ModelViewSet):\n \"\"\"\n API endpoint that allows users to be viewed or edited.\n\n retrieve:\n Return a user instance.\n\n list:\n Return all users, ordered by most recently joined.\n \"\"\"\n queryset = User.objects.all().order_by('-date_joined')\n serializer_class = UserSerializer\n\n\n\n\n\nAPI Reference\n\n\nSchemaGenerator\n\n\nA class that walks a list of routed URL patterns, requests the schema for each view,\nand collates the resulting CoreAPI Document.\n\n\nTypically you'll instantiate \nSchemaGenerator\n with a single argument, like so:\n\n\ngenerator = SchemaGenerator(title='Stock Prices API')\n\n\n\nArguments:\n\n\n\n\ntitle\n \nrequired\n - The name of the API.\n\n\nurl\n - The root URL of the API schema. This option is not required unless the schema is included under path prefix.\n\n\npatterns\n - A list of URLs to inspect when generating the schema. Defaults to the project's URL conf.\n\n\nurlconf\n - A URL conf module name to use when generating the schema. Defaults to \nsettings.ROOT_URLCONF\n.\n\n\n\n\nget_schema(self, request)\n\n\nReturns a \ncoreapi.Document\n instance that represents the API schema.\n\n\n@api_view\n@renderer_classes([renderers.OpenAPIRenderer])\ndef schema_view(request):\n generator = schemas.SchemaGenerator(title='Bookings API')\n return Response(generator.get_schema())\n\n\n\nThe \nrequest\n argument is optional, and may be used if you want to apply per-user\npermissions to the resulting schema generation.\n\n\nget_links(self, request)\n\n\nReturn a nested dictionary containing all the links that should be included in the API schema.\n\n\nThis is a good point to override if you want to modify the resulting structure of the generated schema,\nas you can build a new dictionary with a different layout.\n\n\nAutoSchema\n\n\nA class that deals with introspection of individual views for schema generation.\n\n\nAutoSchema\n is attached to \nAPIView\n via the \nschema\n attribute.\n\n\nThe \nAutoSchema\n constructor takes a single keyword argument \nmanual_fields\n.\n\n\nmanual_fields\n: a \nlist\n of \ncoreapi.Field\n instances that will be added to\nthe generated fields. Generated fields with a matching \nname\n will be overwritten.\n\n\nclass CustomView(APIView):\n schema = AutoSchema(manual_fields=[\n coreapi.Field(\n \"my_extra_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n ])\n\n\n\nFor more advanced customisation subclass \nAutoSchema\n to customise schema generation.\n\n\nclass CustomViewSchema(AutoSchema):\n \"\"\"\n Overrides `get_link()` to provide Custom Behavior X\n \"\"\"\n\n def get_link(self, path, method, base_url):\n link = super().get_link(path, method, base_url)\n # Do something to customize link here...\n return link\n\nclass MyView(APIView):\n schema = CustomViewSchema()\n\n\n\nThe following methods are available to override.\n\n\nget_link(self, path, method, base_url)\n\n\nReturns a \ncoreapi.Link\n instance corresponding to the given view.\n\n\nThis is the main entry point.\nYou can override this if you need to provide custom behaviors for particular views.\n\n\nget_description(self, path, method)\n\n\nReturns a string to use as the link description. By default this is based on the\nview docstring as described in the \"Schemas as Documentation\" section above.\n\n\nget_encoding(self, path, method)\n\n\nReturns a string to indicate the encoding for any request body, when interacting\nwith the given view. Eg. \n'application/json'\n. May return a blank string for views\nthat do not expect a request body.\n\n\nget_path_fields(self, path, method):\n\n\nReturn a list of \ncoreapi.Field()\n instances. One for each path parameter in the URL.\n\n\nget_serializer_fields(self, path, method)\n\n\nReturn a list of \ncoreapi.Field()\n instances. One for each field in the serializer class used by the view.\n\n\nget_pagination_fields(self, path, method)\n\n\nReturn a list of \ncoreapi.Field()\n instances, as returned by the \nget_schema_fields()\n method on any pagination class used by the view.\n\n\nget_filter_fields(self, path, method)\n\n\nReturn a list of \ncoreapi.Field()\n instances, as returned by the \nget_schema_fields()\n method of any filter classes used by the view.\n\n\nget_manual_fields(self, path, method)\n\n\nReturn a list of \ncoreapi.Field()\n instances to be added to or replace generated fields. Defaults to (optional) \nmanual_fields\n passed to \nAutoSchema\n constructor.\n\n\nMay be overridden to customise manual fields by \npath\n or \nmethod\n. For example, a per-method adjustment may look like this:\n\n\ndef get_manual_fields(self, path, method):\n \"\"\"Example adding per-method fields.\"\"\"\n\n extra_fields = []\n if method=='GET':\n extra_fields = # ... list of extra fields for GET ...\n if method=='POST':\n extra_fields = # ... list of extra fields for POST ...\n\n manual_fields = super().get_manual_fields(path, method)\n return manual_fields + extra_fields\n\n\n\n\nupdate_fields(fields, update_with)\n\n\nUtility \nstaticmethod\n. Encapsulates logic to add or replace fields from a list\nby \nField.name\n. May be overridden to adjust replacement criteria.\n\n\nManualSchema\n\n\nAllows manually providing a list of \ncoreapi.Field\n instances for the schema,\nplus an optional description.\n\n\nclass MyView(APIView):\n schema = ManualSchema(fields=[\n coreapi.Field(\n \"first_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n coreapi.Field(\n \"second_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n ]\n )\n\n\n\nThe \nManualSchema\n constructor takes two arguments:\n\n\nfields\n: A list of \ncoreapi.Field\n instances. Required.\n\n\ndescription\n: A string description. Optional.\n\n\nencoding\n: Default \nNone\n. A string encoding, e.g \napplication/json\n. Optional.\n\n\n\n\nCore API\n\n\nThis documentation gives a brief overview of the components within the \ncoreapi\n\npackage that are used to represent an API schema.\n\n\nNote that these classes are imported from the \ncoreapi\n package, rather than\nfrom the \nrest_framework\n package.\n\n\nDocument\n\n\nRepresents a container for the API schema.\n\n\ntitle\n\n\nA name for the API.\n\n\nurl\n\n\nA canonical URL for the API.\n\n\ncontent\n\n\nA dictionary, containing the \nLink\n objects that the schema contains.\n\n\nIn order to provide more structure to the schema, the \ncontent\n dictionary\nmay be nested, typically to a second level. For example:\n\n\ncontent={\n \"bookings\": {\n \"list\": Link(...),\n \"create\": Link(...),\n ...\n },\n \"venues\": {\n \"list\": Link(...),\n ...\n },\n ...\n}\n\n\n\nLink\n\n\nRepresents an individual API endpoint.\n\n\nurl\n\n\nThe URL of the endpoint. May be a URI template, such as \n/users/{username}/\n.\n\n\naction\n\n\nThe HTTP method associated with the endpoint. Note that URLs that support\nmore than one HTTP method, should correspond to a single \nLink\n for each.\n\n\nfields\n\n\nA list of \nField\n instances, describing the available parameters on the input.\n\n\ndescription\n\n\nA short description of the meaning and intended usage of the endpoint.\n\n\nField\n\n\nRepresents a single input parameter on a given API endpoint.\n\n\nname\n\n\nA descriptive name for the input.\n\n\nrequired\n\n\nA boolean, indicated if the client is required to included a value, or if\nthe parameter can be omitted.\n\n\nlocation\n\n\nDetermines how the information is encoded into the request. Should be one of\nthe following strings:\n\n\n\"path\"\n\n\nIncluded in a templated URI. For example a \nurl\n value of \n/products/{product_code}/\n could be used together with a \n\"path\"\n field, to handle API inputs in a URL path such as \n/products/slim-fit-jeans/\n.\n\n\nThese fields will normally correspond with \nnamed arguments in the project URL conf\n.\n\n\n\"query\"\n\n\nIncluded as a URL query parameter. For example \n?search=sale\n. Typically for \nGET\n requests.\n\n\nThese fields will normally correspond with pagination and filtering controls on a view.\n\n\n\"form\"\n\n\nIncluded in the request body, as a single item of a JSON object or HTML form. For example \n{\"colour\": \"blue\", ...}\n. Typically for \nPOST\n, \nPUT\n and \nPATCH\n requests. Multiple \n\"form\"\n fields may be included on a single link.\n\n\nThese fields will normally correspond with serializer fields on a view.\n\n\n\"body\"\n\n\nIncluded as the complete request body. Typically for \nPOST\n, \nPUT\n and \nPATCH\n requests. No more than one \n\"body\"\n field may exist on a link. May not be used together with \n\"form\"\n fields.\n\n\nThese fields will normally correspond with views that use \nListSerializer\n to validate the request input, or with file upload views.\n\n\nencoding\n\n\n\"application/json\"\n\n\nJSON encoded request content. Corresponds to views using \nJSONParser\n.\nValid only if either one or more \nlocation=\"form\"\n fields, or a single\n\nlocation=\"body\"\n field is included on the \nLink\n.\n\n\n\"multipart/form-data\"\n\n\nMultipart encoded request content. Corresponds to views using \nMultiPartParser\n.\nValid only if one or more \nlocation=\"form\"\n fields is included on the \nLink\n.\n\n\n\"application/x-www-form-urlencoded\"\n\n\nURL encoded request content. Corresponds to views using \nFormParser\n. Valid\nonly if one or more \nlocation=\"form\"\n fields is included on the \nLink\n.\n\n\n\"application/octet-stream\"\n\n\nBinary upload request content. Corresponds to views using \nFileUploadParser\n.\nValid only if a \nlocation=\"body\"\n field is included on the \nLink\n.\n\n\ndescription\n\n\nA short description of the meaning and intended usage of the input field.\n\n\n\n\nThird party packages\n\n\ndrf-yasg - Yet Another Swagger Generator\n\n\ndrf-yasg\n generates \nOpenAPI\n documents suitable for code generation - nested schemas,\nnamed models, response bodies, enum/pattern/min/max validators, form parameters, etc.\n\n\nDRF OpenAPI\n\n\nDRF OpenAPI\n renders the schema generated by Django Rest Framework\nin \nOpenAPI\n format.", + "text": "Schemas\n\n\n\n\nA machine-readable [schema] describes what resources are available via the API, what their URLs are, how they are represented and what operations they support.\n\n\n\u2014 Heroku, \nJSON Schema for the Heroku Platform API\n\n\n\n\nAPI schemas are a useful tool that allow for a range of use cases, including\ngenerating reference documentation, or driving dynamic client libraries that\ncan interact with your API.\n\n\nInstall Core API & PyYAML\n\n\nYou'll need to install the \ncoreapi\n package in order to add schema support\nfor REST framework. You probably also want to install \npyyaml\n, so that you\ncan render the schema into the commonly used YAML-based OpenAPI format.\n\n\npip install coreapi pyyaml\n\n\n\nQuickstart\n\n\nThere are two different ways you can serve a schema description for you API.\n\n\nGenerating a schema with the \ngenerateschema\n management command\n\n\nTo generate a static API schema, use the \ngenerateschema\n management command.\n\n\n$ python manage.py generateschema > schema.yml\n\n\n\n\nOnce you've generated a schema in this way you can annotate it with any\nadditional information that cannot be automatically inferred by the schema\ngenerator.\n\n\nYou might want to check your API schema into version control and update it\nwith each new release, or serve the API schema from your site's static media.\n\n\nAdding a view with \nget_schema_view\n\n\nTo add a dynamically generated schema view to your API, use \nget_schema_view\n.\n\n\nfrom rest_framework.schemas import get_schema_view\n\nschema_view = get_schema_view(title=\"Example API\")\n\nurlpatterns = [\n url('^schema$', schema_view),\n ...\n]\n\n\n\n\nSee below \nfor more details\n on customizing a\ndynamically generated schema view.\n\n\nInternal schema representation\n\n\nREST framework uses \nCore API\n in order to model schema information in\na format-independent representation. This information can then be rendered\ninto various different schema formats, or used to generate API documentation.\n\n\nWhen using Core API, a schema is represented as a \nDocument\n which is the\ntop-level container object for information about the API. Available API\ninteractions are represented using \nLink\n objects. Each link includes a URL,\nHTTP method, and may include a list of \nField\n instances, which describe any\nparameters that may be accepted by the API endpoint. The \nLink\n and \nField\n\ninstances may also include descriptions, that allow an API schema to be\nrendered into user documentation.\n\n\nHere's an example of an API description that includes a single \nsearch\n\nendpoint:\n\n\ncoreapi.Document(\n title='Flight Search API',\n url='https://api.example.org/',\n content={\n 'search': coreapi.Link(\n url='/search/',\n action='get',\n fields=[\n coreapi.Field(\n name='from',\n required=True,\n location='query',\n description='City name or airport code.'\n ),\n coreapi.Field(\n name='to',\n required=True,\n location='query',\n description='City name or airport code.'\n ),\n coreapi.Field(\n name='date',\n required=True,\n location='query',\n description='Flight date in \"YYYY-MM-DD\" format.'\n )\n ],\n description='Return flight availability and prices.'\n )\n }\n)\n\n\n\nSchema output formats\n\n\nIn order to be presented in an HTTP response, the internal representation\nhas to be rendered into the actual bytes that are used in the response.\n\n\nREST framework includes a few different renderers that you can use for\nencoding the API schema.\n\n\n\n\nrenderers.OpenAPIRenderer\n - Renders into YAML-based \nOpenAPI\n, the most widely used API schema format.\n\n\nrenderers.JSONOpenAPIRenderer\n - Renders into JSON-based \nOpenAPI\n.\n\n\nrenderers.CoreJSONRenderer\n - Renders into \nCore JSON\n, a format designed for\nuse with the \ncoreapi\n client library.\n\n\n\n\nCore JSON\n is designed as a canonical format for use with Core API.\nREST framework includes a renderer class for handling this media type, which\nis available as \nrenderers.CoreJSONRenderer\n.\n\n\nSchemas vs Hypermedia\n\n\nIt's worth pointing out here that Core API can also be used to model hypermedia\nresponses, which present an alternative interaction style to API schemas.\n\n\nWith an API schema, the entire available interface is presented up-front\nas a single endpoint. Responses to individual API endpoints are then typically\npresented as plain data, without any further interactions contained in each\nresponse.\n\n\nWith Hypermedia, the client is instead presented with a document containing\nboth data and available interactions. Each interaction results in a new\ndocument, detailing both the current state and the available interactions.\n\n\nFurther information and support on building Hypermedia APIs with REST framework\nis planned for a future version.\n\n\n\n\nCreating a schema\n\n\nREST framework includes functionality for auto-generating a schema,\nor allows you to specify one explicitly.\n\n\nManual Schema Specification\n\n\nTo manually specify a schema you create a Core API \nDocument\n, similar to the\nexample above.\n\n\nschema = coreapi.Document(\n title='Flight Search API',\n content={\n ...\n }\n)\n\n\n\nAutomatic Schema Generation\n\n\nAutomatic schema generation is provided by the \nSchemaGenerator\n class.\n\n\nSchemaGenerator\n processes a list of routed URL patterns and compiles the\nappropriately structured Core API Document.\n\n\nBasic usage is just to provide the title for your schema and call\n\nget_schema()\n:\n\n\ngenerator = schemas.SchemaGenerator(title='Flight Search API')\nschema = generator.get_schema()\n\n\n\nPer-View Schema Customisation\n\n\nBy default, view introspection is performed by an \nAutoSchema\n instance\naccessible via the \nschema\n attribute on \nAPIView\n. This provides the\nappropriate Core API \nLink\n object for the view, request method and path:\n\n\nauto_schema = view.schema\ncoreapi_link = auto_schema.get_link(...)\n\n\n\n(In compiling the schema, \nSchemaGenerator\n calls \nview.schema.get_link()\n for\neach view, allowed method and path.)\n\n\n\n\nNote\n: For basic \nAPIView\n subclasses, default introspection is essentially\nlimited to the URL kwarg path parameters. For \nGenericAPIView\n\nsubclasses, which includes all the provided class based views, \nAutoSchema\n will\nattempt to introspect serialiser, pagination and filter fields, as well as\nprovide richer path field descriptions. (The key hooks here are the relevant\n\nGenericAPIView\n attributes and methods: \nget_serializer\n, \npagination_class\n,\n\nfilter_backends\n and so on.)\n\n\n\n\nTo customise the \nLink\n generation you may:\n\n\n\n\n\n\nInstantiate \nAutoSchema\n on your view with the \nmanual_fields\n kwarg:\n\n\nfrom rest_framework.views import APIView\nfrom rest_framework.schemas import AutoSchema\n\nclass CustomView(APIView):\n ...\n schema = AutoSchema(\n manual_fields=[\n coreapi.Field(\"extra_field\", ...),\n ]\n )\n\n\n\nThis allows extension for the most common case without subclassing.\n\n\n\n\n\n\nProvide an \nAutoSchema\n subclass with more complex customisation:\n\n\nfrom rest_framework.views import APIView\nfrom rest_framework.schemas import AutoSchema\n\nclass CustomSchema(AutoSchema):\n def get_link(...):\n # Implement custom introspection here (or in other sub-methods)\n\nclass CustomView(APIView):\n ...\n schema = CustomSchema()\n\n\n\nThis provides complete control over view introspection.\n\n\n\n\n\n\nInstantiate \nManualSchema\n on your view, providing the Core API \nFields\n for\n the view explicitly:\n\n\nfrom rest_framework.views import APIView\nfrom rest_framework.schemas import ManualSchema\n\nclass CustomView(APIView):\n ...\n schema = ManualSchema(fields=[\n coreapi.Field(\n \"first_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n coreapi.Field(\n \"second_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n ])\n\n\n\nThis allows manually specifying the schema for some views whilst maintaining\nautomatic generation elsewhere.\n\n\n\n\n\n\nYou may disable schema generation for a view by setting \nschema\n to \nNone\n:\n\n\n class CustomView(APIView):\n ...\n schema = None # Will not appear in schema\n\n\n\nThis also applies to extra actions for \nViewSet\ns:\n\n\n class CustomViewSet(viewsets.ModelViewSet):\n\n @action(detail=True, schema=None)\n def extra_action(self, request, pk=None):\n ...\n\n\n\n\n\nNote\n: For full details on \nSchemaGenerator\n plus the \nAutoSchema\n and\n\nManualSchema\n descriptors see the \nAPI Reference below\n.\n\n\n\n\nAdding a schema view\n\n\nThere are a few different ways to add a schema view to your API, depending on\nexactly what you need.\n\n\nThe get_schema_view shortcut\n\n\nThe simplest way to include a schema in your project is to use the\n\nget_schema_view()\n function.\n\n\nfrom rest_framework.schemas import get_schema_view\n\nschema_view = get_schema_view(title=\"Server Monitoring API\")\n\nurlpatterns = [\n url('^$', schema_view),\n ...\n]\n\n\n\nOnce the view has been added, you'll be able to make API requests to retrieve\nthe auto-generated schema definition.\n\n\n$ http http://127.0.0.1:8000/ Accept:application/coreapi+json\nHTTP/1.0 200 OK\nAllow: GET, HEAD, OPTIONS\nContent-Type: application/vnd.coreapi+json\n\n{\n \"_meta\": {\n \"title\": \"Server Monitoring API\"\n },\n \"_type\": \"document\",\n ...\n}\n\n\n\nThe arguments to \nget_schema_view()\n are:\n\n\ntitle\n\n\nMay be used to provide a descriptive title for the schema definition.\n\n\nurl\n\n\nMay be used to pass a canonical URL for the schema.\n\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/'\n)\n\n\n\nurlconf\n\n\nA string representing the import path to the URL conf that you want\nto generate an API schema for. This defaults to the value of Django's\nROOT_URLCONF setting.\n\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n urlconf='myproject.urls'\n)\n\n\n\nrenderer_classes\n\n\nMay be used to pass the set of renderer classes that can be used to render the API root endpoint.\n\n\nfrom rest_framework.schemas import get_schema_view\nfrom rest_framework.renderers import JSONOpenAPIRenderer\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n renderer_classes=[JSONOpenAPIRenderer]\n)\n\n\n\npatterns\n\n\nList of url patterns to limit the schema introspection to. If you only want the \nmyproject.api\n urls\nto be exposed in the schema:\n\n\nschema_url_patterns = [\n url(r'^api/', include('myproject.api.urls')),\n]\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n patterns=schema_url_patterns,\n)\n\n\n\ngenerator_class\n\n\nMay be used to specify a \nSchemaGenerator\n subclass to be passed to the\n\nSchemaView\n.\n\n\nauthentication_classes\n\n\nMay be used to specify the list of authentication classes that will apply to the schema endpoint.\nDefaults to \nsettings.DEFAULT_AUTHENTICATION_CLASSES\n\n\npermission_classes\n\n\nMay be used to specify the list of permission classes that will apply to the schema endpoint.\nDefaults to \nsettings.DEFAULT_PERMISSION_CLASSES\n\n\nUsing an explicit schema view\n\n\nIf you need a little more control than the \nget_schema_view()\n shortcut gives you,\nthen you can use the \nSchemaGenerator\n class directly to auto-generate the\n\nDocument\n instance, and to return that from a view.\n\n\nThis option gives you the flexibility of setting up the schema endpoint\nwith whatever behaviour you want. For example, you can apply different\npermission, throttling, or authentication policies to the schema endpoint.\n\n\nHere's an example of using \nSchemaGenerator\n together with a view to\nreturn the schema.\n\n\nviews.py:\n\n\nfrom rest_framework.decorators import api_view, renderer_classes\nfrom rest_framework import renderers, response, schemas\n\ngenerator = schemas.SchemaGenerator(title='Bookings API')\n\n@api_view()\n@renderer_classes([renderers.OpenAPIRenderer])\ndef schema_view(request):\n schema = generator.get_schema(request)\n return response.Response(schema)\n\n\n\nurls.py:\n\n\nurlpatterns = [\n url('/', schema_view),\n ...\n]\n\n\n\nYou can also serve different schemas to different users, depending on the\npermissions they have available. This approach can be used to ensure that\nunauthenticated requests are presented with a different schema to\nauthenticated requests, or to ensure that different parts of the API are\nmade visible to different users depending on their role.\n\n\nIn order to present a schema with endpoints filtered by user permissions,\nyou need to pass the \nrequest\n argument to the \nget_schema()\n method, like so:\n\n\n@api_view()\n@renderer_classes([renderers.OpenAPIRenderer])\ndef schema_view(request):\n generator = schemas.SchemaGenerator(title='Bookings API')\n return response.Response(generator.get_schema(request=request))\n\n\n\nExplicit schema definition\n\n\nAn alternative to the auto-generated approach is to specify the API schema\nexplicitly, by declaring a \nDocument\n object in your codebase. Doing so is a\nlittle more work, but ensures that you have full control over the schema\nrepresentation.\n\n\nimport coreapi\nfrom rest_framework.decorators import api_view, renderer_classes\nfrom rest_framework import renderers, response\n\nschema = coreapi.Document(\n title='Bookings API',\n content={\n ...\n }\n)\n\n@api_view()\n@renderer_classes([renderers.OpenAPIRenderer])\ndef schema_view(request):\n return response.Response(schema)\n\n\n\n\n\nSchemas as documentation\n\n\nOne common usage of API schemas is to use them to build documentation pages.\n\n\nThe schema generation in REST framework uses docstrings to automatically\npopulate descriptions in the schema document.\n\n\nThese descriptions will be based on:\n\n\n\n\nThe corresponding method docstring if one exists.\n\n\nA named section within the class docstring, which can be either single line or multi-line.\n\n\nThe class docstring.\n\n\n\n\nExamples\n\n\nAn \nAPIView\n, with an explicit method docstring.\n\n\nclass ListUsernames(APIView):\n def get(self, request):\n \"\"\"\n Return a list of all user names in the system.\n \"\"\"\n usernames = [user.username for user in User.objects.all()]\n return Response(usernames)\n\n\n\nA \nViewSet\n, with an explict action docstring.\n\n\nclass ListUsernames(ViewSet):\n def list(self, request):\n \"\"\"\n Return a list of all user names in the system.\n \"\"\"\n usernames = [user.username for user in User.objects.all()]\n return Response(usernames)\n\n\n\nA generic view with sections in the class docstring, using single-line style.\n\n\nclass UserList(generics.ListCreateAPIView):\n \"\"\"\n get: List all the users.\n post: Create a new user.\n \"\"\"\n queryset = User.objects.all()\n serializer_class = UserSerializer\n permission_classes = (IsAdminUser,)\n\n\n\nA generic viewset with sections in the class docstring, using multi-line style.\n\n\nclass UserViewSet(viewsets.ModelViewSet):\n \"\"\"\n API endpoint that allows users to be viewed or edited.\n\n retrieve:\n Return a user instance.\n\n list:\n Return all users, ordered by most recently joined.\n \"\"\"\n queryset = User.objects.all().order_by('-date_joined')\n serializer_class = UserSerializer\n\n\n\n\n\nAPI Reference\n\n\nSchemaGenerator\n\n\nA class that walks a list of routed URL patterns, requests the schema for each view,\nand collates the resulting CoreAPI Document.\n\n\nTypically you'll instantiate \nSchemaGenerator\n with a single argument, like so:\n\n\ngenerator = SchemaGenerator(title='Stock Prices API')\n\n\n\nArguments:\n\n\n\n\ntitle\n \nrequired\n - The name of the API.\n\n\nurl\n - The root URL of the API schema. This option is not required unless the schema is included under path prefix.\n\n\npatterns\n - A list of URLs to inspect when generating the schema. Defaults to the project's URL conf.\n\n\nurlconf\n - A URL conf module name to use when generating the schema. Defaults to \nsettings.ROOT_URLCONF\n.\n\n\n\n\nget_schema(self, request)\n\n\nReturns a \ncoreapi.Document\n instance that represents the API schema.\n\n\n@api_view\n@renderer_classes([renderers.OpenAPIRenderer])\ndef schema_view(request):\n generator = schemas.SchemaGenerator(title='Bookings API')\n return Response(generator.get_schema())\n\n\n\nThe \nrequest\n argument is optional, and may be used if you want to apply per-user\npermissions to the resulting schema generation.\n\n\nget_links(self, request)\n\n\nReturn a nested dictionary containing all the links that should be included in the API schema.\n\n\nThis is a good point to override if you want to modify the resulting structure of the generated schema,\nas you can build a new dictionary with a different layout.\n\n\nAutoSchema\n\n\nA class that deals with introspection of individual views for schema generation.\n\n\nAutoSchema\n is attached to \nAPIView\n via the \nschema\n attribute.\n\n\nThe \nAutoSchema\n constructor takes a single keyword argument \nmanual_fields\n.\n\n\nmanual_fields\n: a \nlist\n of \ncoreapi.Field\n instances that will be added to\nthe generated fields. Generated fields with a matching \nname\n will be overwritten.\n\n\nclass CustomView(APIView):\n schema = AutoSchema(manual_fields=[\n coreapi.Field(\n \"my_extra_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n ])\n\n\n\nFor more advanced customisation subclass \nAutoSchema\n to customise schema generation.\n\n\nclass CustomViewSchema(AutoSchema):\n \"\"\"\n Overrides `get_link()` to provide Custom Behavior X\n \"\"\"\n\n def get_link(self, path, method, base_url):\n link = super().get_link(path, method, base_url)\n # Do something to customize link here...\n return link\n\nclass MyView(APIView):\n schema = CustomViewSchema()\n\n\n\nThe following methods are available to override.\n\n\nget_link(self, path, method, base_url)\n\n\nReturns a \ncoreapi.Link\n instance corresponding to the given view.\n\n\nThis is the main entry point.\nYou can override this if you need to provide custom behaviors for particular views.\n\n\nget_description(self, path, method)\n\n\nReturns a string to use as the link description. By default this is based on the\nview docstring as described in the \"Schemas as Documentation\" section above.\n\n\nget_encoding(self, path, method)\n\n\nReturns a string to indicate the encoding for any request body, when interacting\nwith the given view. Eg. \n'application/json'\n. May return a blank string for views\nthat do not expect a request body.\n\n\nget_path_fields(self, path, method):\n\n\nReturn a list of \ncoreapi.Field()\n instances. One for each path parameter in the URL.\n\n\nget_serializer_fields(self, path, method)\n\n\nReturn a list of \ncoreapi.Field()\n instances. One for each field in the serializer class used by the view.\n\n\nget_pagination_fields(self, path, method)\n\n\nReturn a list of \ncoreapi.Field()\n instances, as returned by the \nget_schema_fields()\n method on any pagination class used by the view.\n\n\nget_filter_fields(self, path, method)\n\n\nReturn a list of \ncoreapi.Field()\n instances, as returned by the \nget_schema_fields()\n method of any filter classes used by the view.\n\n\nget_manual_fields(self, path, method)\n\n\nReturn a list of \ncoreapi.Field()\n instances to be added to or replace generated fields. Defaults to (optional) \nmanual_fields\n passed to \nAutoSchema\n constructor.\n\n\nMay be overridden to customise manual fields by \npath\n or \nmethod\n. For example, a per-method adjustment may look like this:\n\n\ndef get_manual_fields(self, path, method):\n \"\"\"Example adding per-method fields.\"\"\"\n\n extra_fields = []\n if method=='GET':\n extra_fields = # ... list of extra fields for GET ...\n if method=='POST':\n extra_fields = # ... list of extra fields for POST ...\n\n manual_fields = super().get_manual_fields(path, method)\n return manual_fields + extra_fields\n\n\n\n\nupdate_fields(fields, update_with)\n\n\nUtility \nstaticmethod\n. Encapsulates logic to add or replace fields from a list\nby \nField.name\n. May be overridden to adjust replacement criteria.\n\n\nManualSchema\n\n\nAllows manually providing a list of \ncoreapi.Field\n instances for the schema,\nplus an optional description.\n\n\nclass MyView(APIView):\n schema = ManualSchema(fields=[\n coreapi.Field(\n \"first_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n coreapi.Field(\n \"second_field\",\n required=True,\n location=\"path\",\n schema=coreschema.String()\n ),\n ]\n )\n\n\n\nThe \nManualSchema\n constructor takes two arguments:\n\n\nfields\n: A list of \ncoreapi.Field\n instances. Required.\n\n\ndescription\n: A string description. Optional.\n\n\nencoding\n: Default \nNone\n. A string encoding, e.g \napplication/json\n. Optional.\n\n\n\n\nCore API\n\n\nThis documentation gives a brief overview of the components within the \ncoreapi\n\npackage that are used to represent an API schema.\n\n\nNote that these classes are imported from the \ncoreapi\n package, rather than\nfrom the \nrest_framework\n package.\n\n\nDocument\n\n\nRepresents a container for the API schema.\n\n\ntitle\n\n\nA name for the API.\n\n\nurl\n\n\nA canonical URL for the API.\n\n\ncontent\n\n\nA dictionary, containing the \nLink\n objects that the schema contains.\n\n\nIn order to provide more structure to the schema, the \ncontent\n dictionary\nmay be nested, typically to a second level. For example:\n\n\ncontent={\n \"bookings\": {\n \"list\": Link(...),\n \"create\": Link(...),\n ...\n },\n \"venues\": {\n \"list\": Link(...),\n ...\n },\n ...\n}\n\n\n\nLink\n\n\nRepresents an individual API endpoint.\n\n\nurl\n\n\nThe URL of the endpoint. May be a URI template, such as \n/users/{username}/\n.\n\n\naction\n\n\nThe HTTP method associated with the endpoint. Note that URLs that support\nmore than one HTTP method, should correspond to a single \nLink\n for each.\n\n\nfields\n\n\nA list of \nField\n instances, describing the available parameters on the input.\n\n\ndescription\n\n\nA short description of the meaning and intended usage of the endpoint.\n\n\nField\n\n\nRepresents a single input parameter on a given API endpoint.\n\n\nname\n\n\nA descriptive name for the input.\n\n\nrequired\n\n\nA boolean, indicated if the client is required to included a value, or if\nthe parameter can be omitted.\n\n\nlocation\n\n\nDetermines how the information is encoded into the request. Should be one of\nthe following strings:\n\n\n\"path\"\n\n\nIncluded in a templated URI. For example a \nurl\n value of \n/products/{product_code}/\n could be used together with a \n\"path\"\n field, to handle API inputs in a URL path such as \n/products/slim-fit-jeans/\n.\n\n\nThese fields will normally correspond with \nnamed arguments in the project URL conf\n.\n\n\n\"query\"\n\n\nIncluded as a URL query parameter. For example \n?search=sale\n. Typically for \nGET\n requests.\n\n\nThese fields will normally correspond with pagination and filtering controls on a view.\n\n\n\"form\"\n\n\nIncluded in the request body, as a single item of a JSON object or HTML form. For example \n{\"colour\": \"blue\", ...}\n. Typically for \nPOST\n, \nPUT\n and \nPATCH\n requests. Multiple \n\"form\"\n fields may be included on a single link.\n\n\nThese fields will normally correspond with serializer fields on a view.\n\n\n\"body\"\n\n\nIncluded as the complete request body. Typically for \nPOST\n, \nPUT\n and \nPATCH\n requests. No more than one \n\"body\"\n field may exist on a link. May not be used together with \n\"form\"\n fields.\n\n\nThese fields will normally correspond with views that use \nListSerializer\n to validate the request input, or with file upload views.\n\n\nencoding\n\n\n\"application/json\"\n\n\nJSON encoded request content. Corresponds to views using \nJSONParser\n.\nValid only if either one or more \nlocation=\"form\"\n fields, or a single\n\nlocation=\"body\"\n field is included on the \nLink\n.\n\n\n\"multipart/form-data\"\n\n\nMultipart encoded request content. Corresponds to views using \nMultiPartParser\n.\nValid only if one or more \nlocation=\"form\"\n fields is included on the \nLink\n.\n\n\n\"application/x-www-form-urlencoded\"\n\n\nURL encoded request content. Corresponds to views using \nFormParser\n. Valid\nonly if one or more \nlocation=\"form\"\n fields is included on the \nLink\n.\n\n\n\"application/octet-stream\"\n\n\nBinary upload request content. Corresponds to views using \nFileUploadParser\n.\nValid only if a \nlocation=\"body\"\n field is included on the \nLink\n.\n\n\ndescription\n\n\nA short description of the meaning and intended usage of the input field.\n\n\n\n\nThird party packages\n\n\ndrf-yasg - Yet Another Swagger Generator\n\n\ndrf-yasg\n generates \nOpenAPI\n documents suitable for code generation - nested schemas,\nnamed models, response bodies, enum/pattern/min/max validators, form parameters, etc.", "title": "Schemas" }, { @@ -3152,7 +3152,7 @@ }, { "location": "/api-guide/schemas/#schema-output-formats", - "text": "In order to be presented in an HTTP response, the internal representation\nhas to be rendered into the actual bytes that are used in the response. REST framework includes a few different renderers that you can use for\nencoding the API schema. renderers.OpenAPIRenderer - Renders into YAML-based [OpenAPI][openapi], the most widely used API schema format. renderers.JSONOpenAPIRenderer - Renders into JSON-based [OpenAPI][openapi]. renderers.CoreJSONRenderer - Renders into Core JSON , a format designed for\nuse with the coreapi client library. Core JSON is designed as a canonical format for use with Core API.\nREST framework includes a renderer class for handling this media type, which\nis available as renderers.CoreJSONRenderer .", + "text": "In order to be presented in an HTTP response, the internal representation\nhas to be rendered into the actual bytes that are used in the response. REST framework includes a few different renderers that you can use for\nencoding the API schema. renderers.OpenAPIRenderer - Renders into YAML-based OpenAPI , the most widely used API schema format. renderers.JSONOpenAPIRenderer - Renders into JSON-based OpenAPI . renderers.CoreJSONRenderer - Renders into Core JSON , a format designed for\nuse with the coreapi client library. Core JSON is designed as a canonical format for use with Core API.\nREST framework includes a renderer class for handling this media type, which\nis available as renderers.CoreJSONRenderer .", "title": "Schema output formats" }, { @@ -3415,11 +3415,6 @@ "text": "drf-yasg generates OpenAPI documents suitable for code generation - nested schemas,\nnamed models, response bodies, enum/pattern/min/max validators, form parameters, etc.", "title": "drf-yasg - Yet Another Swagger Generator" }, - { - "location": "/api-guide/schemas/#drf-openapi", - "text": "DRF OpenAPI renders the schema generated by Django Rest Framework\nin OpenAPI format.", - "title": "DRF OpenAPI" - }, { "location": "/api-guide/format-suffixes/", "text": "Format suffixes\n\n\n\n\nSection 6.2.1 does not say that content negotiation should be\nused all the time.\n\n\n\u2014 Roy Fielding, \nREST discuss mailing list\n\n\n\n\nA common pattern for Web APIs is to use filename extensions on URLs to provide an endpoint for a given media type. For example, 'http://example.com/api/users.json' to serve a JSON representation.\n\n\nAdding format-suffix patterns to each individual entry in the URLconf for your API is error-prone and non-DRY, so REST framework provides a shortcut to adding these patterns to your URLConf.\n\n\nformat_suffix_patterns\n\n\nSignature\n: format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None)\n\n\nReturns a URL pattern list which includes format suffix patterns appended to each of the URL patterns provided.\n\n\nArguments:\n\n\n\n\nurlpatterns\n: Required. A URL pattern list.\n\n\nsuffix_required\n: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to \nFalse\n, meaning that suffixes are optional by default.\n\n\nallowed\n: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used.\n\n\n\n\nExample:\n\n\nfrom rest_framework.urlpatterns import format_suffix_patterns\nfrom blog import views\n\nurlpatterns = [\n url(r'^/$', views.apt_root),\n url(r'^comments/$', views.comment_list),\n url(r'^comments/(?P[0-9]+)/$', views.comment_detail)\n]\n\nurlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html'])\n\n\n\nWhen using \nformat_suffix_patterns\n, you must make sure to add the \n'format'\n keyword argument to the corresponding views. For example:\n\n\n@api_view(('GET', 'POST'))\ndef comment_list(request, format=None):\n # do stuff...\n\n\n\nOr with class-based views:\n\n\nclass CommentList(APIView):\n def get(self, request, format=None):\n # do stuff...\n\n def post(self, request, format=None):\n # do stuff...\n\n\n\nThe name of the kwarg used may be modified by using the \nFORMAT_SUFFIX_KWARG\n setting.\n\n\nAlso note that \nformat_suffix_patterns\n does not support descending into \ninclude\n URL patterns.\n\n\nUsing with \ni18n_patterns\n\n\nIf using the \ni18n_patterns\n function provided by Django, as well as \nformat_suffix_patterns\n you should make sure that the \ni18n_patterns\n function is applied as the final, or outermost function. For example:\n\n\nurl patterns = [\n \u2026\n]\n\nurlpatterns = i18n_patterns(\n format_suffix_patterns(urlpatterns, allowed=['json', 'html'])\n)\n\n\n\n\n\nQuery parameter formats\n\n\nAn alternative to the format suffixes is to include the requested format in a query parameter. REST framework provides this option by default, and it is used in the browsable API to switch between differing available representations.\n\n\nTo select a representation using its short format, use the \nformat\n query parameter. For example: \nhttp://example.com/organizations/?format=csv\n.\n\n\nThe name of this query parameter can be modified using the \nURL_FORMAT_OVERRIDE\n setting. Set the value to \nNone\n to disable this behavior.\n\n\n\n\nAccept headers vs. format suffixes\n\n\nThere seems to be a view among some of the Web community that filename extensions are not a RESTful pattern, and that \nHTTP Accept\n headers should always be used instead.\n\n\nIt is actually a misconception. For example, take the following quote from Roy Fielding discussing the relative merits of query parameter media-type indicators vs. file extension media-type indicators:\n\n\n\u201cThat's why I always prefer extensions. Neither choice has anything to do with REST.\u201d \u2014 Roy Fielding, \nREST discuss mailing list\n\n\nThe quote does not mention Accept headers, but it does make it clear that format suffixes should be considered an acceptable pattern.", @@ -3612,7 +3607,7 @@ }, { "location": "/api-guide/testing/", - "text": "Testing\n\n\n\n\nCode without tests is broken as designed.\n\n\n\u2014 \nJacob Kaplan-Moss\n\n\n\n\nREST framework includes a few helper classes that extend Django's existing test framework, and improve support for making API requests.\n\n\nAPIRequestFactory\n\n\nExtends \nDjango's existing \nRequestFactory\n class\n.\n\n\nCreating test requests\n\n\nThe \nAPIRequestFactory\n class supports an almost identical API to Django's standard \nRequestFactory\n class. This means that the standard \n.get()\n, \n.post()\n, \n.put()\n, \n.patch()\n, \n.delete()\n, \n.head()\n and \n.options()\n methods are all available.\n\n\nfrom rest_framework.test import APIRequestFactory\n\n# Using the standard RequestFactory API to create a form POST request\nfactory = APIRequestFactory()\nrequest = factory.post('/notes/', {'title': 'new idea'})\n\n\n\nUsing the \nformat\n argument\n\n\nMethods which create a request body, such as \npost\n, \nput\n and \npatch\n, include a \nformat\n argument, which make it easy to generate requests using a content type other than multipart form data. For example:\n\n\n# Create a JSON POST request\nfactory = APIRequestFactory()\nrequest = factory.post('/notes/', {'title': 'new idea'}, format='json')\n\n\n\nBy default the available formats are \n'multipart'\n and \n'json'\n. For compatibility with Django's existing \nRequestFactory\n the default format is \n'multipart'\n.\n\n\nTo support a wider set of request formats, or change the default format, \nsee the configuration section\n.\n\n\nExplicitly encoding the request body\n\n\nIf you need to explicitly encode the request body, you can do so by setting the \ncontent_type\n flag. For example:\n\n\nrequest = factory.post('/notes/', json.dumps({'title': 'new idea'}), content_type='application/json')\n\n\n\nPUT and PATCH with form data\n\n\nOne difference worth noting between Django's \nRequestFactory\n and REST framework's \nAPIRequestFactory\n is that multipart form data will be encoded for methods other than just \n.post()\n.\n\n\nFor example, using \nAPIRequestFactory\n, you can make a form PUT request like so:\n\n\nfactory = APIRequestFactory()\nrequest = factory.put('/notes/547/', {'title': 'remember to email dave'})\n\n\n\nUsing Django's \nRequestFactory\n, you'd need to explicitly encode the data yourself:\n\n\nfrom django.test.client import encode_multipart, RequestFactory\n\nfactory = RequestFactory()\ndata = {'title': 'remember to email dave'}\ncontent = encode_multipart('BoUnDaRyStRiNg', data)\ncontent_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg'\nrequest = factory.put('/notes/547/', content, content_type=content_type)\n\n\n\nForcing authentication\n\n\nWhen 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.\n\n\nTo forcibly authenticate a request, use the \nforce_authenticate()\n method.\n\n\nfrom rest_framework.test import force_authenticate\n\nfactory = APIRequestFactory()\nuser = User.objects.get(username='olivia')\nview = AccountDetail.as_view()\n\n# Make an authenticated request to the view...\nrequest = factory.get('/accounts/django-superstars/')\nforce_authenticate(request, user=user)\nresponse = view(request)\n\n\n\nThe signature for the method is \nforce_authenticate(request, user=None, token=None)\n. When making the call, either or both of the user and token may be set.\n\n\nFor example, when forcibly authenticating using a token, you might do something like the following:\n\n\nuser = User.objects.get(username='olivia')\nrequest = factory.get('/accounts/django-superstars/')\nforce_authenticate(request, user=user, token=user.auth_token)\n\n\n\n\n\nNote\n: \nforce_authenticate\n directly sets \nrequest.user\n to the in-memory \nuser\n instance. If you are re-using the same \nuser\n instance across multiple tests that update the saved \nuser\n state, you may need to call \nrefresh_from_db()\n between tests.\n\n\n\n\nNote\n: When using \nAPIRequestFactory\n, the object that is returned is Django's standard \nHttpRequest\n, and not REST framework's \nRequest\n object, which is only generated once the view is called.\n\n\nThis means that setting attributes directly on the request object may not always have the effect you expect. For example, setting \n.token\n directly will have no effect, and setting \n.user\n directly will only work if session authentication is being used.\n\n\n# Request will only authenticate if `SessionAuthentication` is in use.\nrequest = factory.get('/accounts/django-superstars/')\nrequest.user = user\nresponse = view(request)\n\n\n\n\n\nForcing CSRF validation\n\n\nBy default, requests created with \nAPIRequestFactory\n will not have CSRF validation applied when passed to a REST framework view. If you need to explicitly turn CSRF validation on, you can do so by setting the \nenforce_csrf_checks\n flag when instantiating the factory.\n\n\nfactory = APIRequestFactory(enforce_csrf_checks=True)\n\n\n\n\n\nNote\n: It's worth noting that Django's standard \nRequestFactory\n 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.\n\n\n\n\nAPIClient\n\n\nExtends \nDjango's existing \nClient\n class\n.\n\n\nMaking requests\n\n\nThe \nAPIClient\n class supports the same request interface as Django's standard \nClient\n class. This means that the standard \n.get()\n, \n.post()\n, \n.put()\n, \n.patch()\n, \n.delete()\n, \n.head()\n and \n.options()\n methods are all available. For example:\n\n\nfrom rest_framework.test import APIClient\n\nclient = APIClient()\nclient.post('/notes/', {'title': 'new idea'}, format='json')\n\n\n\nTo support a wider set of request formats, or change the default format, \nsee the configuration section\n.\n\n\nAuthenticating\n\n\n.login(**kwargs)\n\n\nThe \nlogin\n method functions exactly as it does with Django's regular \nClient\n class. This allows you to authenticate requests against any views which include \nSessionAuthentication\n.\n\n\n# Make all requests in the context of a logged in session.\nclient = APIClient()\nclient.login(username='lauren', password='secret')\n\n\n\nTo logout, call the \nlogout\n method as usual.\n\n\n# Log out\nclient.logout()\n\n\n\nThe \nlogin\n method is appropriate for testing APIs that use session authentication, for example web sites which include AJAX interaction with the API.\n\n\n.credentials(**kwargs)\n\n\nThe \ncredentials\n method can be used to set headers that will then be included on all subsequent requests by the test client.\n\n\nfrom rest_framework.authtoken.models import Token\nfrom rest_framework.test import APIClient\n\n# Include an appropriate `Authorization:` header on all requests.\ntoken = Token.objects.get(user__username='lauren')\nclient = APIClient()\nclient.credentials(HTTP_AUTHORIZATION='Token ' + token.key)\n\n\n\nNote that calling \ncredentials\n a second time overwrites any existing credentials. You can unset any existing credentials by calling the method with no arguments.\n\n\n# Stop including any credentials\nclient.credentials()\n\n\n\nThe \ncredentials\n method is appropriate for testing APIs that require authentication headers, such as basic authentication, OAuth1a and OAuth2 authentication, and simple token authentication schemes.\n\n\n.force_authenticate(user=None, token=None)\n\n\nSometimes you may want to bypass authentication entirely and force all requests by the test client to be automatically treated as authenticated.\n\n\nThis can be a useful shortcut if you're testing the API but don't want to have to construct valid authentication credentials in order to make test requests.\n\n\nuser = User.objects.get(username='lauren')\nclient = APIClient()\nclient.force_authenticate(user=user)\n\n\n\nTo unauthenticate subsequent requests, call \nforce_authenticate\n setting the user and/or token to \nNone\n.\n\n\nclient.force_authenticate(user=None)\n\n\n\nCSRF validation\n\n\nBy default CSRF validation is not applied when using \nAPIClient\n. If you need to explicitly enable CSRF validation, you can do so by setting the \nenforce_csrf_checks\n flag when instantiating the client.\n\n\nclient = APIClient(enforce_csrf_checks=True)\n\n\n\nAs usual CSRF validation will only apply to any session authenticated views. This means CSRF validation will only occur if the client has been logged in by calling \nlogin()\n.\n\n\n\n\nRequestsClient\n\n\nREST framework also includes a client for interacting with your application\nusing the popular Python library, \nrequests\n. This may be useful if:\n\n\n\n\nYou are expecting to interface with the API primarily from another Python service,\nand want to test the service at the same level as the client will see.\n\n\nYou want to write tests in such a way that they can also be run against a staging or\nlive environment. (See \"Live tests\" below.)\n\n\n\n\nThis exposes exactly the same interface as if you were using a requests session\ndirectly.\n\n\nfrom rest_framework.test import RequestsClient\n\nclient = RequestsClient()\nresponse = client.get('http://testserver/users/')\nassert response.status_code == 200\n\n\n\nNote that the requests client requires you to pass fully qualified URLs.\n\n\nRequestsClient\n and working with the database\n\n\nThe \nRequestsClient\n class is useful if you want to write tests that solely interact with the service interface. This is a little stricter than using the standard Django test client, as it means that all interactions should be via the API.\n\n\nIf you're using \nRequestsClient\n you'll want to ensure that test setup, and results assertions are performed as regular API calls, rather than interacting with the database models directly. For example, rather than checking that \nCustomer.objects.count() == 3\n you would list the customers endpoint, and ensure that it contains three records.\n\n\nHeaders & Authentication\n\n\nCustom headers and authentication credentials can be provided in the same way\nas \nwhen using a standard \nrequests.Session\n instance\n.\n\n\nfrom requests.auth import HTTPBasicAuth\n\nclient.auth = HTTPBasicAuth('user', 'pass')\nclient.headers.update({'x-test': 'true'})\n\n\n\nCSRF\n\n\nIf you're using \nSessionAuthentication\n then you'll need to include a CSRF token\nfor any \nPOST\n, \nPUT\n, \nPATCH\n or \nDELETE\n requests.\n\n\nYou can do so by following the same flow that a JavaScript based client would use.\nFirst make a \nGET\n request in order to obtain a CRSF token, then present that\ntoken in the following request.\n\n\nFor example...\n\n\nclient = RequestsClient()\n\n# Obtain a CSRF token.\nresponse = client.get('http://testserver/homepage/')\nassert response.status_code == 200\ncsrftoken = response.cookies['csrftoken']\n\n# Interact with the API.\nresponse = client.post('http://testserver/organisations/', json={\n 'name': 'MegaCorp',\n 'status': 'active'\n}, headers={'X-CSRFToken': csrftoken})\nassert response.status_code == 200\n\n\n\nLive tests\n\n\nWith careful usage both the \nRequestsClient\n and the \nCoreAPIClient\n provide\nthe ability to write test cases that can run either in development, or be run\ndirectly against your staging server or production environment.\n\n\nUsing this style to create basic tests of a few core piece of functionality is\na powerful way to validate your live service. Doing so may require some careful\nattention to setup and teardown to ensure that the tests run in a way that they\ndo not directly affect customer data.\n\n\n\n\nCoreAPIClient\n\n\nThe CoreAPIClient allows you to interact with your API using the Python\n\ncoreapi\n client library.\n\n\n# Fetch the API schema\nclient = CoreAPIClient()\nschema = client.get('http://testserver/schema/')\n\n# Create a new organisation\nparams = {'name': 'MegaCorp', 'status': 'active'}\nclient.action(schema, ['organisations', 'create'], params)\n\n# Ensure that the organisation exists in the listing\ndata = client.action(schema, ['organisations', 'list'])\nassert(len(data) == 1)\nassert(data == [{'name': 'MegaCorp', 'status': 'active'}])\n\n\n\nHeaders & Authentication\n\n\nCustom headers and authentication may be used with \nCoreAPIClient\n in a\nsimilar way as with \nRequestsClient\n.\n\n\nfrom requests.auth import HTTPBasicAuth\n\nclient = CoreAPIClient()\nclient.session.auth = HTTPBasicAuth('user', 'pass')\nclient.session.headers.update({'x-test': 'true'})\n\n\n\n\n\nAPI Test cases\n\n\nREST framework includes the following test case classes, that mirror the existing Django test case classes, but use \nAPIClient\n instead of Django's default \nClient\n.\n\n\n\n\nAPISimpleTestCase\n\n\nAPITransactionTestCase\n\n\nAPITestCase\n\n\nAPILiveServerTestCase\n\n\n\n\nExample\n\n\nYou can use any of REST framework's test case classes as you would for the regular Django test case classes. The \nself.client\n attribute will be an \nAPIClient\n instance.\n\n\nfrom django.urls import reverse\nfrom rest_framework import status\nfrom rest_framework.test import APITestCase\nfrom myproject.apps.core.models import Account\n\nclass AccountTests(APITestCase):\n def test_create_account(self):\n \"\"\"\n Ensure we can create a new account object.\n \"\"\"\n url = reverse('account-list')\n data = {'name': 'DabApps'}\n response = self.client.post(url, data, format='json')\n self.assertEqual(response.status_code, status.HTTP_201_CREATED)\n self.assertEqual(Account.objects.count(), 1)\n self.assertEqual(Account.objects.get().name, 'DabApps')\n\n\n\n\n\nURLPatternsTestCase\n\n\nREST framework also provides a test case class for isolating \nurlpatterns\n on a per-class basis. Note that this inherits from Django's \nSimpleTestCase\n, and will most likely need to be mixed with another test case class.\n\n\nExample\n\n\nfrom django.urls import include, path, reverse\nfrom rest_framework.test import APITestCase, URLPatternsTestCase\n\n\nclass AccountTests(APITestCase, URLPatternsTestCase):\n urlpatterns = [\n path('api/', include('api.urls')),\n ]\n\n def test_create_account(self):\n \"\"\"\n Ensure we can create a new account object.\n \"\"\"\n url = reverse('account-list')\n response = self.client.get(url, format='json')\n self.assertEqual(response.status_code, status.HTTP_200_OK)\n self.assertEqual(len(response.data), 1)\n\n\n\n\n\nTesting responses\n\n\nChecking the response data\n\n\nWhen checking the validity of test responses it's often more convenient to inspect the data that the response was created with, rather than inspecting the fully rendered response.\n\n\nFor example, it's easier to inspect \nresponse.data\n:\n\n\nresponse = self.client.get('/users/4/')\nself.assertEqual(response.data, {'id': 4, 'username': 'lauren'})\n\n\n\nInstead of inspecting the result of parsing \nresponse.content\n:\n\n\nresponse = self.client.get('/users/4/')\nself.assertEqual(json.loads(response.content), {'id': 4, 'username': 'lauren'})\n\n\n\nRendering responses\n\n\nIf you're testing views directly using \nAPIRequestFactory\n, the responses that are returned will not yet be rendered, as rendering of template responses is performed by Django's internal request-response cycle. In order to access \nresponse.content\n, you'll first need to render the response.\n\n\nview = UserDetail.as_view()\nrequest = factory.get('/users/4')\nresponse = view(request, pk='4')\nresponse.render() # Cannot access `response.content` without this.\nself.assertEqual(response.content, '{\"username\": \"lauren\", \"id\": 4}')\n\n\n\n\n\nConfiguration\n\n\nSetting the default format\n\n\nThe default format used to make test requests may be set using the \nTEST_REQUEST_DEFAULT_FORMAT\n setting key. For example, to always use JSON for test requests by default instead of standard multipart form requests, set the following in your \nsettings.py\n file:\n\n\nREST_FRAMEWORK = {\n ...\n 'TEST_REQUEST_DEFAULT_FORMAT': 'json'\n}\n\n\n\nSetting the available formats\n\n\nIf you need to test requests using something other than multipart or json requests, you can do so by setting the \nTEST_REQUEST_RENDERER_CLASSES\n setting.\n\n\nFor example, to add support for using \nformat='html'\n in test requests, you might have something like this in your \nsettings.py\n file.\n\n\nREST_FRAMEWORK = {\n ...\n 'TEST_REQUEST_RENDERER_CLASSES': (\n 'rest_framework.renderers.MultiPartRenderer',\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.TemplateHTMLRenderer'\n )\n}", + "text": "Testing\n\n\n\n\nCode without tests is broken as designed.\n\n\n\u2014 \nJacob Kaplan-Moss\n\n\n\n\nREST framework includes a few helper classes that extend Django's existing test framework, and improve support for making API requests.\n\n\nAPIRequestFactory\n\n\nExtends \nDjango's existing \nRequestFactory\n class\n.\n\n\nCreating test requests\n\n\nThe \nAPIRequestFactory\n class supports an almost identical API to Django's standard \nRequestFactory\n class. This means that the standard \n.get()\n, \n.post()\n, \n.put()\n, \n.patch()\n, \n.delete()\n, \n.head()\n and \n.options()\n methods are all available.\n\n\nfrom rest_framework.test import APIRequestFactory\n\n# Using the standard RequestFactory API to create a form POST request\nfactory = APIRequestFactory()\nrequest = factory.post('/notes/', {'title': 'new idea'})\n\n\n\nUsing the \nformat\n argument\n\n\nMethods which create a request body, such as \npost\n, \nput\n and \npatch\n, include a \nformat\n argument, which make it easy to generate requests using a content type other than multipart form data. For example:\n\n\n# Create a JSON POST request\nfactory = APIRequestFactory()\nrequest = factory.post('/notes/', {'title': 'new idea'}, format='json')\n\n\n\nBy default the available formats are \n'multipart'\n and \n'json'\n. For compatibility with Django's existing \nRequestFactory\n the default format is \n'multipart'\n.\n\n\nTo support a wider set of request formats, or change the default format, \nsee the configuration section\n.\n\n\nExplicitly encoding the request body\n\n\nIf you need to explicitly encode the request body, you can do so by setting the \ncontent_type\n flag. For example:\n\n\nrequest = factory.post('/notes/', json.dumps({'title': 'new idea'}), content_type='application/json')\n\n\n\nPUT and PATCH with form data\n\n\nOne difference worth noting between Django's \nRequestFactory\n and REST framework's \nAPIRequestFactory\n is that multipart form data will be encoded for methods other than just \n.post()\n.\n\n\nFor example, using \nAPIRequestFactory\n, you can make a form PUT request like so:\n\n\nfactory = APIRequestFactory()\nrequest = factory.put('/notes/547/', {'title': 'remember to email dave'})\n\n\n\nUsing Django's \nRequestFactory\n, you'd need to explicitly encode the data yourself:\n\n\nfrom django.test.client import encode_multipart, RequestFactory\n\nfactory = RequestFactory()\ndata = {'title': 'remember to email dave'}\ncontent = encode_multipart('BoUnDaRyStRiNg', data)\ncontent_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg'\nrequest = factory.put('/notes/547/', content, content_type=content_type)\n\n\n\nForcing authentication\n\n\nWhen 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.\n\n\nTo forcibly authenticate a request, use the \nforce_authenticate()\n method.\n\n\nfrom rest_framework.test import force_authenticate\n\nfactory = APIRequestFactory()\nuser = User.objects.get(username='olivia')\nview = AccountDetail.as_view()\n\n# Make an authenticated request to the view...\nrequest = factory.get('/accounts/django-superstars/')\nforce_authenticate(request, user=user)\nresponse = view(request)\n\n\n\nThe signature for the method is \nforce_authenticate(request, user=None, token=None)\n. When making the call, either or both of the user and token may be set.\n\n\nFor example, when forcibly authenticating using a token, you might do something like the following:\n\n\nuser = User.objects.get(username='olivia')\nrequest = factory.get('/accounts/django-superstars/')\nforce_authenticate(request, user=user, token=user.auth_token)\n\n\n\n\n\nNote\n: \nforce_authenticate\n directly sets \nrequest.user\n to the in-memory \nuser\n instance. If you are re-using the same \nuser\n instance across multiple tests that update the saved \nuser\n state, you may need to call \nrefresh_from_db()\n between tests.\n\n\n\n\nNote\n: When using \nAPIRequestFactory\n, the object that is returned is Django's standard \nHttpRequest\n, and not REST framework's \nRequest\n object, which is only generated once the view is called.\n\n\nThis means that setting attributes directly on the request object may not always have the effect you expect. For example, setting \n.token\n directly will have no effect, and setting \n.user\n directly will only work if session authentication is being used.\n\n\n# Request will only authenticate if `SessionAuthentication` is in use.\nrequest = factory.get('/accounts/django-superstars/')\nrequest.user = user\nresponse = view(request)\n\n\n\n\n\nForcing CSRF validation\n\n\nBy default, requests created with \nAPIRequestFactory\n will not have CSRF validation applied when passed to a REST framework view. If you need to explicitly turn CSRF validation on, you can do so by setting the \nenforce_csrf_checks\n flag when instantiating the factory.\n\n\nfactory = APIRequestFactory(enforce_csrf_checks=True)\n\n\n\n\n\nNote\n: It's worth noting that Django's standard \nRequestFactory\n 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.\n\n\n\n\nAPIClient\n\n\nExtends \nDjango's existing \nClient\n class\n.\n\n\nMaking requests\n\n\nThe \nAPIClient\n class supports the same request interface as Django's standard \nClient\n class. This means that the standard \n.get()\n, \n.post()\n, \n.put()\n, \n.patch()\n, \n.delete()\n, \n.head()\n and \n.options()\n methods are all available. For example:\n\n\nfrom rest_framework.test import APIClient\n\nclient = APIClient()\nclient.post('/notes/', {'title': 'new idea'}, format='json')\n\n\n\nTo support a wider set of request formats, or change the default format, \nsee the configuration section\n.\n\n\nAuthenticating\n\n\n.login(**kwargs)\n\n\nThe \nlogin\n method functions exactly as it does with Django's regular \nClient\n class. This allows you to authenticate requests against any views which include \nSessionAuthentication\n.\n\n\n# Make all requests in the context of a logged in session.\nclient = APIClient()\nclient.login(username='lauren', password='secret')\n\n\n\nTo logout, call the \nlogout\n method as usual.\n\n\n# Log out\nclient.logout()\n\n\n\nThe \nlogin\n method is appropriate for testing APIs that use session authentication, for example web sites which include AJAX interaction with the API.\n\n\n.credentials(**kwargs)\n\n\nThe \ncredentials\n method can be used to set headers that will then be included on all subsequent requests by the test client.\n\n\nfrom rest_framework.authtoken.models import Token\nfrom rest_framework.test import APIClient\n\n# Include an appropriate `Authorization:` header on all requests.\ntoken = Token.objects.get(user__username='lauren')\nclient = APIClient()\nclient.credentials(HTTP_AUTHORIZATION='Token ' + token.key)\n\n\n\nNote that calling \ncredentials\n a second time overwrites any existing credentials. You can unset any existing credentials by calling the method with no arguments.\n\n\n# Stop including any credentials\nclient.credentials()\n\n\n\nThe \ncredentials\n method is appropriate for testing APIs that require authentication headers, such as basic authentication, OAuth1a and OAuth2 authentication, and simple token authentication schemes.\n\n\n.force_authenticate(user=None, token=None)\n\n\nSometimes you may want to bypass authentication entirely and force all requests by the test client to be automatically treated as authenticated.\n\n\nThis can be a useful shortcut if you're testing the API but don't want to have to construct valid authentication credentials in order to make test requests.\n\n\nuser = User.objects.get(username='lauren')\nclient = APIClient()\nclient.force_authenticate(user=user)\n\n\n\nTo unauthenticate subsequent requests, call \nforce_authenticate\n setting the user and/or token to \nNone\n.\n\n\nclient.force_authenticate(user=None)\n\n\n\nCSRF validation\n\n\nBy default CSRF validation is not applied when using \nAPIClient\n. If you need to explicitly enable CSRF validation, you can do so by setting the \nenforce_csrf_checks\n flag when instantiating the client.\n\n\nclient = APIClient(enforce_csrf_checks=True)\n\n\n\nAs usual CSRF validation will only apply to any session authenticated views. This means CSRF validation will only occur if the client has been logged in by calling \nlogin()\n.\n\n\n\n\nRequestsClient\n\n\nREST framework also includes a client for interacting with your application\nusing the popular Python library, \nrequests\n. This may be useful if:\n\n\n\n\nYou are expecting to interface with the API primarily from another Python service,\nand want to test the service at the same level as the client will see.\n\n\nYou want to write tests in such a way that they can also be run against a staging or\nlive environment. (See \"Live tests\" below.)\n\n\n\n\nThis exposes exactly the same interface as if you were using a requests session\ndirectly.\n\n\nfrom rest_framework.test import RequestsClient\n\nclient = RequestsClient()\nresponse = client.get('http://testserver/users/')\nassert response.status_code == 200\n\n\n\nNote that the requests client requires you to pass fully qualified URLs.\n\n\nRequestsClient and working with the database\n\n\nThe \nRequestsClient\n class is useful if you want to write tests that solely interact with the service interface. This is a little stricter than using the standard Django test client, as it means that all interactions should be via the API.\n\n\nIf you're using \nRequestsClient\n you'll want to ensure that test setup, and results assertions are performed as regular API calls, rather than interacting with the database models directly. For example, rather than checking that \nCustomer.objects.count() == 3\n you would list the customers endpoint, and ensure that it contains three records.\n\n\nHeaders & Authentication\n\n\nCustom headers and authentication credentials can be provided in the same way\nas \nwhen using a standard \nrequests.Session\n instance\n.\n\n\nfrom requests.auth import HTTPBasicAuth\n\nclient.auth = HTTPBasicAuth('user', 'pass')\nclient.headers.update({'x-test': 'true'})\n\n\n\nCSRF\n\n\nIf you're using \nSessionAuthentication\n then you'll need to include a CSRF token\nfor any \nPOST\n, \nPUT\n, \nPATCH\n or \nDELETE\n requests.\n\n\nYou can do so by following the same flow that a JavaScript based client would use.\nFirst make a \nGET\n request in order to obtain a CRSF token, then present that\ntoken in the following request.\n\n\nFor example...\n\n\nclient = RequestsClient()\n\n# Obtain a CSRF token.\nresponse = client.get('http://testserver/homepage/')\nassert response.status_code == 200\ncsrftoken = response.cookies['csrftoken']\n\n# Interact with the API.\nresponse = client.post('http://testserver/organisations/', json={\n 'name': 'MegaCorp',\n 'status': 'active'\n}, headers={'X-CSRFToken': csrftoken})\nassert response.status_code == 200\n\n\n\nLive tests\n\n\nWith careful usage both the \nRequestsClient\n and the \nCoreAPIClient\n provide\nthe ability to write test cases that can run either in development, or be run\ndirectly against your staging server or production environment.\n\n\nUsing this style to create basic tests of a few core piece of functionality is\na powerful way to validate your live service. Doing so may require some careful\nattention to setup and teardown to ensure that the tests run in a way that they\ndo not directly affect customer data.\n\n\n\n\nCoreAPIClient\n\n\nThe CoreAPIClient allows you to interact with your API using the Python\n\ncoreapi\n client library.\n\n\n# Fetch the API schema\nclient = CoreAPIClient()\nschema = client.get('http://testserver/schema/')\n\n# Create a new organisation\nparams = {'name': 'MegaCorp', 'status': 'active'}\nclient.action(schema, ['organisations', 'create'], params)\n\n# Ensure that the organisation exists in the listing\ndata = client.action(schema, ['organisations', 'list'])\nassert(len(data) == 1)\nassert(data == [{'name': 'MegaCorp', 'status': 'active'}])\n\n\n\nHeaders & Authentication\n\n\nCustom headers and authentication may be used with \nCoreAPIClient\n in a\nsimilar way as with \nRequestsClient\n.\n\n\nfrom requests.auth import HTTPBasicAuth\n\nclient = CoreAPIClient()\nclient.session.auth = HTTPBasicAuth('user', 'pass')\nclient.session.headers.update({'x-test': 'true'})\n\n\n\n\n\nAPI Test cases\n\n\nREST framework includes the following test case classes, that mirror the existing Django test case classes, but use \nAPIClient\n instead of Django's default \nClient\n.\n\n\n\n\nAPISimpleTestCase\n\n\nAPITransactionTestCase\n\n\nAPITestCase\n\n\nAPILiveServerTestCase\n\n\n\n\nExample\n\n\nYou can use any of REST framework's test case classes as you would for the regular Django test case classes. The \nself.client\n attribute will be an \nAPIClient\n instance.\n\n\nfrom django.urls import reverse\nfrom rest_framework import status\nfrom rest_framework.test import APITestCase\nfrom myproject.apps.core.models import Account\n\nclass AccountTests(APITestCase):\n def test_create_account(self):\n \"\"\"\n Ensure we can create a new account object.\n \"\"\"\n url = reverse('account-list')\n data = {'name': 'DabApps'}\n response = self.client.post(url, data, format='json')\n self.assertEqual(response.status_code, status.HTTP_201_CREATED)\n self.assertEqual(Account.objects.count(), 1)\n self.assertEqual(Account.objects.get().name, 'DabApps')\n\n\n\n\n\nURLPatternsTestCase\n\n\nREST framework also provides a test case class for isolating \nurlpatterns\n on a per-class basis. Note that this inherits from Django's \nSimpleTestCase\n, and will most likely need to be mixed with another test case class.\n\n\nExample\n\n\nfrom django.urls import include, path, reverse\nfrom rest_framework.test import APITestCase, URLPatternsTestCase\n\n\nclass AccountTests(APITestCase, URLPatternsTestCase):\n urlpatterns = [\n path('api/', include('api.urls')),\n ]\n\n def test_create_account(self):\n \"\"\"\n Ensure we can create a new account object.\n \"\"\"\n url = reverse('account-list')\n response = self.client.get(url, format='json')\n self.assertEqual(response.status_code, status.HTTP_200_OK)\n self.assertEqual(len(response.data), 1)\n\n\n\n\n\nTesting responses\n\n\nChecking the response data\n\n\nWhen checking the validity of test responses it's often more convenient to inspect the data that the response was created with, rather than inspecting the fully rendered response.\n\n\nFor example, it's easier to inspect \nresponse.data\n:\n\n\nresponse = self.client.get('/users/4/')\nself.assertEqual(response.data, {'id': 4, 'username': 'lauren'})\n\n\n\nInstead of inspecting the result of parsing \nresponse.content\n:\n\n\nresponse = self.client.get('/users/4/')\nself.assertEqual(json.loads(response.content), {'id': 4, 'username': 'lauren'})\n\n\n\nRendering responses\n\n\nIf you're testing views directly using \nAPIRequestFactory\n, the responses that are returned will not yet be rendered, as rendering of template responses is performed by Django's internal request-response cycle. In order to access \nresponse.content\n, you'll first need to render the response.\n\n\nview = UserDetail.as_view()\nrequest = factory.get('/users/4')\nresponse = view(request, pk='4')\nresponse.render() # Cannot access `response.content` without this.\nself.assertEqual(response.content, '{\"username\": \"lauren\", \"id\": 4}')\n\n\n\n\n\nConfiguration\n\n\nSetting the default format\n\n\nThe default format used to make test requests may be set using the \nTEST_REQUEST_DEFAULT_FORMAT\n setting key. For example, to always use JSON for test requests by default instead of standard multipart form requests, set the following in your \nsettings.py\n file:\n\n\nREST_FRAMEWORK = {\n ...\n 'TEST_REQUEST_DEFAULT_FORMAT': 'json'\n}\n\n\n\nSetting the available formats\n\n\nIf you need to test requests using something other than multipart or json requests, you can do so by setting the \nTEST_REQUEST_RENDERER_CLASSES\n setting.\n\n\nFor example, to add support for using \nformat='html'\n in test requests, you might have something like this in your \nsettings.py\n file.\n\n\nREST_FRAMEWORK = {\n ...\n 'TEST_REQUEST_RENDERER_CLASSES': (\n 'rest_framework.renderers.MultiPartRenderer',\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.TemplateHTMLRenderer'\n )\n}", "title": "Testing" }, { @@ -4482,7 +4477,7 @@ }, { "location": "/topics/browsable-api/", - "text": "The Browsable API\n\n\n\n\nIt is a profoundly erroneous truism... that we should cultivate the habit of thinking of what we are doing. The precise opposite is the case. Civilization advances by extending the number of important operations which we can perform without thinking about them.\n\n\n\u2014 \nAlfred North Whitehead\n, An Introduction to Mathematics (1911)\n\n\n\n\nAPI may stand for Application \nProgramming\n Interface, but humans have to be able to read the APIs, too; someone has to do the programming. Django REST Framework supports generating human-friendly HTML output for each resource when the \nHTML\n format is requested. These pages allow for easy browsing of resources, as well as forms for submitting data to the resources using \nPOST\n, \nPUT\n, and \nDELETE\n.\n\n\nURLs\n\n\nIf you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The \nrest_framework\n package includes a \nreverse\n helper for this purpose.\n\n\nFormats\n\n\nBy default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using \n?format=\n in the request, so you can look at the raw JSON response in a browser by adding \n?format=json\n to the URL. There are helpful extensions for viewing JSON in \nFirefox\n and \nChrome\n.\n\n\nCustomizing\n\n\nThe browsable API is built with \nTwitter's Bootstrap\n (v 3.3.5), making it easy to customize the look-and-feel.\n\n\nTo customize the default style, create a template called \nrest_framework/api.html\n that extends from \nrest_framework/base.html\n. For example:\n\n\ntemplates/rest_framework/api.html\n\n\n{% extends \"rest_framework/base.html\" %}\n\n... # Override blocks with required customizations\n\n\n\nOverriding the default theme\n\n\nTo replace the default theme, add a \nbootstrap_theme\n block to your \napi.html\n and insert a \nlink\n to the desired Bootstrap theme css file. This will completely replace the included theme.\n\n\n{% block bootstrap_theme %}\n \n{% endblock %}\n\n\n\nSuitable pre-made replacement themes are available at \nBootswatch\n. To use any of the Bootswatch themes, simply download the theme's \nbootstrap.min.css\n file, add it to your project, and replace the default one as described above.\n\n\nYou can also change the navbar variant, which by default is \nnavbar-inverse\n, using the \nbootstrap_navbar_variant\n block. The empty \n{% block bootstrap_navbar_variant %}{% endblock %}\n will use the original Bootstrap navbar style.\n\n\nFull example:\n\n\n{% extends \"rest_framework/base.html\" %}\n\n{% block bootstrap_theme %}\n \n{% endblock %}\n\n{% block bootstrap_navbar_variant %}{% endblock %}\n\n\n\nFor more specific CSS tweaks than simply overriding the default bootstrap theme you can override the \nstyle\n block.\n\n\n\n\n\n\nScreenshot of the bootswatch 'Cerulean' theme\n\n\n\n\n\n\nScreenshot of the bootswatch 'Slate' theme\n\n\n\n\nBlocks\n\n\nAll of the blocks available in the browsable API base template that can be used in your \napi.html\n.\n\n\n\n\nbody\n - The entire html \n\n.\n\n\nbodyclass\n - Class attribute for the \n\n tag, empty by default.\n\n\nbootstrap_theme\n - CSS for the Bootstrap theme.\n\n\nbootstrap_navbar_variant\n - CSS class for the navbar.\n\n\nbranding\n - Branding section of the navbar, see \nBootstrap components\n.\n\n\nbreadcrumbs\n - Links showing resource nesting, allowing the user to go back up the resources. It's recommended to preserve these, but they can be overridden using the breadcrumbs block.\n\n\nscript\n - JavaScript files for the page.\n\n\nstyle\n - CSS stylesheets for the page.\n\n\ntitle\n - Title of the page.\n\n\nuserlinks\n - This is a list of links on the right of the header, by default containing login/logout links. To add links instead of replace, use \n{{ block.super }}\n to preserve the authentication links.\n\n\n\n\nComponents\n\n\nAll of the standard \nBootstrap components\n are available.\n\n\nTooltips\n\n\nThe browsable API makes use of the Bootstrap tooltips component. Any element with the \njs-tooltip\n class and a \ntitle\n attribute has that title content will display a tooltip on hover events.\n\n\nLogin Template\n\n\nTo add branding and customize the look-and-feel of the login template, create a template called \nlogin.html\n and add it to your project, eg: \ntemplates/rest_framework/login.html\n. The template should extend from \nrest_framework/login_base.html\n.\n\n\nYou can add your site name or branding by including the branding block:\n\n\n{% block branding %}\n

    My Site Name

    \n{% endblock %}\n\n\n\nYou can also customize the style by adding the \nbootstrap_theme\n or \nstyle\n block similar to \napi.html\n.\n\n\nAdvanced Customization\n\n\nContext\n\n\nThe context that's available to the template:\n\n\n\n\nallowed_methods\n : A list of methods allowed by the resource\n\n\napi_settings\n : The API settings\n\n\navailable_formats\n : A list of formats allowed by the resource\n\n\nbreadcrumblist\n : The list of links following the chain of nested resources\n\n\ncontent\n : The content of the API response\n\n\ndescription\n : The description of the resource, generated from its docstring\n\n\nname\n : The name of the resource\n\n\npost_form\n : A form instance for use by the POST form (if allowed)\n\n\nput_form\n : A form instance for use by the PUT form (if allowed)\n\n\ndisplay_edit_forms\n : A boolean indicating whether or not POST, PUT and PATCH forms will be displayed\n\n\nrequest\n : The request object\n\n\nresponse\n : The response object\n\n\nversion\n : The version of Django REST Framework\n\n\nview\n : The view handling the request\n\n\nFORMAT_PARAM\n : The view can accept a format override\n\n\nMETHOD_PARAM\n : The view can accept a method override\n\n\n\n\nYou can override the \nBrowsableAPIRenderer.get_context()\n method to customise the context that gets passed to the template.\n\n\nNot using base.html\n\n\nFor more advanced customization, such as not having a Bootstrap basis or tighter integration with the rest of your site, you can simply choose not to have \napi.html\n extend \nbase.html\n. Then the page content and capabilities are entirely up to you.\n\n\nHandling \nChoiceField\n with large numbers of items.\n\n\nWhen a relationship or \nChoiceField\n has too many items, rendering the widget containing all the options can become very slow, and cause the browsable API rendering to perform poorly.\n\n\nThe simplest option in this case is to replace the select input with a standard text input. For example:\n\n\n author = serializers.HyperlinkedRelatedField(\n queryset=User.objects.all(),\n style={'base_template': 'input.html'}\n)\n\n\n\nAutocomplete\n\n\nAn alternative, but more complex option would be to replace the input with an autocomplete widget, that only loads and renders a subset of the available options as needed. If you need to do this you'll need to do some work to build a custom autocomplete HTML template yourself.\n\n\nThere are \na variety of packages for autocomplete widgets\n, such as \ndjango-autocomplete-light\n, that you may want to refer to. Note that you will not be able to simply include these components as standard widgets, but will need to write the HTML template explicitly. This is because REST framework 3.0 no longer supports the \nwidget\n keyword argument since it now uses templated HTML generation.", + "text": "The Browsable API\n\n\n\n\nIt is a profoundly erroneous truism... that we should cultivate the habit of thinking of what we are doing. The precise opposite is the case. Civilization advances by extending the number of important operations which we can perform without thinking about them.\n\n\n\u2014 \nAlfred North Whitehead\n, An Introduction to Mathematics (1911)\n\n\n\n\nAPI may stand for Application \nProgramming\n Interface, but humans have to be able to read the APIs, too; someone has to do the programming. Django REST Framework supports generating human-friendly HTML output for each resource when the \nHTML\n format is requested. These pages allow for easy browsing of resources, as well as forms for submitting data to the resources using \nPOST\n, \nPUT\n, and \nDELETE\n.\n\n\nURLs\n\n\nIf you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The \nrest_framework\n package includes a \nreverse\n helper for this purpose.\n\n\nFormats\n\n\nBy default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using \n?format=\n in the request, so you can look at the raw JSON response in a browser by adding \n?format=json\n to the URL. There are helpful extensions for viewing JSON in \nFirefox\n and \nChrome\n.\n\n\nCustomizing\n\n\nThe browsable API is built with \nTwitter's Bootstrap\n (v 3.3.5), making it easy to customize the look-and-feel.\n\n\nTo customize the default style, create a template called \nrest_framework/api.html\n that extends from \nrest_framework/base.html\n. For example:\n\n\ntemplates/rest_framework/api.html\n\n\n{% extends \"rest_framework/base.html\" %}\n\n... # Override blocks with required customizations\n\n\n\nOverriding the default theme\n\n\nTo replace the default theme, add a \nbootstrap_theme\n block to your \napi.html\n and insert a \nlink\n to the desired Bootstrap theme css file. This will completely replace the included theme.\n\n\n{% block bootstrap_theme %}\n \n{% endblock %}\n\n\n\nSuitable pre-made replacement themes are available at \nBootswatch\n. To use any of the Bootswatch themes, simply download the theme's \nbootstrap.min.css\n file, add it to your project, and replace the default one as described above.\n\n\nYou can also change the navbar variant, which by default is \nnavbar-inverse\n, using the \nbootstrap_navbar_variant\n block. The empty \n{% block bootstrap_navbar_variant %}{% endblock %}\n will use the original Bootstrap navbar style.\n\n\nFull example:\n\n\n{% extends \"rest_framework/base.html\" %}\n\n{% block bootstrap_theme %}\n \n{% endblock %}\n\n{% block bootstrap_navbar_variant %}{% endblock %}\n\n\n\nFor more specific CSS tweaks than simply overriding the default bootstrap theme you can override the \nstyle\n block.\n\n\n\n\n\n\nScreenshot of the bootswatch 'Cerulean' theme\n\n\n\n\n\n\nScreenshot of the bootswatch 'Slate' theme\n\n\n\n\nBlocks\n\n\nAll of the blocks available in the browsable API base template that can be used in your \napi.html\n.\n\n\n\n\nbody\n - The entire html \n\n.\n\n\nbodyclass\n - Class attribute for the \n\n tag, empty by default.\n\n\nbootstrap_theme\n - CSS for the Bootstrap theme.\n\n\nbootstrap_navbar_variant\n - CSS class for the navbar.\n\n\nbranding\n - Branding section of the navbar, see \nBootstrap components\n.\n\n\nbreadcrumbs\n - Links showing resource nesting, allowing the user to go back up the resources. It's recommended to preserve these, but they can be overridden using the breadcrumbs block.\n\n\nscript\n - JavaScript files for the page.\n\n\nstyle\n - CSS stylesheets for the page.\n\n\ntitle\n - Title of the page.\n\n\nuserlinks\n - This is a list of links on the right of the header, by default containing login/logout links. To add links instead of replace, use \n{{ block.super }}\n to preserve the authentication links.\n\n\n\n\nComponents\n\n\nAll of the standard \nBootstrap components\n are available.\n\n\nTooltips\n\n\nThe browsable API makes use of the Bootstrap tooltips component. Any element with the \njs-tooltip\n class and a \ntitle\n attribute has that title content will display a tooltip on hover events.\n\n\nLogin Template\n\n\nTo add branding and customize the look-and-feel of the login template, create a template called \nlogin.html\n and add it to your project, eg: \ntemplates/rest_framework/login.html\n. The template should extend from \nrest_framework/login_base.html\n.\n\n\nYou can add your site name or branding by including the branding block:\n\n\n{% extends \"rest_framework/login_base.html\" %}\n\n{% block branding %}\n

    My Site Name

    \n{% endblock %}\n\n\n\nYou can also customize the style by adding the \nbootstrap_theme\n or \nstyle\n block similar to \napi.html\n.\n\n\nAdvanced Customization\n\n\nContext\n\n\nThe context that's available to the template:\n\n\n\n\nallowed_methods\n : A list of methods allowed by the resource\n\n\napi_settings\n : The API settings\n\n\navailable_formats\n : A list of formats allowed by the resource\n\n\nbreadcrumblist\n : The list of links following the chain of nested resources\n\n\ncontent\n : The content of the API response\n\n\ndescription\n : The description of the resource, generated from its docstring\n\n\nname\n : The name of the resource\n\n\npost_form\n : A form instance for use by the POST form (if allowed)\n\n\nput_form\n : A form instance for use by the PUT form (if allowed)\n\n\ndisplay_edit_forms\n : A boolean indicating whether or not POST, PUT and PATCH forms will be displayed\n\n\nrequest\n : The request object\n\n\nresponse\n : The response object\n\n\nversion\n : The version of Django REST Framework\n\n\nview\n : The view handling the request\n\n\nFORMAT_PARAM\n : The view can accept a format override\n\n\nMETHOD_PARAM\n : The view can accept a method override\n\n\n\n\nYou can override the \nBrowsableAPIRenderer.get_context()\n method to customise the context that gets passed to the template.\n\n\nNot using base.html\n\n\nFor more advanced customization, such as not having a Bootstrap basis or tighter integration with the rest of your site, you can simply choose not to have \napi.html\n extend \nbase.html\n. Then the page content and capabilities are entirely up to you.\n\n\nHandling \nChoiceField\n with large numbers of items.\n\n\nWhen a relationship or \nChoiceField\n has too many items, rendering the widget containing all the options can become very slow, and cause the browsable API rendering to perform poorly.\n\n\nThe simplest option in this case is to replace the select input with a standard text input. For example:\n\n\n author = serializers.HyperlinkedRelatedField(\n queryset=User.objects.all(),\n style={'base_template': 'input.html'}\n)\n\n\n\nAutocomplete\n\n\nAn alternative, but more complex option would be to replace the input with an autocomplete widget, that only loads and renders a subset of the available options as needed. If you need to do this you'll need to do some work to build a custom autocomplete HTML template yourself.\n\n\nThere are \na variety of packages for autocomplete widgets\n, such as \ndjango-autocomplete-light\n, that you may want to refer to. Note that you will not be able to simply include these components as standard widgets, but will need to write the HTML template explicitly. This is because REST framework 3.0 no longer supports the \nwidget\n keyword argument since it now uses templated HTML generation.", "title": "The Browsable API" }, { @@ -4527,7 +4522,7 @@ }, { "location": "/topics/browsable-api/#login-template", - "text": "To add branding and customize the look-and-feel of the login template, create a template called login.html and add it to your project, eg: templates/rest_framework/login.html . The template should extend from rest_framework/login_base.html . You can add your site name or branding by including the branding block: {% block branding %}\n

    My Site Name

    \n{% endblock %} You can also customize the style by adding the bootstrap_theme or style block similar to api.html .", + "text": "To add branding and customize the look-and-feel of the login template, create a template called login.html and add it to your project, eg: templates/rest_framework/login.html . The template should extend from rest_framework/login_base.html . You can add your site name or branding by including the branding block: {% extends \"rest_framework/login_base.html\" %}\n\n{% block branding %}\n

    My Site Name

    \n{% endblock %} You can also customize the style by adding the bootstrap_theme or style block similar to api.html .", "title": "Login Template" }, { @@ -4932,7 +4927,7 @@ }, { "location": "/community/release-notes/", - "text": "Release Notes\n\n\n\n\nRelease Early, Release Often\n\n\n\u2014 Eric S. Raymond, \nThe Cathedral and the Bazaar\n.\n\n\n\n\nVersioning\n\n\nMinor version numbers (0.0.x) are used for changes that are API compatible. You should be able to upgrade between minor point releases without any other code changes.\n\n\nMedium version numbers (0.x.0) may include API changes, in line with the \ndeprecation policy\n. You should read the release notes carefully before upgrading between medium point releases.\n\n\nMajor version numbers (x.0.0) are reserved for substantial project milestones.\n\n\nDeprecation policy\n\n\nREST framework releases follow a formal deprecation policy, which is in line with \nDjango's deprecation policy\n.\n\n\nThe timeline for deprecation of a feature present in version 1.0 would work as follows:\n\n\n\n\n\n\nVersion 1.1 would remain \nfully backwards compatible\n with 1.0, but would raise \nPendingDeprecationWarning\n warnings if you use the feature that are due to be deprecated. These warnings are \nsilent by default\n, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using \npython -Wd manage.py test\n, you'll be warned of any API changes you need to make.\n\n\n\n\n\n\nVersion 1.2 would escalate these warnings to \nDeprecationWarning\n, which is loud by default.\n\n\n\n\n\n\nVersion 1.3 would remove the deprecated bits of API entirely.\n\n\n\n\n\n\nNote that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.\n\n\nUpgrading\n\n\nTo upgrade Django REST framework to the latest version, use pip:\n\n\npip install -U djangorestframework\n\n\n\nYou can determine your currently installed version using \npip show\n:\n\n\npip show djangorestframework\n\n\n\n\n\n3.9.x series\n\n\n3.9.0\n\n\nDate\n: \n18th October 2018\n\n\n\n\nImprovements to ViewSet extra actions \n#5605\n\n\nFix \naction\n support for ViewSet suffixes \n#6081\n\n\nAllow \naction\n docs sections \n#6060\n\n\nDeprecate the \nRouter.register\n \nbase_name\n argument in favor of \nbasename\n. \n#5990\n\n\nDeprecate the \nRouter.get_default_base_name\n method in favor of \nRouter.get_default_basename\n. \n#5990\n\n\nChange \nCharField\n to disallow null bytes. \n#6073\n\n To revert to the old behavior, subclass \nCharField\n and remove \nProhibitNullCharactersValidator\n from the validators.\n \npython\n class NullableCharField(serializers.CharField):\n def __init__(self, *args, **kwargs):\n super().__init__(*args, **kwargs)\n self.validators = [v for v in self.validators if not isinstance(v, ProhibitNullCharactersValidator)]\n\n\nAdd \nOpenAPIRenderer\n and \ngenerate_schema\n management command. \n#6229\n\n\nAdd OpenAPIRenderer by default, and add schema docs. \n#6233\n\n\nAllow permissions to be composed \n#5753\n\n\nAllow nullable BooleanField in Django 2.1 \n#6183\n\n\nAdd testing of Python 3.7 support \n#6141\n\n\nTest using Django 2.1 final release. \n#6109\n\n\nAdded djangorestframework-datatables to third-party packages \n#5931\n\n\nChange ISO 8601 date format to exclude year/month \n#5936\n\n\nUpdate all pypi.python.org URLs to pypi.org \n#5942\n\n\nEnsure that html forms (multipart form data) respect optional fields \n#5927\n\n\nAllow hashing of ErrorDetail. \n#5932\n\n\nCorrect schema parsing for JSONField \n#5878\n\n\nRender descriptions (from help_text) using safe \n#5869\n\n\nRemoved input value from deault_error_message \n#5881\n\n\nAdded min_value/max_value support in DurationField \n#5643\n\n\nFixed instance being overwritten in pk-only optimization try/except block \n#5747\n\n\nFixed AttributeError from items filter when value is None \n#5981\n\n\nFixed Javascript \ne.indexOf\n is not a function error \n#5982\n\n\nFix schemas for extra actions \n#5992\n\n\nImproved get_error_detail to use error_dict/error_list \n#5785\n\n\nImprvied URLs in Admin renderer \n#5988\n\n\nAdd \"Community\" section to docs, minor cleanup \n#5993\n\n\nMoved guardian imports out of compat \n#6054\n\n\nDeprecate the \nDjangoObjectPermissionsFilter\n class, moved to the \ndjangorestframework-guardian\n package. \n#6075\n\n\nDrop Django 1.10 support \n#5657\n\n\nOnly catch TypeError/ValueError for object lookups \n#6028\n\n\nHandle models without .objects manager in ModelSerializer. \n#6111\n\n\nImprove ModelSerializer.create() error message. \n#6112\n\n\nFix CSRF cookie check failure when using session auth with django 1.11.6+ \n#6113\n\n\nUpdated JWT docs. \n#6138\n\n\nFix autoescape not getting passed to urlize_quoted_links filter \n#6191\n\n\n\n\n3.8.x series\n\n\n3.8.2\n\n\nDate\n: \n6th April 2018\n\n\n\n\nFix \nread_only\n + \ndefault\n \nunique_together\n validation. \n#5922\n\n\nauthtoken.views import coreapi from rest_framework.compat, not directly. \n#5921\n\n\nDocs: Add missing argument 'detail' to Route \n#5920\n\n\n\n\n3.8.1\n\n\nDate\n: \n4th April 2018\n\n\n\n\n\n\nUse old \nurl_name\n behavior in route decorators \n#5915\n\n\nFor \nlist_route\n and \ndetail_route\n maintain the old behavior of \nurl_name\n,\nbasing it on the \nurl_path\n instead of the function name.\n\n\n\n\n\n\n3.8.0\n\n\nDate\n: \n3rd April 2018\n\n\n\n\n\n\nBreaking Change\n: Alter \nread_only\n plus \ndefault\n behaviour. \n#5886\n\n\nread_only\n fields will now \nalways\n be excluded from writable fields.\n\n\nPreviously \nread_only\n fields with a \ndefault\n value would use the \ndefault\n for create and update operations.\n\n\nIn order to maintain the old behaviour you may need to pass the value of \nread_only\n fields when calling \nsave()\n in\nthe view:\n\n\ndef perform_create(self, serializer):\n serializer.save(owner=self.request.user)\n\n\n\nAlternatively you may override \nsave()\n or \ncreate()\n or \nupdate()\n on the serialiser as appropriate.\n\n\n\n\n\n\nCorrect allow_null behaviour when required=False \n#5888\n\n\nWithout an explicit \ndefault\n, \nallow_null\n implies a default of \nnull\n for outgoing serialisation. Previously such\nfields were being skipped when read-only or otherwise not required.\n\n\nPossible backwards compatibility break\n if you were relying on such fields being excluded from the outgoing\nrepresentation. In order to restore the old behaviour you can override \ndata\n to exclude the field when \nNone\n.\n\n\nFor example:\n\n\n@property\ndef data(self):\n \"\"\"\n Drop `maybe_none` field if None.\n \"\"\"\n data = super().data\n if 'maybe_none' in data and data['maybe_none'] is None:\n del data['maybe_none']\n return data\n\n\n\n\n\n\n\nRefactor dynamic route generation and improve viewset action introspectibility. \n#5705\n\n\nViewSet\ns have been provided with new attributes and methods that allow\nit to introspect its set of actions and the details of the current action.\n\n\n\n\nMerged \nlist_route\n and \ndetail_route\n into a single \naction\n decorator.\n\n\nGet all extra actions on a \nViewSet\n with \n.get_extra_actions()\n.\n\n\nExtra actions now set the \nurl_name\n and \nurl_path\n on the decorated method.\n\n\nurl_name\n is now based on the function name, instead of the \nurl_path\n,\n as the path is not always suitable (e.g., capturing arguments in the path).\n\n\nEnable action url reversing through \n.reverse_action()\n method (added in 3.7.4)\n\n\nExample reverse call: \nself.reverse_action(self.custom_action.url_name)\n\n\nAdd \ndetail\n initkwarg to indicate if the current action is operating on a\n collection or a single instance.\n\n\n\n\nAdditional changes:\n\n\n\n\nDeprecated \nlist_route\n & \ndetail_route\n in favor of \naction\n decorator with \ndetail\n boolean.\n\n\nDeprecated dynamic list/detail route variants in favor of \nDynamicRoute\n with \ndetail\n boolean.\n\n\nRefactored the router's dynamic route generation.\n\n\nlist_route\n and \ndetail_route\n maintain the old behavior of \nurl_name\n,\n basing it on the \nurl_path\n instead of the function name.\n\n\n\n\n\n\n\n\nFix formatting of the 3.7.4 release note \n#5704\n\n\n\n\nDocs: Update DRF Writable Nested Serializers references \n#5711\n\n\nDocs: Fixed typo in auth URLs example. \n#5713\n\n\nImprove composite field child errors \n#5655\n\n\nDisable HTML inputs for dict/list fields \n#5702\n\n\nFix typo in HostNameVersioning doc \n#5709\n\n\nUse rsplit to get module and classname for imports \n#5712\n\n\nFormalize URLPatternsTestCase \n#5703\n\n\nAdd exception translation test \n#5700\n\n\nTest staticfiles \n#5701\n\n\nAdd drf-yasg to documentation and schema 3rd party packages \n#5720\n\n\nRemove unused \ncompat._resolve_model()\n \n#5733\n\n\nDrop compat workaround for unsupported Python 3.2 \n#5734\n\n\nPrefer \niter(dict)\n over \niter(dict.keys())\n \n#5736\n\n\nPass \npython_requires\n argument to setuptools \n#5739\n\n\nRemove unused links from docs \n#5735\n\n\nPrefer https protocol for links in docs when available \n#5729\n\n\nAdd HStoreField, postgres fields tests \n#5654\n\n\nAlways fully qualify ValidationError in docs \n#5751\n\n\nRemove unreachable code from ManualSchema \n#5766\n\n\nAllowed customising API documentation code samples \n#5752\n\n\nUpdated docs to use \npip show\n \n#5757\n\n\nLoad 'static' instead of 'staticfiles' in templates \n#5773\n\n\nFixed a typo in \nfields\n docs \n#5783\n\n\nRefer to \"NamespaceVersioning\" instead of \"NamespacedVersioning\" in the documentation \n#5754\n\n\nErrorDetail: add \n__eq__\n/\n__ne__\n and \n__repr__\n \n#5787\n\n\nReplace \nbackground-attachment: fixed\n in docs \n#5777\n\n\nMake 404 & 403 responses consistent with \nexceptions.APIException\n output \n#5763\n\n\nSmall fix to API documentation: schemas \n#5796\n\n\nFix schema generation for PrimaryKeyRelatedField \n#5764\n\n\nRepresent serializer DictField as an Object in schema \n#5765\n\n\nAdded docs example reimplementing ObtainAuthToken \n#5802\n\n\nAdd schema to the ObtainAuthToken view \n#5676\n\n\nFix request formdata handling \n#5800\n\n\nFix authtoken views imports \n#5818\n\n\nUpdate pytest, isort \n#5815\n \n#5817\n \n#5894\n\n\nFixed active timezone handling for non ISO8601 datetimes. \n#5833\n\n\nMade TemplateHTMLRenderer render IntegerField inputs when value is \n0\n. \n#5834\n\n\nCorrected endpoint in tutorial instructions \n#5835\n\n\nAdd Django Rest Framework Role Filters to Third party packages \n#5809\n\n\nUse single copy of static assets. Update jQuery \n#5823\n\n\nChanges ternary conditionals to be PEP308 compliant \n#5827\n\n\nAdded links to 'A Todo List API with React' and 'Blog API' tutorials \n#5837\n\n\nFix comment typo in ModelSerializer \n#5844\n\n\nAdd admin to installed apps to avoid test failures. \n#5870\n\n\nFixed schema for UUIDField in SimpleMetadata. \n#5872\n\n\nCorrected docs on router include with namespaces. \n#5843\n\n\nTest using model objects for dotted source default \n#5880\n\n\nAllow traversing nullable related fields \n#5849\n\n\nAdded: Tutorial: Django REST with React (Django 2.0) \n#5891\n\n\nAdd \nLimitOffsetPagination.get_count\n to allow method override \n#5846\n\n\nDon't show hidden fields in metadata \n#5854\n\n\nEnable OrderingFilter to handle an empty tuple (or list) for the 'ordering' field. \n#5899\n\n\nAdded generic 500 and 400 JSON error handlers. \n#5904\n\n\n\n\n3.7.x series\n\n\n3.7.7\n\n\nDate\n: \n21st December 2017\n\n\n\n\nFix typo to include *.mo locale files to packaging. \n#5697\n, \n#5695\n\n\n\n\n3.7.6\n\n\nDate\n: \n21st December 2017\n\n\n\n\nAdd missing *.ico icon files to packaging.\n\n\n\n\n3.7.5\n\n\nDate\n: \n21st December 2017\n\n\n\n\nAdd missing *.woff2 font files to packaging. \n#5692\n\n\nAdd missing *.mo locale files to packaging. \n#5695\n, \n#5696\n\n\n\n\n3.7.4\n\n\nDate\n: \n20th December 2017\n\n\n\n\n\n\nSchema: Extract method for \nmanual_fields\n processing \n#5633\n\n\nAllows for easier customisation of \nmanual_fields\n processing, for example\nto provide per-method manual fields. \nAutoSchema\n adds \nget_manual_fields\n,\nas the intended override point, and a utility method \nupdate_fields\n, to\nhandle by-name field replacement from a list, which, in general, you are not\nexpected to override.\n\n\nNote: \nAutoSchema.__init__\n now ensures \nmanual_fields\n is a list.\nPreviously may have been stored internally as \nNone\n.\n\n\n\n\n\n\nRemove ulrparse compatability shim; use six instead \n#5579\n\n\n\n\nDrop compat wrapper for \nTimeDelta.total_seconds()\n \n#5577\n\n\nClean up all whitespace throughout project \n#5578\n\n\nCompat cleanup \n#5581\n\n\nAdd pygments CSS block in browsable API views \n#5584\n \n#5587\n\n\nRemove \nset_rollback()\n from compat \n#5591\n\n\nFix request body/POST access \n#5590\n\n\nRename test to reference correct issue \n#5610\n\n\nDocumentation Fixes \n#5611\n \n#5612\n\n\nRemove references to unsupported Django versions in docs and code \n#5602\n\n\nTest Serializer exclude for declared fields \n#5599\n\n\nFixed schema generation for filter backends \n#5613\n\n\nMinor cleanup for ModelSerializer tests \n#5598\n\n\nReimplement request attribute access w/ \n__getattr__\n \n#5617\n\n\nFixed SchemaJSRenderer renders invalid Javascript \n#5607\n\n\nMake Django 2.0 support official/explicit \n#5619\n\n\nPerform type check on passed request argument \n#5618\n\n\nFix AttributeError hiding on request authenticators \n#5600\n\n\nUpdate test requirements \n#5626\n\n\nDocs: \nSerializer._declared_fields\n enable modifying fields on a serializer \n#5629\n\n\nFix packaging \n#5624\n\n\nFix readme rendering for PyPI, add readme build to CI \n#5625\n\n\nUpdate tutorial \n#5622\n\n\nNon-required fields with \nallow_null=True\n should not imply a default value \n#5639\n\n\nDocs: Add \nallow_null\n serialization output note \n#5641\n\n\nUpdate to use the Django 2.0 release in tox.ini \n#5645\n\n\nFix \nSerializer.data\n for Browsable API rendering when provided invalid \ndata\n \n#5646\n\n\nDocs: Note AutoSchema limitations on bare APIView \n#5649\n\n\nAdd \n.basename\n and \n.reverse_action()\n to ViewSet \n#5648\n\n\nDocs: Fix typos in serializers documentation \n#5652\n\n\nFix \noverride_settings\n compat \n#5668\n\n\nAdd DEFAULT_SCHEMA_CLASS setting \n#5658\n\n\nAdd docs note re generated BooleanField being \nrequired=False\n \n#5665\n\n\nAdd 'dist' build \n#5656\n\n\nFix typo in docstring \n#5678\n\n\nDocs: Add \nUNAUTHENTICATED_USER = None\n note \n#5679\n\n\nUpdate OPTIONS example from \u201cDocumenting Your API\u201d \n#5680\n\n\nDocs: Add note on object permissions for FBVs \n#5681\n\n\nDocs: Add example to \nto_representation\n docs \n#5682\n\n\nAdd link to Classy DRF in docs \n#5683\n\n\nDocument ViewSet.action \n#5685\n\n\nFix schema docs typo \n#5687\n\n\nFix URL pattern parsing in schema generation \n#5689\n\n\nAdd example using \nsource=\u2018*\u2019\n to custom field docs. \n#5688\n\n\nFix format_suffix_patterns behavior with Django 2 path() routes \n#5691\n\n\n\n\n3.7.3\n\n\nDate\n: \n6th November 2017\n\n\n\n\nFix \nAppRegistryNotReady\n error from contrib.auth view imports \n#5567\n\n\n\n\n3.7.2\n\n\nDate\n: \n6th November 2017\n\n\n\n\nFixed Django 2.1 compatibility due to removal of django.contrib.auth.login()/logout() views. \n#5510\n\n\nAdd missing import for TextLexer. \n#5512\n\n\nAdding examples and documentation for caching \n#5514\n\n\nInclude date and date-time format for schema generation \n#5511\n\n\nUse triple backticks for markdown code blocks \n#5513\n\n\nInteractive docs - make bottom sidebar items sticky \n#5516\n\n\nClarify pagination system check \n#5524\n\n\nStop JSONBoundField mangling invalid JSON \n#5527\n\n\nHave JSONField render as textarea in Browsable API \n#5530\n\n\nSchema: Exclude OPTIONS/HEAD for ViewSet actions \n#5532\n\n\nFix ordering for dotted sources \n#5533\n\n\nFix: Fields with \nallow_null=True\n should imply a default serialization value \n#5518\n\n\nEnsure Location header is strictly a 'str', not subclass. \n#5544\n\n\nAdd import to example in api-guide/parsers \n#5547\n\n\nCatch OverflowError for \"out of range\" datetimes \n#5546\n\n\nAdd djangorestframework-rapidjson to third party packages \n#5549\n\n\nIncrease test coverage for \ndrf_create_token\n command \n#5550\n\n\nAdd trove classifier for Python 3.6 support. \n#5555\n\n\nAdd pip cache support to the Travis CI configuration \n#5556\n\n\nRename [\nwheel\n] section to [\nbdist_wheel\n] as the former is legacy \n#5557\n\n\nFix invalid escape sequence deprecation warnings \n#5560\n\n\nAdd interactive docs error template \n#5548\n\n\nAdd rounding parameter to DecimalField \n#5562\n\n\nFix all BytesWarning caught during tests \n#5561\n\n\nUse dict and set literals instead of calls to dict() and set() \n#5559\n\n\nChange ImageField validation pattern, use validators from DjangoImageField \n#5539\n\n\nFix processing unicode symbols in query_string by Python 2 \n#5552\n\n\n\n\n3.7.1\n\n\nDate\n: \n16th October 2017\n\n\n\n\nFix Interactive documentation always uses false for boolean fields in requests \n#5492\n\n\nImprove compatibility with Django 2.0 alpha. \n#5500\n \n#5503\n\n\nImproved handling of schema naming collisions \n#5486\n\n\nAdded additional docs and tests around providing a default value for dotted \nsource\n fields \n#5489\n\n\n\n\n3.7.0\n\n\nDate\n: \n6th October 2017\n\n\n\n\nFix \nDjangoModelPermissions\n to ensure user authentication before calling the view's \nget_queryset()\n method. As a side effect, this changes the order of the HTTP method permissions and authentication checks, and 405 responses will only be returned when authenticated. If you want to replicate the old behavior, see the PR for details. \n#5376\n\n\nDeprecated \nexclude_from_schema\n on \nAPIView\n and \napi_view\n decorator. Set \nschema = None\n or \n@schema(None)\n as appropriate. \n#5422\n\n\n\n\nTimezone-aware \nDateTimeField\ns now respect active or default \ntimezone\n during serialization, instead of always using UTC. \n#5435\n\n\nResolves inconsistency whereby instances were serialised with supplied datetime for \ncreate\n but UTC for \nretrieve\n. \n#3732\n\n\nPossible backwards compatibility break\n if you were relying on datetime strings being UTC. Have client interpret datetimes or \nset default or active timezone (docs)\n to UTC if needed.\n\n\n\n\n\n\nRemoved DjangoFilterBackend inline with deprecation policy. Use \ndjango_filters.rest_framework.FilterSet\n and/or \ndjango_filters.rest_framework.DjangoFilterBackend\n instead. \n#5273\n\n\n\n\nDon't strip microseconds from \ntime\n when encoding. Makes consistent with \ndatetime\n.\n \nBC Change\n: Previously only milliseconds were encoded. \n#5440\n\n\nAdded \nSTRICT_JSON\n setting (default \nTrue\n) to raise exception for the extended float values (\nnan\n, \ninf\n, \n-inf\n) accepted by Python's \njson\n module.\n \nBC Change\n: Previously these values would converted to corresponding strings. Set \nSTRICT_JSON\n to \nFalse\n to restore the previous behaviour. \n#5265\n\n\nAdd support for \npage_size\n parameter in CursorPaginator class \n#5250\n\n\nMake \nDEFAULT_PAGINATION_CLASS\n \nNone\n by default.\n \nBC Change\n: If your were \njust\n setting \nPAGE_SIZE\n to enable pagination you will need to add \nDEFAULT_PAGINATION_CLASS\n.\n The previous default was \nrest_framework.pagination.PageNumberPagination\n. There is a system check warning to catch this case. You may silence that if you are setting pagination class on a per-view basis. \n#5170\n\n\nCatch \nAPIException\n from \nget_serializer_fields\n in schema generation. \n#5443\n\n\nAllow custom authentication and permission classes when using \ninclude_docs_urls\n \n#5448\n\n\nDefer translated string evaluation on validators. \n#5452\n\n\nAdded default value for 'detail' param into 'ValidationError' exception \n#5342\n\n\nAdjust schema get_filter_fields rules to match framework \n#5454\n\n\nUpdated test matrix to add Django 2.0 and drop Django 1.8 & 1.9\n \nBC Change\n: This removes Django 1.8 and Django 1.9 from Django REST Framework supported versions. \n#5457\n\n\nFixed a deprecation warning in serializers.ModelField \n#5058\n\n\nAdded a more explicit error message when \nget_queryset\n returned \nNone\n \n#5348\n\n\nFix docs for Response \ndata\n description \n#5361\n\n\nFix \npycache\n/.pyc excludes when packaging \n#5373\n\n\nFix default value handling for dotted sources \n#5375\n\n\nEnsure content_type is set when passing empty body to RequestFactory \n#5351\n\n\nFix ErrorDetail Documentation \n#5380\n\n\nAllow optional content in the generic content form \n#5372\n\n\nUpdated supported values for the NullBooleanField \n#5387\n\n\nFix ModelSerializer custom named fields with source on model \n#5388\n\n\nFixed the MultipleFieldLookupMixin documentation example to properly check for object level permission \n#5398\n\n\nUpdate get_object() example in permissions.md \n#5401\n\n\nFix authtoken management command \n#5415\n\n\nFix schema generation markdown \n#5421\n\n\nAllow \nChoiceField.choices\n to be set dynamically \n#5426\n\n\nAdd the project layout to the quickstart \n#5434\n\n\nReuse 'apply_markdown' function in 'render_markdown' templatetag \n#5469\n\n\nAdded links to \ndrf-openapi\n package in docs \n#5470\n\n\nAdded docstrings code highlighting with pygments \n#5462\n\n\nFixed documentation rendering for views named \ndata\n \n#5472\n\n\nDocs: Clarified 'to_internal_value()' validation behavior \n#5466\n\n\nFix missing six.text_type() call on APIException.\nstr\n \n#5476\n\n\nDocument documentation.py \n#5478\n\n\nFix naming collisions in Schema Generation \n#5464\n\n\nCall Django's authenticate function with the request object \n#5295\n\n\nUpdate coreapi JS to 0.1.1 \n#5479\n\n\nHave \nis_list_view\n recognise RetrieveModel\u2026 views \n#5480\n\n\nRemove Django 1.8 & 1.9 compatibility code \n#5481\n\n\nRemove deprecated schema code from DefaultRouter \n#5482\n\n\nRefactor schema generation to allow per-view customisation.\n \nBC Change\n: \nSchemaGenerator.get_serializer_fields\n has been refactored as \nAutoSchema.get_serializer_fields\n and drops the \nview\n argument [#5354][gh5354]\n\n\n\n\n3.6.x series\n\n\n3.6.4\n\n\nDate\n: \n21st August 2017\n\n\n\n\nIgnore any invalidly formed query parameters for OrderingFilter. \n#5131\n\n\nImprove memory footprint when reading large JSON requests. \n#5147\n\n\nFix schema generation for pagination. \n#5161\n\n\nFix exception when \nHTML_CUTOFF\n is set to \nNone\n. \n#5174\n\n\nFix browsable API not supporting \nmultipart/form-data\n correctly. \n#5176\n\n\nFixed \ntest_hyperlinked_related_lookup_url_encoded_exists\n. \n#5179\n\n\nMake sure max_length is in FileField kwargs. \n#5186\n\n\nFix \nlist_route\n & \ndetail_route\n with kwargs contains curly bracket in \nurl_path\n \n#5187\n\n\nAdd Django manage command to create a DRF user Token. \n#5188\n\n\nEnsure API documentation templates do not check for user authentication \n#5162\n\n\nFix special case where OneToOneField is also primary key. \n#5192\n\n\nAdded aria-label and a new region for accessibility purposes in base.html \n#5196\n\n\nQuote nested API parameters in api.js. \n#5214\n\n\nSet ViewSet args/kwargs/request before dispatch. \n#5229\n\n\nAdded unicode support to SlugField. \n#5231\n\n\nFix HiddenField appears in Raw Data form initial content. \n#5259\n\n\nRaise validation error on invalid timezone parsing. \n#5261\n\n\nFix SearchFilter to-many behavior/performance. \n#5264\n\n\nSimplified chained comparisons and minor code fixes. \n#5276\n\n\nRemoteUserAuthentication, docs, and tests. \n#5306\n\n\nRevert \"Cached the field's root and context property\" \n#5313\n\n\nFix introspection of list field in schema. \n#5326\n\n\nFix interactive docs for multiple nested and extra methods. \n#5334\n\n\nFix/remove undefined template var \"schema\" \n#5346\n\n\n\n\n3.6.3\n\n\nDate\n: \n12th May 2017\n\n\n\n\nRaise 404 if a URL lookup results in ValidationError. (\n#5126\n)\n\n\nHonor http_method_names on class based view, when generating API schemas. (\n#5085\n)\n\n\nAllow overridden \nget_limit\n in LimitOffsetPagination to return all records. (\n#4437\n)\n\n\nFix partial update for the ListSerializer. (\n#4222\n)\n\n\nRender JSONField control correctly in browsable API. (\n#4999\n, \n#5042\n)\n\n\nRaise validation errors for invalid datetime in given timezone. (\n#4987\n)\n\n\nSupport restricting doc & schema shortcuts to a subset of urls. (\n#4979\n)\n\n\nResolve SchemaGenerator error with paginators that have no \npage_size\n attribute. (\n#5086\n, \n#3692\n)\n\n\nResolve HyperlinkedRelatedField exception on string with %20 instead of space. (\n#4748\n, \n#5078\n)\n\n\nCustomizable schema generator classes. (\n#5082\n)\n\n\nUpdate existing vary headers in response instead of overwriting them. (\n#5047\n)\n\n\nSupport passing \n.as_view()\n to view instance. (\n#5053\n)\n\n\nUse correct exception handler when settings overridden on a view. (\n#5055\n, \n#5054\n)\n\n\nUpdate Boolean field to support 'yes' and 'no' values. (\n#5038\n)\n\n\nFix unique validator for ChoiceField. (\n#5004\n, \n#5026\n, \n#5028\n)\n\n\nJavaScript cleanups in API Docs. (\n#5001\n)\n\n\nInclude URL path regexs in API schemas where valid. (\n#5014\n)\n\n\nCorrectly set scheme in coreapi TokenAuthentication. (\n#5000\n, \n#4994\n)\n\n\nHEAD requests on ViewSets should not return 405. (\n#4705\n, \n#4973\n, \n#4864\n)\n\n\nSupport usage of 'source' in \nextra_kwargs\n. (\n#4688\n)\n\n\nFix invalid content type for schema.js (\n#4968\n)\n\n\nFix DjangoFilterBackend inheritance issues. (\n#5089\n, \n#5117\n)\n\n\n\n\n3.6.2\n\n\nDate\n: \n10th March 2017\n\n\n\n\nSupport for Safari & IE in API docs. (\n#4959\n, \n#4961\n)\n\n\nAdd missing \nmark_safe\n in API docs template tags. (\n#4952\n, \n#4953\n)\n\n\nAdd missing glyphicon fonts. (\n#4950\n, \n#4951\n)\n\n\nFix One-to-one fields in API docs. (\n#4955\n, \n#4956\n)\n\n\nTest clean ups. (\n#4949\n)\n\n\n\n\n3.6.1\n\n\nDate\n: \n9th March 2017\n\n\n\n\nEnsure \nmarkdown\n dependency is optional. (\n#4947\n)\n\n\n\n\n3.6.0\n\n\nDate\n: \n9th March 2017\n\n\nSee the \nrelease announcement\n.\n\n\n\n\n3.5.x series\n\n\n3.5.4\n\n\nDate\n: \n10th February 2017\n\n\n\n\nAdd max_length and min_length arguments for ListField. (\n#4877\n)\n\n\nAdd per-view custom exception handler support. (\n#4753\n)\n\n\nSupport disabling of declared fields on serializer subclasses. (\n#4764\n)\n\n\nSupport custom view names on \n@list_route\n and \n@detail_route\n endpoints. (\n#4821\n)\n\n\nCorrect labels for fields in login template when custom user model is used. (\n#4841\n)\n\n\nWhitespace fixes for descriptions generated from docstrings. (\n#4759\n, \n#4869\n, \n#4870\n)\n\n\nBetter error reporting when schemas are returned by views without a schema renderer. (\n#4790\n)\n\n\nFix for returned response of \nPUT\n requests when \nprefetch_related\n is used. (\n#4661\n, \n#4668\n)\n\n\nFix for breadcrumb view names. (\n#4750\n)\n\n\nFix for RequestsClient ensuring fully qualified URLs. (\n#4678\n)\n\n\nFix for incorrect behavior of writable-nested fields check in some cases. (\n#4634\n, \n#4669\n)\n\n\nResolve Django deprecation warnings. (\n#4712\n)\n\n\nVarious cleanup of test cases.\n\n\n\n\n3.5.3\n\n\nDate\n: \n7th November 2016\n\n\n\n\nDon't raise incorrect FilterSet deprecation warnings. (\n#4660\n, \n#4643\n, \n#4644\n)\n\n\nSchema generation should not raise 404 when a view permission class does. (\n#4645\n, \n#4646\n)\n\n\nAdd \nautofocus\n support for input controls. (\n#4650\n)\n\n\n\n\n3.5.2\n\n\nDate\n: \n1st November 2016\n\n\n\n\nRestore exception tracebacks in Python 2.7. (\n#4631\n, \n#4638\n)\n\n\nProperly display dicts in the admin console. (\n#4532\n, \n#4636\n)\n\n\nFix is_simple_callable with variable args, kwargs. (\n#4622\n, \n#4602\n)\n\n\nSupport 'on'/'off' literals with BooleanField. (\n#4640\n, \n#4624\n)\n\n\nEnable cursor pagination of value querysets. (\n#4569\n)\n\n\nFix support of get_full_details() for Throttled exceptions. (\n#4627\n)\n\n\nFix FilterSet proxy. (\n#4620\n)\n\n\nMake serializer fields import explicit. (\n#4628\n)\n\n\nDrop redundant requests adapter. (\n#4639\n)\n\n\n\n\n3.5.1\n\n\nDate\n: \n21st October 2016\n\n\n\n\nMake \nrest_framework/compat.py\n imports. (\n#4612\n, \n#4608\n, \n#4601\n)\n\n\nFix bug in schema base path generation. (\n#4611\n, \n#4605\n)\n\n\nFix broken case of ListSerializer with single item. (\n#4609\n, \n#4606\n)\n\n\nRemove bare \nraise\n for Python 3.5 compat. (\n#4600\n)\n\n\n\n\n3.5.0\n\n\nDate\n: \n20th October 2016\n\n\n\n\n3.4.x series\n\n\n3.4.7\n\n\nDate\n: \n21st September 2016\n\n\n\n\nFallback behavior for request parsing when request.POST already accessed. (\n#3951\n, \n#4500\n)\n\n\nFix regression of \nRegexField\n. (\n#4489\n, \n#4490\n, \n#2617\n)\n\n\nMissing comma in \nadmin.html\n causing CSRF error. (\n#4472\n, \n#4473\n)\n\n\nFix response rendering with empty context. (\n#4495\n)\n\n\nFix indentation regression in API listing. (\n#4493\n)\n\n\nFixed an issue where the incorrect value is set to \nResolverMatch.func_name\n of api_view decorated view. (\n#4465\n, \n#4462\n)\n\n\nFix \nAPIClient.get()\n when path contains unicode arguments (\n#4458\n)\n\n\n\n\n3.4.6\n\n\nDate\n: \n23rd August 2016\n\n\n\n\nFix malformed Javascript in browsable API. (\n#4435\n)\n\n\nSkip HiddenField from Schema fields. (\n#4425\n, \n#4429\n)\n\n\nImprove Create to show the original exception traceback. (\n#3508\n)\n\n\nFix \nAdminRenderer\n display of PK only related fields. (\n#4419\n, \n#4423\n)\n\n\n\n\n3.4.5\n\n\nDate\n: \n19th August 2016\n\n\n\n\nImprove debug error handling. (\n#4416\n, \n#4409\n)\n\n\nAllow custom CSRF_HEADER_NAME setting. (\n#4415\n, \n#4410\n)\n\n\nInclude .action attribute on viewsets when generating schemas. (\n#4408\n, \n#4398\n)\n\n\nDo not include request.FILES items in request.POST. (\n#4407\n)\n\n\nFix rendering of checkbox multiple. (\n#4403\n)\n\n\nFix docstring of Field.get_default. (\n#4404\n)\n\n\nReplace utf8 character with its ascii counterpart in README. (\n#4412\n)\n\n\n\n\n3.4.4\n\n\nDate\n: \n12th August 2016\n\n\n\n\nEnsure views are fully initialized when generating schemas. (\n#4373\n, \n#4382\n, \n#4383\n, \n#4279\n, \n#4278\n)\n\n\nAdd form field descriptions to schemas. (\n#4387\n)\n\n\nFix category generation for schema endpoints. (\n#4391\n, \n#4394\n, \n#4390\n, \n#4386\n, \n#4376\n, \n#4329\n)\n\n\nDon't strip empty query params when paginating. (\n#4392\n, \n#4393\n, \n#4260\n)\n\n\nDo not re-run query for empty results with LimitOffsetPagination. (\n#4201\n, \n#4388\n)\n\n\nStricter type validation for CharField. (\n#4380\n, \n#3394\n)\n\n\nRelatedField.choices should preserve non-string values. (\n#4111\n, \n#4379\n, \n#3365\n)\n\n\nTest case for rendering checkboxes in vertical form style. (\n#4378\n, \n#3868\n, \n#3868\n)\n\n\nShow error traceback HTML in browsable API (\n#4042\n, \n#4172\n)\n\n\nFix handling of ALLOWED_VERSIONS and no DEFAULT_VERSION. \n#4370\n\n\nAllow \nmax_digits=None\n on DecimalField. (\n#4377\n, \n#4372\n)\n\n\nLimit queryset when rendering relational choices. (\n#4375\n, \n#4122\n, \n#3329\n, \n#3330\n, \n#3877\n)\n\n\nResolve form display with ChoiceField, MultipleChoiceField and non-string choices. (\n#4374\n, \n#4119\n, \n#4121\n, \n#4137\n, \n#4120\n)\n\n\nFix call to TemplateHTMLRenderer.resolve_context() fallback method. (\n#4371\n)\n\n\n\n\n3.4.3\n\n\nDate\n: \n5th August 2016\n\n\n\n\nInclude fallback for users of older TemplateHTMLRenderer internal API. (\n#4361\n)\n\n\n\n\n3.4.2\n\n\nDate\n: \n5th August 2016\n\n\n\n\nInclude kwargs passed to 'as_view' when generating schemas. (\n#4359\n, \n#4330\n, \n#4331\n)\n\n\nAccess \nrequest.user.is_authenticated\n as property not method, under Django 1.10+ (\n#4358\n, \n#4354\n)\n\n\nFilter HEAD out from schemas. (\n#4357\n)\n\n\nextra_kwargs takes precedence over uniqueness kwargs. (\n#4198\n, \n#4199\n, \n#4349\n)\n\n\nCorrect descriptions when tabs are used in code indentation. (\n#4345\n, \n#4347\n)*\n\n\nChange template context generation in TemplateHTMLRenderer. (\n#4236\n)\n\n\nSerializer defaults should not be included in partial updates. (\n#4346\n, \n#3565\n)\n\n\nConsistent behavior & descriptive error from FileUploadParser when filename not included. (\n#4340\n, \n#3610\n, \n#4292\n, \n#4296\n)\n\n\nDecimalField quantizes incoming digitals. (\n#4339\n, \n#4318\n)\n\n\nHandle non-string input for IP fields. (\n#4335\n, \n#4336\n, \n#4338\n)\n\n\nFix leading slash handling when Schema generation includes a root URL. (\n#4332\n)\n\n\nTest cases for DictField with allow_null options. (\n#4348\n)\n\n\nUpdate tests from Django 1.10 beta to Django 1.10. (\n#4344\n)\n\n\n\n\n3.4.1\n\n\nDate\n: \n28th July 2016\n\n\n\n\nAdded \nroot_renderers\n argument to \nDefaultRouter\n. (\n#4323\n, \n#4268\n)\n\n\nAdded \nurl\n and \nschema_url\n arguments. (\n#4321\n, \n#4308\n, \n#4305\n)\n\n\nUnique together checks should apply to read-only fields which have a default. (\n#4316\n, \n#4294\n)\n\n\nSet view.format_kwarg in schema generator. (\n#4293\n, \n#4315\n)\n\n\nFix schema generator for views with \npagination_class = None\n. (\n#4314\n, \n#4289\n)\n\n\nFix schema generator for views with no \nget_serializer_class\n. (\n#4265\n, \n#4285\n)\n\n\nFixes for media type parameters in \nAccept\n and \nContent-Type\n headers. (\n#4287\n, \n#4313\n, \n#4281\n)\n\n\nUse verbose_name instead of object_name in error messages. (\n#4299\n)\n\n\nMinor version update to Twitter Bootstrap. (\n#4307\n)\n\n\nSearchFilter raises error when using with related field. (\n#4302\n, \n#4303\n, \n#4298\n)\n\n\nAdding support for RFC 4918 status codes. (\n#4291\n)\n\n\nAdd LICENSE.md to the built wheel. (\n#4270\n)\n\n\nSerializing \"complex\" field returns None instead of the value since 3.4 (\n#4272\n, \n#4273\n, \n#4288\n)\n\n\n\n\n3.4.0\n\n\nDate\n: \n14th July 2016\n\n\n\n\nDon't strip microseconds in JSON output. (\n#4256\n)\n\n\nTwo slightly different iso 8601 datetime serialization. (\n#4255\n)\n\n\nResolve incorrect inclusion of media type parameters. (\n#4254\n)\n\n\nResponse Content-Type potentially malformed. (\n#4253\n)\n\n\nFix setup.py error on some platforms. (\n#4246\n)\n\n\nMove alternate formats in coreapi into separate packages. (\n#4244\n)\n\n\nAdd localize keyword argument to \nDecimalField\n. (\n#4233\n)\n\n\nFix issues with routers for custom list-route and detail-routes. (\n#4229\n)\n\n\nNamespace versioning with nested namespaces. (\n#4219\n)\n\n\nRobust uniqueness checks. (\n#4217\n)\n\n\nMinor refactoring of \nmust_call_distinct\n. (\n#4215\n)\n\n\nOverridable offset cutoff in CursorPagination. (\n#4212\n)\n\n\nPass through strings as-in with date/time fields. (\n#4196\n)\n\n\nAdd test confirming that required=False is valid on a relational field. (\n#4195\n)\n\n\nIn LimitOffsetPagination \nlimit=0\n should revert to default limit. (\n#4194\n)\n\n\nExclude read_only=True fields from unique_together validation & add docs. (\n#4192\n)\n\n\nHandle bytestrings in JSON. (\n#4191\n)\n\n\nJSONField(binary=True) represents using binary strings, which JSONRenderer does not support. (\n#4187\n)\n\n\nJSONField(binary=True) represents using binary strings, which JSONRenderer does not support. (\n#4185\n)\n\n\nMore robust form rendering in the browsable API. (\n#4181\n)\n\n\nEmpty cases of \n.validated_data\n and \n.errors\n as lists not dicts for ListSerializer. (\n#4180\n)\n\n\nSchemas & client libraries. (\n#4179\n)\n\n\nRemoved \nAUTH_USER_MODEL\n compat property. (\n#4176\n)\n\n\nClean up existing deprecation warnings. (\n#4166\n)\n\n\nDjango 1.10 support. (\n#4158\n)\n\n\nUpdated jQuery version to 1.12.4. (\n#4157\n)\n\n\nMore robust default behavior on OrderingFilter. (\n#4156\n)\n\n\ndescription.py codes and tests removal. (\n#4153\n)\n\n\nWrap guardian.VERSION in tuple. (\n#4149\n)\n\n\nRefine validator for fields with \n kwargs. (\n#4146\n)\n\n\nFix None values representation in childs of ListField, DictField. (\n#4118\n)\n\n\nResolve TimeField representation for midnight value. (\n#4107\n)\n\n\nSet proper status code in AdminRenderer for the redirection after POST/DELETE requests. (\n#4106\n)\n\n\nTimeField render returns None instead of 00:00:00. (\n#4105\n)\n\n\nFix incorrectly named zh-hans and zh-hant locale path. (\n#4103\n)\n\n\nPrevent raising exception when limit is 0. (\n#4098\n)\n\n\nTokenAuthentication: Allow custom keyword in the header. (\n#4097\n)\n\n\nHandle incorrectly padded HTTP basic auth header. (\n#4090\n)\n\n\nLimitOffset pagination crashes Browseable API when limit=0. (\n#4079\n)\n\n\nFixed DecimalField arbitrary precision support. (\n#4075\n)\n\n\nAdded support for custom CSRF cookie names. (\n#4049\n)\n\n\nFix regression introduced by #4035. (\n#4041\n)\n\n\nNo auth view failing permission should raise 403. (\n#4040\n)\n\n\nFix string_types / text_types confusion. (\n#4025\n)\n\n\nDo not list related field choices in OPTIONS requests. (\n#4021\n)\n\n\nFix typo. (\n#4008\n)\n\n\nReorder initializing the view. (\n#4006\n)\n\n\nType error in DjangoObjectPermissionsFilter on Python 3.4. (\n#4005\n)\n\n\nFixed use of deprecated Query.aggregates. (\n#4003\n)\n\n\nFix blank lines around docstrings. (\n#4002\n)\n\n\nFixed admin pagination when limit is 0. (\n#3990\n)\n\n\nOrderingFilter adjustments. (\n#3983\n)\n\n\nNon-required serializer related fields. (\n#3976\n)\n\n\nUsing safer calling way of \"@api_view\" in tutorial. (\n#3971\n)\n\n\nListSerializer doesn't handle unique_together constraints. (\n#3970\n)\n\n\nAdd missing migration file. (\n#3968\n)\n\n\nOrderingFilter\n should call \nget_serializer_class()\n to determine default fields. (\n#3964\n)\n\n\nRemove old Django checks from tests and compat. (\n#3953\n)\n\n\nSupport callable as the value of \ninitial\n for any \nserializer.Field\n. (\n#3943\n)\n\n\nPrevented unnecessary distinct() call in SearchFilter. (\n#3938\n)\n\n\nFix None UUID ForeignKey serialization. (\n#3936\n)\n\n\nDrop EOL Django 1.7. (\n#3933\n)\n\n\nAdd missing space in serializer error message. (\n#3926\n)\n\n\nFixed _force_text_recursive typo. (\n#3908\n)\n\n\nAttempt to address Django 2.0 deprecate warnings related to \nfield.rel\n. (\n#3906\n)\n\n\nFix parsing multipart data using a nested serializer with list. (\n#3820\n)\n\n\nResolving APIs URL to different namespaces. (\n#3816\n)\n\n\nDo not HTML-escape \nhelp_text\n in Browsable API forms. (\n#3812\n)\n\n\nOPTIONS fetches and shows all possible foreign keys in choices field. (\n#3751\n)\n\n\nDjango 1.9 deprecation warnings (\n#3729\n)\n\n\nTest case for #3598 (\n#3710\n)\n\n\nAdding support for multiple values for search filter. (\n#3541\n)\n\n\nUse get_serializer_class in ordering filter. (\n#3487\n)\n\n\nSerializers with many=True should return empty list rather than empty dict. (\n#3476\n)\n\n\nLimitOffsetPagination limit=0 fix. (\n#3444\n)\n\n\nEnable Validators to defer string evaluation and handle new string format. (\n#3438\n)\n\n\nUnique validator is executed and breaks if field is invalid. (\n#3381\n)\n\n\nDo not ignore overridden View.get_view_name() in breadcrumbs. (\n#3273\n)\n\n\nRetry form rendering when rendering with serializer fails. (\n#3164\n)\n\n\nUnique constraint prevents nested serializers from updating. (\n#2996\n)\n\n\nUniqueness validators should not be run for excluded (read_only) fields. (\n#2848\n)\n\n\nUniqueValidator raises exception for nested objects. (\n#2403\n)\n\n\nlookup_type\n is deprecated in favor of \nlookup_expr\n. (\n#4259\n)\n\n\n\n\n\n\n3.3.x series\n\n\n3.3.3\n\n\nDate\n: \n14th March 2016\n.\n\n\n\n\nRemove version string from templates. Thanks to @blag for the report and fixes. (\n#3878\n, \n#3913\n, \n#3912\n)\n\n\nFixes vertical html layout for \nBooleanField\n. Thanks to Mikalai Radchuk for the fix. (\n#3910\n)\n\n\nSilenced deprecation warnings on Django 1.8. Thanks to Simon Charette for the fix. (\n#3903\n)\n\n\nInternationalization for authtoken. Thanks to Michael Nacharov for the fix. (\n#3887\n, \n#3968\n)\n\n\nFix \nToken\n model as \nabstract\n when the authtoken application isn't declared. Thanks to Adam Thomas for the report. (\n#3860\n, \n#3858\n)\n\n\nImprove Markdown version compatibility. Thanks to Michael J. Schultz for the fix. (\n#3604\n, \n#3842\n)\n\n\nQueryParameterVersioning\n does not use \nDEFAULT_VERSION\n setting. Thanks to Brad Montgomery for the fix. (\n#3833\n)\n\n\nAdd an explicit \non_delete\n on the models. Thanks to Mads Jensen for the fix. (\n#3832\n)\n\n\nFix \nDateField.to_representation\n to work with Python 2 unicode. Thanks to Mikalai Radchuk for the fix. (\n#3819\n)\n\n\nFixed \nTimeField\n not handling string times. Thanks to Areski Belaid for the fix. (\n#3809\n)\n\n\nAvoid updates of \nMeta.extra_kwargs\n. Thanks to Kevin Massey for the report and fix. (\n#3805\n, \n#3804\n)\n\n\nFix nested validation error being rendered incorrectly. Thanks to Craig de Stigter for the fix. (\n#3801\n)\n\n\nDocument how to avoid CSRF and missing button issues with \ndjango-crispy-forms\n. Thanks to Emmanuelle Delescolle, Jos\u00e9 Padilla and Luis San Pablo for the report, analysis and fix. (\n#3787\n, \n#3636\n, \n#3637\n)\n\n\nImprove Rest Framework Settings file setup time. Thanks to Miles Hutson for the report and Mads Jensen for the fix. (\n#3786\n, \n#3815\n)\n\n\nImprove authtoken compatibility with Django 1.9. Thanks to S. Andrew Sheppard for the fix. (\n#3785\n)\n\n\nFix \nMin/MaxValueValidator\n transfer from a model's \nDecimalField\n. Thanks to Kevin Brown for the fix. (\n#3774\n)\n\n\nImprove HTML title in the Browsable API. Thanks to Mike Lissner for the report and fix. (\n#3769\n)\n\n\nFix \nAutoFilterSet\n to inherit from \ndefault_filter_set\n. Thanks to Tom Linford for the fix. (\n#3753\n)\n\n\nFix transifex config to handle the new Chinese language codes. Thanks to @nypisces for the report and fix. (\n#3739\n)\n\n\nDateTimeField\n does not handle empty values correctly. Thanks to Mick Parker for the report and fix. (\n#3731\n, \n#3726\n)\n\n\nRaise error when setting a removed rest_framework setting. Thanks to Luis San Pablo for the fix. (\n#3715\n)\n\n\nAdd missing csrf_token in AdminRenderer post form. Thanks to Piotr \u015aniegowski for the fix. (\n#3703\n)\n\n\nRefactored \n_get_reverse_relationships()\n to use correct \nto_field\n. Thanks to Benjamin Phillips for the fix. (\n#3696\n)\n\n\nDocument the use of \nget_queryset\n for \nRelatedField\n. Thanks to Ryan Hiebert for the fix. (\n#3605\n)\n\n\nFix empty pk detection in HyperlinkRelatedField.get_url. Thanks to @jslang for the fix (\n#3962\n)\n\n\n\n\n3.3.2\n\n\nDate\n: \n14th December 2015\n.\n\n\n\n\nListField\n enforces input is a list. (\n#3513\n)\n\n\nFix regression hiding raw data form. (\n#3600\n, \n#3578\n)\n\n\nFix Python 3.5 compatibility. (\n#3534\n, \n#3626\n)\n\n\nAllow setting a custom Django Paginator in \npagination.PageNumberPagination\n. (\n#3631\n, \n#3684\n)\n\n\nFix relational fields without \nto_fields\n attribute. (\n#3635\n, \n#3634\n)\n\n\nFix \ntemplate.render\n deprecation warnings for Django 1.9. (\n#3654\n)\n\n\nSort response headers in browsable API renderer. (\n#3655\n)\n\n\nUse related_objects api for Django 1.9+. (\n#3656\n, \n#3252\n)\n\n\nAdd confirm modal when deleting. (\n#3228\n, \n#3662\n)\n\n\nReveal previously hidden AttributeErrors and TypeErrors while calling has_[object_]permissions. (\n#3668\n)\n\n\nMake DRF compatible with multi template engine in Django 1.8. (\n#3672\n)\n\n\nUpdate \nNestedBoundField\n to also handle empty string when rendering its form. (\n#3677\n)\n\n\nFix UUID validation to properly catch invalid input types. (\n#3687\n, \n#3679\n)\n\n\nFix caching issues. (\n#3628\n, \n#3701\n)\n\n\nFix Admin and API browser for views without a filter_class. (\n#3705\n, \n#3596\n, \n#3597\n)\n\n\nAdd app_name to rest_framework.urls. (\n#3714\n)\n\n\nImprove authtoken's views to support url versioning. (\n#3718\n, \n#3723\n)\n\n\n\n\n3.3.1\n\n\nDate\n: \n4th November 2015\n.\n\n\n\n\nResolve parsing bug when accessing \nrequest.POST\n (\n#3592\n)\n\n\nCorrectly deal with \nto_field\n referring to primary key. (\n#3593\n)\n\n\nAllow filter HTML to render when no \nfilter_class\n is defined. (\n#3560\n)\n\n\nFix admin rendering issues. (\n#3564\n, \n#3556\n)\n\n\nFix issue with DecimalValidator. (\n#3568\n)\n\n\n\n\n3.3.0\n\n\nDate\n: \n28th October 2015\n.\n\n\n\n\nHTML controls for filters. (\n#3315\n)\n\n\nForms API. (\n#3475\n)\n\n\nAJAX browsable API. (\n#3410\n)\n\n\nAdded JSONField. (\n#3454\n)\n\n\nCorrectly map \nto_field\n when creating \nModelSerializer\n relational fields. (\n#3526\n)\n\n\nInclude keyword arguments when mapping \nFilePathField\n to a serializer field. (\n#3536\n)\n\n\nMap appropriate model \nerror_messages\n on \nModelSerializer\n uniqueness constraints. (\n#3435\n)\n\n\nInclude \nmax_length\n constraint for \nModelSerializer\n fields mapped from TextField. (\n#3509\n)\n\n\nAdded support for Django 1.9. (\n#3450\n, \n#3525\n)\n\n\nRemoved support for Django 1.5 & 1.6. (\n#3421\n, \n#3429\n)\n\n\nRemoved 'south' migrations. (\n#3495\n)\n\n\n\n\n\n\n3.2.x series\n\n\n3.2.5\n\n\nDate\n: \n27th October 2015\n.\n\n\n\n\nEscape \nusername\n in optional logout tag. (\n#3550\n)\n\n\n\n\n3.2.4\n\n\nDate\n: \n21th September 2015\n.\n\n\n\n\nDon't error on missing \nViewSet.search_fields\n attribute. (\n#3324\n, \n#3323\n)\n\n\nFix \nallow_empty\n not working on serializers with \nmany=True\n. (\n#3361\n, \n#3364\n)\n\n\nLet \nDurationField\n accepts integers. (\n#3359\n)\n\n\nMulti-level dictionaries not supported in multipart requests. (\n#3314\n)\n\n\nFix \nListField\n truncation on HTTP PATCH (\n#3415\n, \n#2761\n)\n\n\n\n\n3.2.3\n\n\nDate\n: \n24th August 2015\n.\n\n\n\n\nAdded \nhtml_cutoff\n and \nhtml_cutoff_text\n for limiting select dropdowns. (\n#3313\n)\n\n\nAdded regex style to \nSearchFilter\n. (\n#3316\n)\n\n\nResolve issues with setting blank HTML fields. (\n#3318\n) (\n#3321\n)\n\n\nCorrectly display existing 'select multiple' values in browsable API forms. (\n#3290\n)\n\n\nResolve duplicated validation message for \nIPAddressField\n. ([#3249[gh3249]) (\n#3250\n)\n\n\nFix to ensure admin renderer continues to work when pagination is disabled. (\n#3275\n)\n\n\nResolve error with \nLimitOffsetPagination\n when count=0, offset=0. (\n#3303\n)\n\n\n\n\n3.2.2\n\n\nDate\n: \n13th August 2015\n.\n\n\n\n\nAdd \ndisplay_value()\n method for use when displaying relational field select inputs. (\n#3254\n)\n\n\nFix issue with \nBooleanField\n checkboxes incorrectly displaying as checked. (\n#3258\n)\n\n\nEnsure empty checkboxes properly set \nBooleanField\n to \nFalse\n in all cases. (\n#2776\n)\n\n\nAllow \nWSGIRequest.FILES\n property without raising incorrect deprecated error. (\n#3261\n)\n\n\nResolve issue with rendering nested serializers in forms. (\n#3260\n)\n\n\nRaise an error if user accidentally pass a serializer instance to a response, rather than data. (\n#3241\n)\n\n\n\n\n3.2.1\n\n\nDate\n: \n7th August 2015\n.\n\n\n\n\nFix for relational select widgets rendering without any choices. (\n#3237\n)\n\n\nFix for \n1\n, \n0\n rendering as \ntrue\n, \nfalse\n in the admin interface. \n#3227\n)\n\n\nFix for ListFields with single value in HTML form input. (\n#3238\n)\n\n\nAllow \nrequest.FILES\n for compat with Django's \nHTTPRequest\n class. (\n#3239\n)\n\n\n\n\n3.2.0\n\n\nDate\n: \n6th August 2015\n.\n\n\n\n\nAdd \nAdminRenderer\n. (\n#2926\n)\n\n\nAdd \nFilePathField\n. (\n#1854\n)\n\n\nAdd \nallow_empty\n to \nListField\n. (\n#2250\n)\n\n\nSupport django-guardian 1.3. (\n#3165\n)\n\n\nSupport grouped choices. (\n#3225\n)\n\n\nSupport error forms in browsable API. (\n#3024\n)\n\n\nAllow permission classes to customize the error message. (\n#2539\n)\n\n\nSupport \nsource=\n on hyperlinked fields. (\n#2690\n)\n\n\nListField(allow_null=True)\n now allows null as the list value, not null items in the list. (\n#2766\n)\n\n\nManyToMany()\n maps to \nallow_empty=False\n, \nManyToMany(blank=True)\n maps to \nallow_empty=True\n. (\n#2804\n)\n\n\nSupport custom serialization styles for primary key fields. (\n#2789\n)\n\n\nOPTIONS\n requests support nested representations. (\n#2915\n)\n\n\nSet \nview.action == \"metadata\"\n for viewsets with \nOPTIONS\n requests. (\n#3115\n)\n\n\nSupport \nallow_blank\n on \nUUIDField\n. ([#3130][gh#3130])\n\n\nDo not display view docstrings with 401 or 403 response codes. (\n#3216\n)\n\n\nResolve Django 1.8 deprecation warnings. (\n#2886\n)\n\n\nFix for \nDecimalField\n validation. (\n#3139\n)\n\n\nFix behavior of \nallow_blank=False\n when used with \ntrim_whitespace=True\n. (\n#2712\n)\n\n\nFix issue with some field combinations incorrectly mapping to an invalid \nallow_blank\n argument. (\n#3011\n)\n\n\nFix for output representations with prefetches and modified querysets. (\n#2704\n, \n#2727\n)\n\n\nFix assertion error when CursorPagination is provided with certain invalid query parameters. (#2920)\ngh2920\n.\n\n\nFix \nUnicodeDecodeError\n when invalid characters included in header with \nTokenAuthentication\n. (\n#2928\n)\n\n\nFix transaction rollbacks with \n@non_atomic_requests\n decorator. (\n#3016\n)\n\n\nFix duplicate results issue with Oracle databases using \nSearchFilter\n. (\n#2935\n)\n\n\nFix checkbox alignment and rendering in browsable API forms. (\n#2783\n)\n\n\nFix for unsaved file objects which should use \n\"url\": null\n in the representation. (\n#2759\n)\n\n\nFix field value rendering in browsable API. (\n#2416\n)\n\n\nFix \nHStoreField\n to include \nallow_blank=True\n in \nDictField\n mapping. (\n#2659\n)\n\n\nNumerous other cleanups, improvements to error messaging, private API & minor fixes.\n\n\n\n\n\n\n3.1.x series\n\n\n3.1.3\n\n\nDate\n: \n4th June 2015\n.\n\n\n\n\nAdd \nDurationField\n. (\n#2481\n, \n#2989\n)\n\n\nAdd \nformat\n argument to \nUUIDField\n. (\n#2788\n, \n#3000\n)\n\n\nMultipleChoiceField\n empties incorrectly on a partial update using multipart/form-data (\n#2993\n, \n#2894\n)\n\n\nFix a bug in options related to read-only \nRelatedField\n. (\n#2981\n, \n#2811\n)\n\n\nFix nested serializers with \nunique_together\n relations. (\n#2975\n)\n\n\nAllow unexpected values for \nChoiceField\n/\nMultipleChoiceField\n representations. (\n#2839\n, \n#2940\n)\n\n\nRollback the transaction on error if \nATOMIC_REQUESTS\n is set. (\n#2887\n, \n#2034\n)\n\n\nSet the action on a view when override_method regardless of its None-ness. (\n#2933\n)\n\n\nDecimalField\n accepts \n2E+2\n as 200 and validates decimal place correctly. (\n#2948\n, \n#2947\n)\n\n\nSupport basic authentication with custom \nUserModel\n that change \nusername\n. (\n#2952\n)\n\n\nIPAddressField\n improvements. (\n#2747\n, \n#2618\n, \n#3008\n)\n\n\nImprove \nDecimalField\n for easier subclassing. (\n#2695\n)\n\n\n\n\n3.1.2\n\n\nDate\n: \n13rd May 2015\n.\n\n\n\n\nDateField.to_representation\n can handle str and empty values. (\n#2656\n, \n#2687\n, \n#2869\n)\n\n\nUse default reason phrases from HTTP standard. (\n#2764\n, \n#2763\n)\n\n\nRaise error when \nModelSerializer\n used with abstract model. (\n#2757\n, \n#2630\n)\n\n\nHandle reversal of non-API view_name in \nHyperLinkedRelatedField\n (\n#2724\n, \n#2711\n)\n\n\nDon't require pk strictly for related fields. (\n#2745\n, \n#2754\n)\n\n\nMetadata detects null boolean field type. (\n#2762\n)\n\n\nProper handling of depth in nested serializers. (\n#2798\n)\n\n\nDisplay viewset without paginator. (\n#2807\n)\n\n\nDon't check for deprecated \n.model\n attribute in permissions (\n#2818\n)\n\n\nRestrict integer field to integers and strings. (\n#2835\n, \n#2836\n)\n\n\nImprove \nIntegerField\n to use compiled decimal regex. (\n#2853\n)\n\n\nPrevent empty \nqueryset\n to raise AssertionError. (\n#2862\n)\n\n\nDjangoModelPermissions\n rely on \nget_queryset\n. (\n#2863\n)\n\n\nCheck \nAcceptHeaderVersioning\n with content negotiation in place. (\n#2868\n)\n\n\nAllow \nDjangoObjectPermissions\n to use views that define \nget_queryset\n. (\n#2905\n)\n\n\n\n\n3.1.1\n\n\nDate\n: \n23rd March 2015\n.\n\n\n\n\nSecurity fix\n: Escape tab switching cookie name in browsable API.\n\n\nDisplay input forms in browsable API if \nserializer_class\n is used, even when \nget_serializer\n method does not exist on the view. (\n#2743\n)\n\n\nUse a password input for the AuthTokenSerializer. (\n#2741\n)\n\n\nFix missing anchor closing tag after next button. (\n#2691\n)\n\n\nFix \nlookup_url_kwarg\n handling in viewsets. (\n#2685\n, \n#2591\n)\n\n\nFix problem with importing \nrest_framework.views\n in \napps.py\n (\n#2678\n)\n\n\nLimitOffsetPagination raises \nTypeError\n if PAGE_SIZE not set (\n#2667\n, \n#2700\n)\n\n\nGerman translation for \nmin_value\n field error message references \nmax_value\n. (\n#2645\n)\n\n\nRemove \nMergeDict\n. (\n#2640\n)\n\n\nSupport serializing unsaved models with related fields. (\n#2637\n, \n#2641\n)\n\n\nAllow blank/null on radio.html choices. (\n#2631\n)\n\n\n\n\n3.1.0\n\n\nDate\n: \n5th March 2015\n.\n\n\nFor full details see the \n3.1 release announcement\n.\n\n\n\n\n3.0.x series\n\n\n3.0.5\n\n\nDate\n: \n10th February 2015\n.\n\n\n\n\nFix a bug where \n_closable_objects\n breaks pickling. (\n#1850\n, \n#2492\n)\n\n\nAllow non-standard \nUser\n models with \nThrottling\n. (\n#2524\n)\n\n\nSupport custom \nUser.db_table\n in TokenAuthentication migration. (\n#2479\n)\n\n\nFix misleading \nAttributeError\n tracebacks on \nRequest\n objects. (\n#2530\n, \n#2108\n)\n\n\nManyRelatedField.get_value\n clearing field on partial update. (\n#2475\n)\n\n\nRemoved '.model' shortcut from code. (\n#2486\n)\n\n\nFix \ndetail_route\n and \nlist_route\n mutable argument. (\n#2518\n)\n\n\nPrefetching the user object when getting the token in \nTokenAuthentication\n. (\n#2519\n)\n\n\n\n\n3.0.4\n\n\nDate\n: \n28th January 2015\n.\n\n\n\n\nDjango 1.8a1 support. (\n#2425\n, \n#2446\n, \n#2441\n)\n\n\nAdd \nDictField\n and support Django 1.8 \nHStoreField\n. (\n#2451\n, \n#2106\n)\n\n\nAdd \nUUIDField\n and support Django 1.8 \nUUIDField\n. (\n#2448\n, \n#2433\n, \n#2432\n)\n\n\nBaseRenderer.render\n now raises \nNotImplementedError\n. (\n#2434\n)\n\n\nFix timedelta JSON serialization on Python 2.6. (\n#2430\n)\n\n\nResultDict\n and \nResultList\n now appear as standard dict/list. (\n#2421\n)\n\n\nFix visible \nHiddenField\n in the HTML form of the web browsable API page. (\n#2410\n)\n\n\nUse \nOrderedDict\n for \nRelatedField.choices\n. (\n#2408\n)\n\n\nFix ident format when using \nHTTP_X_FORWARDED_FOR\n. (\n#2401\n)\n\n\nFix invalid key with memcached while using throttling. (\n#2400\n)\n\n\nFix \nFileUploadParser\n with version 3.x. (\n#2399\n)\n\n\nFix the serializer inheritance. (\n#2388\n)\n\n\nFix caching issues with \nReturnDict\n. (\n#2360\n)\n\n\n\n\n3.0.3\n\n\nDate\n: \n8th January 2015\n.\n\n\n\n\nFix \nMinValueValidator\n on \nmodels.DateField\n. (\n#2369\n)\n\n\nFix serializer missing context when pagination is used. (\n#2355\n)\n\n\nNamespaced router URLs are now supported by the \nDefaultRouter\n. (\n#2351\n)\n\n\nrequired=False\n allows omission of value for output. (\n#2342\n)\n\n\nUse textarea input for \nmodels.TextField\n. (\n#2340\n)\n\n\nUse custom \nListSerializer\n for pagination if required. (\n#2331\n, \n#2327\n)\n\n\nBetter behavior with null and '' for blank HTML fields. (\n#2330\n)\n\n\nEnsure fields in \nexclude\n are model fields. (\n#2319\n)\n\n\nFix \nIntegerField\n and \nmax_length\n argument incompatibility. (\n#2317\n)\n\n\nFix the YAML encoder for 3.0 serializers. (\n#2315\n, \n#2283\n)\n\n\nFix the behavior of empty HTML fields. (\n#2311\n, \n#1101\n)\n\n\nFix Metaclass attribute depth ignoring fields attribute. (\n#2287\n)\n\n\nFix \nformat_suffix_patterns\n to work with Django's \ni18n_patterns\n. (\n#2278\n)\n\n\nAbility to customize router URLs for custom actions, using \nurl_path\n. (\n#2010\n)\n\n\nDon't install Django REST Framework as egg. (\n#2386\n)\n\n\n\n\n3.0.2\n\n\nDate\n: \n17th December 2014\n.\n\n\n\n\nEnsure \nrequest.user\n is made available to response middleware. (\n#2155\n)\n\n\nClient.logout()\n also cancels any existing \nforce_authenticate\n. (\n#2218\n, \n#2259\n)\n\n\nExtra assertions and better checks to preventing incorrect serializer API use. (\n#2228\n, \n#2234\n, \n#2262\n, \n#2263\n, \n#2266\n, \n#2267\n, \n#2289\n, \n#2291\n)\n\n\nFixed \nmin_length\n message for \nCharField\n. (\n#2255\n)\n\n\nFix \nUnicodeDecodeError\n, which can occur on serializer \nrepr\n. (\n#2270\n, \n#2279\n)\n\n\nFix empty HTML values when a default is provided. (\n#2280\n, \n#2294\n)\n\n\nFix \nSlugRelatedField\n raising \nUnicodeEncodeError\n when used as a multiple choice input. (\n#2290\n)\n\n\n\n\n3.0.1\n\n\nDate\n: \n11th December 2014\n.\n\n\n\n\nMore helpful error message when the default Serializer \ncreate()\n fails. (\n#2013\n)\n\n\nRaise error when attempting to save serializer if data is not valid. (\n#2098\n)\n\n\nFix \nFileUploadParser\n breaks with empty file names and multiple upload handlers. (\n#2109\n)\n\n\nImprove \nBindingDict\n to support standard dict-functions. (\n#2135\n, \n#2163\n)\n\n\nAdd \nvalidate()\n to \nListSerializer\n. (\n#2168\n, \n#2225\n, \n#2232\n)\n\n\nFix JSONP renderer failing to escape some characters. (\n#2169\n, \n#2195\n)\n\n\nAdd missing default style for \nFileField\n. (\n#2172\n)\n\n\nActions are required when calling \nViewSet.as_view()\n. (\n#2175\n)\n\n\nAdd \nallow_blank\n to \nChoiceField\n. (\n#2184\n, \n#2239\n)\n\n\nCosmetic fixes in the HTML renderer. (\n#2187\n)\n\n\nRaise error if \nfields\n on serializer is not a list of strings. (\n#2193\n, \n#2213\n)\n\n\nImprove checks for nested creates and updates. (\n#2194\n, \n#2196\n)\n\n\nvalidated_attrs\n argument renamed to \nvalidated_data\n in \nSerializer\n \ncreate()\n/\nupdate()\n. (\n#2197\n)\n\n\nRemove deprecated code to reflect the dropped Django versions. (\n#2200\n)\n\n\nBetter serializer errors for nested writes. (\n#2202\n, \n#2215\n)\n\n\nFix pagination and custom permissions incompatibility. (\n#2205\n)\n\n\nRaise error if \nfields\n on serializer is not a list of strings. (\n#2213\n)\n\n\nAdd missing translation markers for relational fields. (\n#2231\n)\n\n\nImprove field lookup behavior for dicts/mappings. (\n#2244\n, \n#2243\n)\n\n\nOptimized hyperlinked PK. (\n#2242\n)\n\n\n\n\n3.0.0\n\n\nDate\n: 1st December 2014\n\n\nFor full details see the \n3.0 release announcement\n.\n\n\n\n\nFor older release notes, \nplease see the version 2.x documentation\n.", + "text": "Release Notes\n\n\n\n\nRelease Early, Release Often\n\n\n\u2014 Eric S. Raymond, \nThe Cathedral and the Bazaar\n.\n\n\n\n\nVersioning\n\n\nMinor version numbers (0.0.x) are used for changes that are API compatible. You should be able to upgrade between minor point releases without any other code changes.\n\n\nMedium version numbers (0.x.0) may include API changes, in line with the \ndeprecation policy\n. You should read the release notes carefully before upgrading between medium point releases.\n\n\nMajor version numbers (x.0.0) are reserved for substantial project milestones.\n\n\nDeprecation policy\n\n\nREST framework releases follow a formal deprecation policy, which is in line with \nDjango's deprecation policy\n.\n\n\nThe timeline for deprecation of a feature present in version 1.0 would work as follows:\n\n\n\n\n\n\nVersion 1.1 would remain \nfully backwards compatible\n with 1.0, but would raise \nPendingDeprecationWarning\n warnings if you use the feature that are due to be deprecated. These warnings are \nsilent by default\n, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using \npython -Wd manage.py test\n, you'll be warned of any API changes you need to make.\n\n\n\n\n\n\nVersion 1.2 would escalate these warnings to \nDeprecationWarning\n, which is loud by default.\n\n\n\n\n\n\nVersion 1.3 would remove the deprecated bits of API entirely.\n\n\n\n\n\n\nNote that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.\n\n\nUpgrading\n\n\nTo upgrade Django REST framework to the latest version, use pip:\n\n\npip install -U djangorestframework\n\n\n\nYou can determine your currently installed version using \npip show\n:\n\n\npip show djangorestframework\n\n\n\n\n\n3.9.x series\n\n\n3.9.1\n\n\nDate\n: \n16th Janurary 2019\n\n\n\n\nResolve XSS issue in browsable API. \n#6330\n\n\nResolve issues with composable permissions. \n#6299\n\n\nRespect \nlimit_choices_to\n on foreign keys. \n#6371\n\n\n\n\n3.9.0\n\n\nDate\n: \n18th October 2018\n\n\n\n\nImprovements to ViewSet extra actions \n#5605\n\n\nFix \naction\n support for ViewSet suffixes \n#6081\n\n\nAllow \naction\n docs sections \n#6060\n\n\nDeprecate the \nRouter.register\n \nbase_name\n argument in favor of \nbasename\n. \n#5990\n\n\nDeprecate the \nRouter.get_default_base_name\n method in favor of \nRouter.get_default_basename\n. \n#5990\n\n\nChange \nCharField\n to disallow null bytes. \n#6073\n\n To revert to the old behavior, subclass \nCharField\n and remove \nProhibitNullCharactersValidator\n from the validators.\n \npython\n class NullableCharField(serializers.CharField):\n def __init__(self, *args, **kwargs):\n super().__init__(*args, **kwargs)\n self.validators = [v for v in self.validators if not isinstance(v, ProhibitNullCharactersValidator)]\n\n\nAdd \nOpenAPIRenderer\n and \ngenerate_schema\n management command. \n#6229\n\n\nAdd OpenAPIRenderer by default, and add schema docs. \n#6233\n\n\nAllow permissions to be composed \n#5753\n\n\nAllow nullable BooleanField in Django 2.1 \n#6183\n\n\nAdd testing of Python 3.7 support \n#6141\n\n\nTest using Django 2.1 final release. \n#6109\n\n\nAdded djangorestframework-datatables to third-party packages \n#5931\n\n\nChange ISO 8601 date format to exclude year/month \n#5936\n\n\nUpdate all pypi.python.org URLs to pypi.org \n#5942\n\n\nEnsure that html forms (multipart form data) respect optional fields \n#5927\n\n\nAllow hashing of ErrorDetail. \n#5932\n\n\nCorrect schema parsing for JSONField \n#5878\n\n\nRender descriptions (from help_text) using safe \n#5869\n\n\nRemoved input value from deault_error_message \n#5881\n\n\nAdded min_value/max_value support in DurationField \n#5643\n\n\nFixed instance being overwritten in pk-only optimization try/except block \n#5747\n\n\nFixed AttributeError from items filter when value is None \n#5981\n\n\nFixed Javascript \ne.indexOf\n is not a function error \n#5982\n\n\nFix schemas for extra actions \n#5992\n\n\nImproved get_error_detail to use error_dict/error_list \n#5785\n\n\nImprvied URLs in Admin renderer \n#5988\n\n\nAdd \"Community\" section to docs, minor cleanup \n#5993\n\n\nMoved guardian imports out of compat \n#6054\n\n\nDeprecate the \nDjangoObjectPermissionsFilter\n class, moved to the \ndjangorestframework-guardian\n package. \n#6075\n\n\nDrop Django 1.10 support \n#5657\n\n\nOnly catch TypeError/ValueError for object lookups \n#6028\n\n\nHandle models without .objects manager in ModelSerializer. \n#6111\n\n\nImprove ModelSerializer.create() error message. \n#6112\n\n\nFix CSRF cookie check failure when using session auth with django 1.11.6+ \n#6113\n\n\nUpdated JWT docs. \n#6138\n\n\nFix autoescape not getting passed to urlize_quoted_links filter \n#6191\n\n\n\n\n3.8.x series\n\n\n3.8.2\n\n\nDate\n: \n6th April 2018\n\n\n\n\nFix \nread_only\n + \ndefault\n \nunique_together\n validation. \n#5922\n\n\nauthtoken.views import coreapi from rest_framework.compat, not directly. \n#5921\n\n\nDocs: Add missing argument 'detail' to Route \n#5920\n\n\n\n\n3.8.1\n\n\nDate\n: \n4th April 2018\n\n\n\n\n\n\nUse old \nurl_name\n behavior in route decorators \n#5915\n\n\nFor \nlist_route\n and \ndetail_route\n maintain the old behavior of \nurl_name\n,\nbasing it on the \nurl_path\n instead of the function name.\n\n\n\n\n\n\n3.8.0\n\n\nDate\n: \n3rd April 2018\n\n\n\n\n\n\nBreaking Change\n: Alter \nread_only\n plus \ndefault\n behaviour. \n#5886\n\n\nread_only\n fields will now \nalways\n be excluded from writable fields.\n\n\nPreviously \nread_only\n fields with a \ndefault\n value would use the \ndefault\n for create and update operations.\n\n\nIn order to maintain the old behaviour you may need to pass the value of \nread_only\n fields when calling \nsave()\n in\nthe view:\n\n\ndef perform_create(self, serializer):\n serializer.save(owner=self.request.user)\n\n\n\nAlternatively you may override \nsave()\n or \ncreate()\n or \nupdate()\n on the serialiser as appropriate.\n\n\n\n\n\n\nCorrect allow_null behaviour when required=False \n#5888\n\n\nWithout an explicit \ndefault\n, \nallow_null\n implies a default of \nnull\n for outgoing serialisation. Previously such\nfields were being skipped when read-only or otherwise not required.\n\n\nPossible backwards compatibility break\n if you were relying on such fields being excluded from the outgoing\nrepresentation. In order to restore the old behaviour you can override \ndata\n to exclude the field when \nNone\n.\n\n\nFor example:\n\n\n@property\ndef data(self):\n \"\"\"\n Drop `maybe_none` field if None.\n \"\"\"\n data = super().data\n if 'maybe_none' in data and data['maybe_none'] is None:\n del data['maybe_none']\n return data\n\n\n\n\n\n\n\nRefactor dynamic route generation and improve viewset action introspectibility. \n#5705\n\n\nViewSet\ns have been provided with new attributes and methods that allow\nit to introspect its set of actions and the details of the current action.\n\n\n\n\nMerged \nlist_route\n and \ndetail_route\n into a single \naction\n decorator.\n\n\nGet all extra actions on a \nViewSet\n with \n.get_extra_actions()\n.\n\n\nExtra actions now set the \nurl_name\n and \nurl_path\n on the decorated method.\n\n\nurl_name\n is now based on the function name, instead of the \nurl_path\n,\n as the path is not always suitable (e.g., capturing arguments in the path).\n\n\nEnable action url reversing through \n.reverse_action()\n method (added in 3.7.4)\n\n\nExample reverse call: \nself.reverse_action(self.custom_action.url_name)\n\n\nAdd \ndetail\n initkwarg to indicate if the current action is operating on a\n collection or a single instance.\n\n\n\n\nAdditional changes:\n\n\n\n\nDeprecated \nlist_route\n & \ndetail_route\n in favor of \naction\n decorator with \ndetail\n boolean.\n\n\nDeprecated dynamic list/detail route variants in favor of \nDynamicRoute\n with \ndetail\n boolean.\n\n\nRefactored the router's dynamic route generation.\n\n\nlist_route\n and \ndetail_route\n maintain the old behavior of \nurl_name\n,\n basing it on the \nurl_path\n instead of the function name.\n\n\n\n\n\n\n\n\nFix formatting of the 3.7.4 release note \n#5704\n\n\n\n\nDocs: Update DRF Writable Nested Serializers references \n#5711\n\n\nDocs: Fixed typo in auth URLs example. \n#5713\n\n\nImprove composite field child errors \n#5655\n\n\nDisable HTML inputs for dict/list fields \n#5702\n\n\nFix typo in HostNameVersioning doc \n#5709\n\n\nUse rsplit to get module and classname for imports \n#5712\n\n\nFormalize URLPatternsTestCase \n#5703\n\n\nAdd exception translation test \n#5700\n\n\nTest staticfiles \n#5701\n\n\nAdd drf-yasg to documentation and schema 3rd party packages \n#5720\n\n\nRemove unused \ncompat._resolve_model()\n \n#5733\n\n\nDrop compat workaround for unsupported Python 3.2 \n#5734\n\n\nPrefer \niter(dict)\n over \niter(dict.keys())\n \n#5736\n\n\nPass \npython_requires\n argument to setuptools \n#5739\n\n\nRemove unused links from docs \n#5735\n\n\nPrefer https protocol for links in docs when available \n#5729\n\n\nAdd HStoreField, postgres fields tests \n#5654\n\n\nAlways fully qualify ValidationError in docs \n#5751\n\n\nRemove unreachable code from ManualSchema \n#5766\n\n\nAllowed customising API documentation code samples \n#5752\n\n\nUpdated docs to use \npip show\n \n#5757\n\n\nLoad 'static' instead of 'staticfiles' in templates \n#5773\n\n\nFixed a typo in \nfields\n docs \n#5783\n\n\nRefer to \"NamespaceVersioning\" instead of \"NamespacedVersioning\" in the documentation \n#5754\n\n\nErrorDetail: add \n__eq__\n/\n__ne__\n and \n__repr__\n \n#5787\n\n\nReplace \nbackground-attachment: fixed\n in docs \n#5777\n\n\nMake 404 & 403 responses consistent with \nexceptions.APIException\n output \n#5763\n\n\nSmall fix to API documentation: schemas \n#5796\n\n\nFix schema generation for PrimaryKeyRelatedField \n#5764\n\n\nRepresent serializer DictField as an Object in schema \n#5765\n\n\nAdded docs example reimplementing ObtainAuthToken \n#5802\n\n\nAdd schema to the ObtainAuthToken view \n#5676\n\n\nFix request formdata handling \n#5800\n\n\nFix authtoken views imports \n#5818\n\n\nUpdate pytest, isort \n#5815\n \n#5817\n \n#5894\n\n\nFixed active timezone handling for non ISO8601 datetimes. \n#5833\n\n\nMade TemplateHTMLRenderer render IntegerField inputs when value is \n0\n. \n#5834\n\n\nCorrected endpoint in tutorial instructions \n#5835\n\n\nAdd Django Rest Framework Role Filters to Third party packages \n#5809\n\n\nUse single copy of static assets. Update jQuery \n#5823\n\n\nChanges ternary conditionals to be PEP308 compliant \n#5827\n\n\nAdded links to 'A Todo List API with React' and 'Blog API' tutorials \n#5837\n\n\nFix comment typo in ModelSerializer \n#5844\n\n\nAdd admin to installed apps to avoid test failures. \n#5870\n\n\nFixed schema for UUIDField in SimpleMetadata. \n#5872\n\n\nCorrected docs on router include with namespaces. \n#5843\n\n\nTest using model objects for dotted source default \n#5880\n\n\nAllow traversing nullable related fields \n#5849\n\n\nAdded: Tutorial: Django REST with React (Django 2.0) \n#5891\n\n\nAdd \nLimitOffsetPagination.get_count\n to allow method override \n#5846\n\n\nDon't show hidden fields in metadata \n#5854\n\n\nEnable OrderingFilter to handle an empty tuple (or list) for the 'ordering' field. \n#5899\n\n\nAdded generic 500 and 400 JSON error handlers. \n#5904\n\n\n\n\n3.7.x series\n\n\n3.7.7\n\n\nDate\n: \n21st December 2017\n\n\n\n\nFix typo to include *.mo locale files to packaging. \n#5697\n, \n#5695\n\n\n\n\n3.7.6\n\n\nDate\n: \n21st December 2017\n\n\n\n\nAdd missing *.ico icon files to packaging.\n\n\n\n\n3.7.5\n\n\nDate\n: \n21st December 2017\n\n\n\n\nAdd missing *.woff2 font files to packaging. \n#5692\n\n\nAdd missing *.mo locale files to packaging. \n#5695\n, \n#5696\n\n\n\n\n3.7.4\n\n\nDate\n: \n20th December 2017\n\n\n\n\n\n\nSchema: Extract method for \nmanual_fields\n processing \n#5633\n\n\nAllows for easier customisation of \nmanual_fields\n processing, for example\nto provide per-method manual fields. \nAutoSchema\n adds \nget_manual_fields\n,\nas the intended override point, and a utility method \nupdate_fields\n, to\nhandle by-name field replacement from a list, which, in general, you are not\nexpected to override.\n\n\nNote: \nAutoSchema.__init__\n now ensures \nmanual_fields\n is a list.\nPreviously may have been stored internally as \nNone\n.\n\n\n\n\n\n\nRemove ulrparse compatability shim; use six instead \n#5579\n\n\n\n\nDrop compat wrapper for \nTimeDelta.total_seconds()\n \n#5577\n\n\nClean up all whitespace throughout project \n#5578\n\n\nCompat cleanup \n#5581\n\n\nAdd pygments CSS block in browsable API views \n#5584\n \n#5587\n\n\nRemove \nset_rollback()\n from compat \n#5591\n\n\nFix request body/POST access \n#5590\n\n\nRename test to reference correct issue \n#5610\n\n\nDocumentation Fixes \n#5611\n \n#5612\n\n\nRemove references to unsupported Django versions in docs and code \n#5602\n\n\nTest Serializer exclude for declared fields \n#5599\n\n\nFixed schema generation for filter backends \n#5613\n\n\nMinor cleanup for ModelSerializer tests \n#5598\n\n\nReimplement request attribute access w/ \n__getattr__\n \n#5617\n\n\nFixed SchemaJSRenderer renders invalid Javascript \n#5607\n\n\nMake Django 2.0 support official/explicit \n#5619\n\n\nPerform type check on passed request argument \n#5618\n\n\nFix AttributeError hiding on request authenticators \n#5600\n\n\nUpdate test requirements \n#5626\n\n\nDocs: \nSerializer._declared_fields\n enable modifying fields on a serializer \n#5629\n\n\nFix packaging \n#5624\n\n\nFix readme rendering for PyPI, add readme build to CI \n#5625\n\n\nUpdate tutorial \n#5622\n\n\nNon-required fields with \nallow_null=True\n should not imply a default value \n#5639\n\n\nDocs: Add \nallow_null\n serialization output note \n#5641\n\n\nUpdate to use the Django 2.0 release in tox.ini \n#5645\n\n\nFix \nSerializer.data\n for Browsable API rendering when provided invalid \ndata\n \n#5646\n\n\nDocs: Note AutoSchema limitations on bare APIView \n#5649\n\n\nAdd \n.basename\n and \n.reverse_action()\n to ViewSet \n#5648\n\n\nDocs: Fix typos in serializers documentation \n#5652\n\n\nFix \noverride_settings\n compat \n#5668\n\n\nAdd DEFAULT_SCHEMA_CLASS setting \n#5658\n\n\nAdd docs note re generated BooleanField being \nrequired=False\n \n#5665\n\n\nAdd 'dist' build \n#5656\n\n\nFix typo in docstring \n#5678\n\n\nDocs: Add \nUNAUTHENTICATED_USER = None\n note \n#5679\n\n\nUpdate OPTIONS example from \u201cDocumenting Your API\u201d \n#5680\n\n\nDocs: Add note on object permissions for FBVs \n#5681\n\n\nDocs: Add example to \nto_representation\n docs \n#5682\n\n\nAdd link to Classy DRF in docs \n#5683\n\n\nDocument ViewSet.action \n#5685\n\n\nFix schema docs typo \n#5687\n\n\nFix URL pattern parsing in schema generation \n#5689\n\n\nAdd example using \nsource=\u2018*\u2019\n to custom field docs. \n#5688\n\n\nFix format_suffix_patterns behavior with Django 2 path() routes \n#5691\n\n\n\n\n3.7.3\n\n\nDate\n: \n6th November 2017\n\n\n\n\nFix \nAppRegistryNotReady\n error from contrib.auth view imports \n#5567\n\n\n\n\n3.7.2\n\n\nDate\n: \n6th November 2017\n\n\n\n\nFixed Django 2.1 compatibility due to removal of django.contrib.auth.login()/logout() views. \n#5510\n\n\nAdd missing import for TextLexer. \n#5512\n\n\nAdding examples and documentation for caching \n#5514\n\n\nInclude date and date-time format for schema generation \n#5511\n\n\nUse triple backticks for markdown code blocks \n#5513\n\n\nInteractive docs - make bottom sidebar items sticky \n#5516\n\n\nClarify pagination system check \n#5524\n\n\nStop JSONBoundField mangling invalid JSON \n#5527\n\n\nHave JSONField render as textarea in Browsable API \n#5530\n\n\nSchema: Exclude OPTIONS/HEAD for ViewSet actions \n#5532\n\n\nFix ordering for dotted sources \n#5533\n\n\nFix: Fields with \nallow_null=True\n should imply a default serialization value \n#5518\n\n\nEnsure Location header is strictly a 'str', not subclass. \n#5544\n\n\nAdd import to example in api-guide/parsers \n#5547\n\n\nCatch OverflowError for \"out of range\" datetimes \n#5546\n\n\nAdd djangorestframework-rapidjson to third party packages \n#5549\n\n\nIncrease test coverage for \ndrf_create_token\n command \n#5550\n\n\nAdd trove classifier for Python 3.6 support. \n#5555\n\n\nAdd pip cache support to the Travis CI configuration \n#5556\n\n\nRename [\nwheel\n] section to [\nbdist_wheel\n] as the former is legacy \n#5557\n\n\nFix invalid escape sequence deprecation warnings \n#5560\n\n\nAdd interactive docs error template \n#5548\n\n\nAdd rounding parameter to DecimalField \n#5562\n\n\nFix all BytesWarning caught during tests \n#5561\n\n\nUse dict and set literals instead of calls to dict() and set() \n#5559\n\n\nChange ImageField validation pattern, use validators from DjangoImageField \n#5539\n\n\nFix processing unicode symbols in query_string by Python 2 \n#5552\n\n\n\n\n3.7.1\n\n\nDate\n: \n16th October 2017\n\n\n\n\nFix Interactive documentation always uses false for boolean fields in requests \n#5492\n\n\nImprove compatibility with Django 2.0 alpha. \n#5500\n \n#5503\n\n\nImproved handling of schema naming collisions \n#5486\n\n\nAdded additional docs and tests around providing a default value for dotted \nsource\n fields \n#5489\n\n\n\n\n3.7.0\n\n\nDate\n: \n6th October 2017\n\n\n\n\nFix \nDjangoModelPermissions\n to ensure user authentication before calling the view's \nget_queryset()\n method. As a side effect, this changes the order of the HTTP method permissions and authentication checks, and 405 responses will only be returned when authenticated. If you want to replicate the old behavior, see the PR for details. \n#5376\n\n\nDeprecated \nexclude_from_schema\n on \nAPIView\n and \napi_view\n decorator. Set \nschema = None\n or \n@schema(None)\n as appropriate. \n#5422\n\n\n\n\nTimezone-aware \nDateTimeField\ns now respect active or default \ntimezone\n during serialization, instead of always using UTC. \n#5435\n\n\nResolves inconsistency whereby instances were serialised with supplied datetime for \ncreate\n but UTC for \nretrieve\n. \n#3732\n\n\nPossible backwards compatibility break\n if you were relying on datetime strings being UTC. Have client interpret datetimes or \nset default or active timezone (docs)\n to UTC if needed.\n\n\n\n\n\n\nRemoved DjangoFilterBackend inline with deprecation policy. Use \ndjango_filters.rest_framework.FilterSet\n and/or \ndjango_filters.rest_framework.DjangoFilterBackend\n instead. \n#5273\n\n\n\n\nDon't strip microseconds from \ntime\n when encoding. Makes consistent with \ndatetime\n.\n \nBC Change\n: Previously only milliseconds were encoded. \n#5440\n\n\nAdded \nSTRICT_JSON\n setting (default \nTrue\n) to raise exception for the extended float values (\nnan\n, \ninf\n, \n-inf\n) accepted by Python's \njson\n module.\n \nBC Change\n: Previously these values would converted to corresponding strings. Set \nSTRICT_JSON\n to \nFalse\n to restore the previous behaviour. \n#5265\n\n\nAdd support for \npage_size\n parameter in CursorPaginator class \n#5250\n\n\nMake \nDEFAULT_PAGINATION_CLASS\n \nNone\n by default.\n \nBC Change\n: If your were \njust\n setting \nPAGE_SIZE\n to enable pagination you will need to add \nDEFAULT_PAGINATION_CLASS\n.\n The previous default was \nrest_framework.pagination.PageNumberPagination\n. There is a system check warning to catch this case. You may silence that if you are setting pagination class on a per-view basis. \n#5170\n\n\nCatch \nAPIException\n from \nget_serializer_fields\n in schema generation. \n#5443\n\n\nAllow custom authentication and permission classes when using \ninclude_docs_urls\n \n#5448\n\n\nDefer translated string evaluation on validators. \n#5452\n\n\nAdded default value for 'detail' param into 'ValidationError' exception \n#5342\n\n\nAdjust schema get_filter_fields rules to match framework \n#5454\n\n\nUpdated test matrix to add Django 2.0 and drop Django 1.8 & 1.9\n \nBC Change\n: This removes Django 1.8 and Django 1.9 from Django REST Framework supported versions. \n#5457\n\n\nFixed a deprecation warning in serializers.ModelField \n#5058\n\n\nAdded a more explicit error message when \nget_queryset\n returned \nNone\n \n#5348\n\n\nFix docs for Response \ndata\n description \n#5361\n\n\nFix \npycache\n/.pyc excludes when packaging \n#5373\n\n\nFix default value handling for dotted sources \n#5375\n\n\nEnsure content_type is set when passing empty body to RequestFactory \n#5351\n\n\nFix ErrorDetail Documentation \n#5380\n\n\nAllow optional content in the generic content form \n#5372\n\n\nUpdated supported values for the NullBooleanField \n#5387\n\n\nFix ModelSerializer custom named fields with source on model \n#5388\n\n\nFixed the MultipleFieldLookupMixin documentation example to properly check for object level permission \n#5398\n\n\nUpdate get_object() example in permissions.md \n#5401\n\n\nFix authtoken management command \n#5415\n\n\nFix schema generation markdown \n#5421\n\n\nAllow \nChoiceField.choices\n to be set dynamically \n#5426\n\n\nAdd the project layout to the quickstart \n#5434\n\n\nReuse 'apply_markdown' function in 'render_markdown' templatetag \n#5469\n\n\nAdded links to \ndrf-openapi\n package in docs \n#5470\n\n\nAdded docstrings code highlighting with pygments \n#5462\n\n\nFixed documentation rendering for views named \ndata\n \n#5472\n\n\nDocs: Clarified 'to_internal_value()' validation behavior \n#5466\n\n\nFix missing six.text_type() call on APIException.\nstr\n \n#5476\n\n\nDocument documentation.py \n#5478\n\n\nFix naming collisions in Schema Generation \n#5464\n\n\nCall Django's authenticate function with the request object \n#5295\n\n\nUpdate coreapi JS to 0.1.1 \n#5479\n\n\nHave \nis_list_view\n recognise RetrieveModel\u2026 views \n#5480\n\n\nRemove Django 1.8 & 1.9 compatibility code \n#5481\n\n\nRemove deprecated schema code from DefaultRouter \n#5482\n\n\nRefactor schema generation to allow per-view customisation.\n \nBC Change\n: \nSchemaGenerator.get_serializer_fields\n has been refactored as \nAutoSchema.get_serializer_fields\n and drops the \nview\n argument [#5354][gh5354]\n\n\n\n\n3.6.x series\n\n\n3.6.4\n\n\nDate\n: \n21st August 2017\n\n\n\n\nIgnore any invalidly formed query parameters for OrderingFilter. \n#5131\n\n\nImprove memory footprint when reading large JSON requests. \n#5147\n\n\nFix schema generation for pagination. \n#5161\n\n\nFix exception when \nHTML_CUTOFF\n is set to \nNone\n. \n#5174\n\n\nFix browsable API not supporting \nmultipart/form-data\n correctly. \n#5176\n\n\nFixed \ntest_hyperlinked_related_lookup_url_encoded_exists\n. \n#5179\n\n\nMake sure max_length is in FileField kwargs. \n#5186\n\n\nFix \nlist_route\n & \ndetail_route\n with kwargs contains curly bracket in \nurl_path\n \n#5187\n\n\nAdd Django manage command to create a DRF user Token. \n#5188\n\n\nEnsure API documentation templates do not check for user authentication \n#5162\n\n\nFix special case where OneToOneField is also primary key. \n#5192\n\n\nAdded aria-label and a new region for accessibility purposes in base.html \n#5196\n\n\nQuote nested API parameters in api.js. \n#5214\n\n\nSet ViewSet args/kwargs/request before dispatch. \n#5229\n\n\nAdded unicode support to SlugField. \n#5231\n\n\nFix HiddenField appears in Raw Data form initial content. \n#5259\n\n\nRaise validation error on invalid timezone parsing. \n#5261\n\n\nFix SearchFilter to-many behavior/performance. \n#5264\n\n\nSimplified chained comparisons and minor code fixes. \n#5276\n\n\nRemoteUserAuthentication, docs, and tests. \n#5306\n\n\nRevert \"Cached the field's root and context property\" \n#5313\n\n\nFix introspection of list field in schema. \n#5326\n\n\nFix interactive docs for multiple nested and extra methods. \n#5334\n\n\nFix/remove undefined template var \"schema\" \n#5346\n\n\n\n\n3.6.3\n\n\nDate\n: \n12th May 2017\n\n\n\n\nRaise 404 if a URL lookup results in ValidationError. (\n#5126\n)\n\n\nHonor http_method_names on class based view, when generating API schemas. (\n#5085\n)\n\n\nAllow overridden \nget_limit\n in LimitOffsetPagination to return all records. (\n#4437\n)\n\n\nFix partial update for the ListSerializer. (\n#4222\n)\n\n\nRender JSONField control correctly in browsable API. (\n#4999\n, \n#5042\n)\n\n\nRaise validation errors for invalid datetime in given timezone. (\n#4987\n)\n\n\nSupport restricting doc & schema shortcuts to a subset of urls. (\n#4979\n)\n\n\nResolve SchemaGenerator error with paginators that have no \npage_size\n attribute. (\n#5086\n, \n#3692\n)\n\n\nResolve HyperlinkedRelatedField exception on string with %20 instead of space. (\n#4748\n, \n#5078\n)\n\n\nCustomizable schema generator classes. (\n#5082\n)\n\n\nUpdate existing vary headers in response instead of overwriting them. (\n#5047\n)\n\n\nSupport passing \n.as_view()\n to view instance. (\n#5053\n)\n\n\nUse correct exception handler when settings overridden on a view. (\n#5055\n, \n#5054\n)\n\n\nUpdate Boolean field to support 'yes' and 'no' values. (\n#5038\n)\n\n\nFix unique validator for ChoiceField. (\n#5004\n, \n#5026\n, \n#5028\n)\n\n\nJavaScript cleanups in API Docs. (\n#5001\n)\n\n\nInclude URL path regexs in API schemas where valid. (\n#5014\n)\n\n\nCorrectly set scheme in coreapi TokenAuthentication. (\n#5000\n, \n#4994\n)\n\n\nHEAD requests on ViewSets should not return 405. (\n#4705\n, \n#4973\n, \n#4864\n)\n\n\nSupport usage of 'source' in \nextra_kwargs\n. (\n#4688\n)\n\n\nFix invalid content type for schema.js (\n#4968\n)\n\n\nFix DjangoFilterBackend inheritance issues. (\n#5089\n, \n#5117\n)\n\n\n\n\n3.6.2\n\n\nDate\n: \n10th March 2017\n\n\n\n\nSupport for Safari & IE in API docs. (\n#4959\n, \n#4961\n)\n\n\nAdd missing \nmark_safe\n in API docs template tags. (\n#4952\n, \n#4953\n)\n\n\nAdd missing glyphicon fonts. (\n#4950\n, \n#4951\n)\n\n\nFix One-to-one fields in API docs. (\n#4955\n, \n#4956\n)\n\n\nTest clean ups. (\n#4949\n)\n\n\n\n\n3.6.1\n\n\nDate\n: \n9th March 2017\n\n\n\n\nEnsure \nmarkdown\n dependency is optional. (\n#4947\n)\n\n\n\n\n3.6.0\n\n\nDate\n: \n9th March 2017\n\n\nSee the \nrelease announcement\n.\n\n\n\n\n3.5.x series\n\n\n3.5.4\n\n\nDate\n: \n10th February 2017\n\n\n\n\nAdd max_length and min_length arguments for ListField. (\n#4877\n)\n\n\nAdd per-view custom exception handler support. (\n#4753\n)\n\n\nSupport disabling of declared fields on serializer subclasses. (\n#4764\n)\n\n\nSupport custom view names on \n@list_route\n and \n@detail_route\n endpoints. (\n#4821\n)\n\n\nCorrect labels for fields in login template when custom user model is used. (\n#4841\n)\n\n\nWhitespace fixes for descriptions generated from docstrings. (\n#4759\n, \n#4869\n, \n#4870\n)\n\n\nBetter error reporting when schemas are returned by views without a schema renderer. (\n#4790\n)\n\n\nFix for returned response of \nPUT\n requests when \nprefetch_related\n is used. (\n#4661\n, \n#4668\n)\n\n\nFix for breadcrumb view names. (\n#4750\n)\n\n\nFix for RequestsClient ensuring fully qualified URLs. (\n#4678\n)\n\n\nFix for incorrect behavior of writable-nested fields check in some cases. (\n#4634\n, \n#4669\n)\n\n\nResolve Django deprecation warnings. (\n#4712\n)\n\n\nVarious cleanup of test cases.\n\n\n\n\n3.5.3\n\n\nDate\n: \n7th November 2016\n\n\n\n\nDon't raise incorrect FilterSet deprecation warnings. (\n#4660\n, \n#4643\n, \n#4644\n)\n\n\nSchema generation should not raise 404 when a view permission class does. (\n#4645\n, \n#4646\n)\n\n\nAdd \nautofocus\n support for input controls. (\n#4650\n)\n\n\n\n\n3.5.2\n\n\nDate\n: \n1st November 2016\n\n\n\n\nRestore exception tracebacks in Python 2.7. (\n#4631\n, \n#4638\n)\n\n\nProperly display dicts in the admin console. (\n#4532\n, \n#4636\n)\n\n\nFix is_simple_callable with variable args, kwargs. (\n#4622\n, \n#4602\n)\n\n\nSupport 'on'/'off' literals with BooleanField. (\n#4640\n, \n#4624\n)\n\n\nEnable cursor pagination of value querysets. (\n#4569\n)\n\n\nFix support of get_full_details() for Throttled exceptions. (\n#4627\n)\n\n\nFix FilterSet proxy. (\n#4620\n)\n\n\nMake serializer fields import explicit. (\n#4628\n)\n\n\nDrop redundant requests adapter. (\n#4639\n)\n\n\n\n\n3.5.1\n\n\nDate\n: \n21st October 2016\n\n\n\n\nMake \nrest_framework/compat.py\n imports. (\n#4612\n, \n#4608\n, \n#4601\n)\n\n\nFix bug in schema base path generation. (\n#4611\n, \n#4605\n)\n\n\nFix broken case of ListSerializer with single item. (\n#4609\n, \n#4606\n)\n\n\nRemove bare \nraise\n for Python 3.5 compat. (\n#4600\n)\n\n\n\n\n3.5.0\n\n\nDate\n: \n20th October 2016\n\n\n\n\n3.4.x series\n\n\n3.4.7\n\n\nDate\n: \n21st September 2016\n\n\n\n\nFallback behavior for request parsing when request.POST already accessed. (\n#3951\n, \n#4500\n)\n\n\nFix regression of \nRegexField\n. (\n#4489\n, \n#4490\n, \n#2617\n)\n\n\nMissing comma in \nadmin.html\n causing CSRF error. (\n#4472\n, \n#4473\n)\n\n\nFix response rendering with empty context. (\n#4495\n)\n\n\nFix indentation regression in API listing. (\n#4493\n)\n\n\nFixed an issue where the incorrect value is set to \nResolverMatch.func_name\n of api_view decorated view. (\n#4465\n, \n#4462\n)\n\n\nFix \nAPIClient.get()\n when path contains unicode arguments (\n#4458\n)\n\n\n\n\n3.4.6\n\n\nDate\n: \n23rd August 2016\n\n\n\n\nFix malformed Javascript in browsable API. (\n#4435\n)\n\n\nSkip HiddenField from Schema fields. (\n#4425\n, \n#4429\n)\n\n\nImprove Create to show the original exception traceback. (\n#3508\n)\n\n\nFix \nAdminRenderer\n display of PK only related fields. (\n#4419\n, \n#4423\n)\n\n\n\n\n3.4.5\n\n\nDate\n: \n19th August 2016\n\n\n\n\nImprove debug error handling. (\n#4416\n, \n#4409\n)\n\n\nAllow custom CSRF_HEADER_NAME setting. (\n#4415\n, \n#4410\n)\n\n\nInclude .action attribute on viewsets when generating schemas. (\n#4408\n, \n#4398\n)\n\n\nDo not include request.FILES items in request.POST. (\n#4407\n)\n\n\nFix rendering of checkbox multiple. (\n#4403\n)\n\n\nFix docstring of Field.get_default. (\n#4404\n)\n\n\nReplace utf8 character with its ascii counterpart in README. (\n#4412\n)\n\n\n\n\n3.4.4\n\n\nDate\n: \n12th August 2016\n\n\n\n\nEnsure views are fully initialized when generating schemas. (\n#4373\n, \n#4382\n, \n#4383\n, \n#4279\n, \n#4278\n)\n\n\nAdd form field descriptions to schemas. (\n#4387\n)\n\n\nFix category generation for schema endpoints. (\n#4391\n, \n#4394\n, \n#4390\n, \n#4386\n, \n#4376\n, \n#4329\n)\n\n\nDon't strip empty query params when paginating. (\n#4392\n, \n#4393\n, \n#4260\n)\n\n\nDo not re-run query for empty results with LimitOffsetPagination. (\n#4201\n, \n#4388\n)\n\n\nStricter type validation for CharField. (\n#4380\n, \n#3394\n)\n\n\nRelatedField.choices should preserve non-string values. (\n#4111\n, \n#4379\n, \n#3365\n)\n\n\nTest case for rendering checkboxes in vertical form style. (\n#4378\n, \n#3868\n, \n#3868\n)\n\n\nShow error traceback HTML in browsable API (\n#4042\n, \n#4172\n)\n\n\nFix handling of ALLOWED_VERSIONS and no DEFAULT_VERSION. \n#4370\n\n\nAllow \nmax_digits=None\n on DecimalField. (\n#4377\n, \n#4372\n)\n\n\nLimit queryset when rendering relational choices. (\n#4375\n, \n#4122\n, \n#3329\n, \n#3330\n, \n#3877\n)\n\n\nResolve form display with ChoiceField, MultipleChoiceField and non-string choices. (\n#4374\n, \n#4119\n, \n#4121\n, \n#4137\n, \n#4120\n)\n\n\nFix call to TemplateHTMLRenderer.resolve_context() fallback method. (\n#4371\n)\n\n\n\n\n3.4.3\n\n\nDate\n: \n5th August 2016\n\n\n\n\nInclude fallback for users of older TemplateHTMLRenderer internal API. (\n#4361\n)\n\n\n\n\n3.4.2\n\n\nDate\n: \n5th August 2016\n\n\n\n\nInclude kwargs passed to 'as_view' when generating schemas. (\n#4359\n, \n#4330\n, \n#4331\n)\n\n\nAccess \nrequest.user.is_authenticated\n as property not method, under Django 1.10+ (\n#4358\n, \n#4354\n)\n\n\nFilter HEAD out from schemas. (\n#4357\n)\n\n\nextra_kwargs takes precedence over uniqueness kwargs. (\n#4198\n, \n#4199\n, \n#4349\n)\n\n\nCorrect descriptions when tabs are used in code indentation. (\n#4345\n, \n#4347\n)*\n\n\nChange template context generation in TemplateHTMLRenderer. (\n#4236\n)\n\n\nSerializer defaults should not be included in partial updates. (\n#4346\n, \n#3565\n)\n\n\nConsistent behavior & descriptive error from FileUploadParser when filename not included. (\n#4340\n, \n#3610\n, \n#4292\n, \n#4296\n)\n\n\nDecimalField quantizes incoming digitals. (\n#4339\n, \n#4318\n)\n\n\nHandle non-string input for IP fields. (\n#4335\n, \n#4336\n, \n#4338\n)\n\n\nFix leading slash handling when Schema generation includes a root URL. (\n#4332\n)\n\n\nTest cases for DictField with allow_null options. (\n#4348\n)\n\n\nUpdate tests from Django 1.10 beta to Django 1.10. (\n#4344\n)\n\n\n\n\n3.4.1\n\n\nDate\n: \n28th July 2016\n\n\n\n\nAdded \nroot_renderers\n argument to \nDefaultRouter\n. (\n#4323\n, \n#4268\n)\n\n\nAdded \nurl\n and \nschema_url\n arguments. (\n#4321\n, \n#4308\n, \n#4305\n)\n\n\nUnique together checks should apply to read-only fields which have a default. (\n#4316\n, \n#4294\n)\n\n\nSet view.format_kwarg in schema generator. (\n#4293\n, \n#4315\n)\n\n\nFix schema generator for views with \npagination_class = None\n. (\n#4314\n, \n#4289\n)\n\n\nFix schema generator for views with no \nget_serializer_class\n. (\n#4265\n, \n#4285\n)\n\n\nFixes for media type parameters in \nAccept\n and \nContent-Type\n headers. (\n#4287\n, \n#4313\n, \n#4281\n)\n\n\nUse verbose_name instead of object_name in error messages. (\n#4299\n)\n\n\nMinor version update to Twitter Bootstrap. (\n#4307\n)\n\n\nSearchFilter raises error when using with related field. (\n#4302\n, \n#4303\n, \n#4298\n)\n\n\nAdding support for RFC 4918 status codes. (\n#4291\n)\n\n\nAdd LICENSE.md to the built wheel. (\n#4270\n)\n\n\nSerializing \"complex\" field returns None instead of the value since 3.4 (\n#4272\n, \n#4273\n, \n#4288\n)\n\n\n\n\n3.4.0\n\n\nDate\n: \n14th July 2016\n\n\n\n\nDon't strip microseconds in JSON output. (\n#4256\n)\n\n\nTwo slightly different iso 8601 datetime serialization. (\n#4255\n)\n\n\nResolve incorrect inclusion of media type parameters. (\n#4254\n)\n\n\nResponse Content-Type potentially malformed. (\n#4253\n)\n\n\nFix setup.py error on some platforms. (\n#4246\n)\n\n\nMove alternate formats in coreapi into separate packages. (\n#4244\n)\n\n\nAdd localize keyword argument to \nDecimalField\n. (\n#4233\n)\n\n\nFix issues with routers for custom list-route and detail-routes. (\n#4229\n)\n\n\nNamespace versioning with nested namespaces. (\n#4219\n)\n\n\nRobust uniqueness checks. (\n#4217\n)\n\n\nMinor refactoring of \nmust_call_distinct\n. (\n#4215\n)\n\n\nOverridable offset cutoff in CursorPagination. (\n#4212\n)\n\n\nPass through strings as-in with date/time fields. (\n#4196\n)\n\n\nAdd test confirming that required=False is valid on a relational field. (\n#4195\n)\n\n\nIn LimitOffsetPagination \nlimit=0\n should revert to default limit. (\n#4194\n)\n\n\nExclude read_only=True fields from unique_together validation & add docs. (\n#4192\n)\n\n\nHandle bytestrings in JSON. (\n#4191\n)\n\n\nJSONField(binary=True) represents using binary strings, which JSONRenderer does not support. (\n#4187\n)\n\n\nJSONField(binary=True) represents using binary strings, which JSONRenderer does not support. (\n#4185\n)\n\n\nMore robust form rendering in the browsable API. (\n#4181\n)\n\n\nEmpty cases of \n.validated_data\n and \n.errors\n as lists not dicts for ListSerializer. (\n#4180\n)\n\n\nSchemas & client libraries. (\n#4179\n)\n\n\nRemoved \nAUTH_USER_MODEL\n compat property. (\n#4176\n)\n\n\nClean up existing deprecation warnings. (\n#4166\n)\n\n\nDjango 1.10 support. (\n#4158\n)\n\n\nUpdated jQuery version to 1.12.4. (\n#4157\n)\n\n\nMore robust default behavior on OrderingFilter. (\n#4156\n)\n\n\ndescription.py codes and tests removal. (\n#4153\n)\n\n\nWrap guardian.VERSION in tuple. (\n#4149\n)\n\n\nRefine validator for fields with \n kwargs. (\n#4146\n)\n\n\nFix None values representation in childs of ListField, DictField. (\n#4118\n)\n\n\nResolve TimeField representation for midnight value. (\n#4107\n)\n\n\nSet proper status code in AdminRenderer for the redirection after POST/DELETE requests. (\n#4106\n)\n\n\nTimeField render returns None instead of 00:00:00. (\n#4105\n)\n\n\nFix incorrectly named zh-hans and zh-hant locale path. (\n#4103\n)\n\n\nPrevent raising exception when limit is 0. (\n#4098\n)\n\n\nTokenAuthentication: Allow custom keyword in the header. (\n#4097\n)\n\n\nHandle incorrectly padded HTTP basic auth header. (\n#4090\n)\n\n\nLimitOffset pagination crashes Browseable API when limit=0. (\n#4079\n)\n\n\nFixed DecimalField arbitrary precision support. (\n#4075\n)\n\n\nAdded support for custom CSRF cookie names. (\n#4049\n)\n\n\nFix regression introduced by #4035. (\n#4041\n)\n\n\nNo auth view failing permission should raise 403. (\n#4040\n)\n\n\nFix string_types / text_types confusion. (\n#4025\n)\n\n\nDo not list related field choices in OPTIONS requests. (\n#4021\n)\n\n\nFix typo. (\n#4008\n)\n\n\nReorder initializing the view. (\n#4006\n)\n\n\nType error in DjangoObjectPermissionsFilter on Python 3.4. (\n#4005\n)\n\n\nFixed use of deprecated Query.aggregates. (\n#4003\n)\n\n\nFix blank lines around docstrings. (\n#4002\n)\n\n\nFixed admin pagination when limit is 0. (\n#3990\n)\n\n\nOrderingFilter adjustments. (\n#3983\n)\n\n\nNon-required serializer related fields. (\n#3976\n)\n\n\nUsing safer calling way of \"@api_view\" in tutorial. (\n#3971\n)\n\n\nListSerializer doesn't handle unique_together constraints. (\n#3970\n)\n\n\nAdd missing migration file. (\n#3968\n)\n\n\nOrderingFilter\n should call \nget_serializer_class()\n to determine default fields. (\n#3964\n)\n\n\nRemove old Django checks from tests and compat. (\n#3953\n)\n\n\nSupport callable as the value of \ninitial\n for any \nserializer.Field\n. (\n#3943\n)\n\n\nPrevented unnecessary distinct() call in SearchFilter. (\n#3938\n)\n\n\nFix None UUID ForeignKey serialization. (\n#3936\n)\n\n\nDrop EOL Django 1.7. (\n#3933\n)\n\n\nAdd missing space in serializer error message. (\n#3926\n)\n\n\nFixed _force_text_recursive typo. (\n#3908\n)\n\n\nAttempt to address Django 2.0 deprecate warnings related to \nfield.rel\n. (\n#3906\n)\n\n\nFix parsing multipart data using a nested serializer with list. (\n#3820\n)\n\n\nResolving APIs URL to different namespaces. (\n#3816\n)\n\n\nDo not HTML-escape \nhelp_text\n in Browsable API forms. (\n#3812\n)\n\n\nOPTIONS fetches and shows all possible foreign keys in choices field. (\n#3751\n)\n\n\nDjango 1.9 deprecation warnings (\n#3729\n)\n\n\nTest case for #3598 (\n#3710\n)\n\n\nAdding support for multiple values for search filter. (\n#3541\n)\n\n\nUse get_serializer_class in ordering filter. (\n#3487\n)\n\n\nSerializers with many=True should return empty list rather than empty dict. (\n#3476\n)\n\n\nLimitOffsetPagination limit=0 fix. (\n#3444\n)\n\n\nEnable Validators to defer string evaluation and handle new string format. (\n#3438\n)\n\n\nUnique validator is executed and breaks if field is invalid. (\n#3381\n)\n\n\nDo not ignore overridden View.get_view_name() in breadcrumbs. (\n#3273\n)\n\n\nRetry form rendering when rendering with serializer fails. (\n#3164\n)\n\n\nUnique constraint prevents nested serializers from updating. (\n#2996\n)\n\n\nUniqueness validators should not be run for excluded (read_only) fields. (\n#2848\n)\n\n\nUniqueValidator raises exception for nested objects. (\n#2403\n)\n\n\nlookup_type\n is deprecated in favor of \nlookup_expr\n. (\n#4259\n)\n\n\n\n\n\n\n3.3.x series\n\n\n3.3.3\n\n\nDate\n: \n14th March 2016\n.\n\n\n\n\nRemove version string from templates. Thanks to @blag for the report and fixes. (\n#3878\n, \n#3913\n, \n#3912\n)\n\n\nFixes vertical html layout for \nBooleanField\n. Thanks to Mikalai Radchuk for the fix. (\n#3910\n)\n\n\nSilenced deprecation warnings on Django 1.8. Thanks to Simon Charette for the fix. (\n#3903\n)\n\n\nInternationalization for authtoken. Thanks to Michael Nacharov for the fix. (\n#3887\n, \n#3968\n)\n\n\nFix \nToken\n model as \nabstract\n when the authtoken application isn't declared. Thanks to Adam Thomas for the report. (\n#3860\n, \n#3858\n)\n\n\nImprove Markdown version compatibility. Thanks to Michael J. Schultz for the fix. (\n#3604\n, \n#3842\n)\n\n\nQueryParameterVersioning\n does not use \nDEFAULT_VERSION\n setting. Thanks to Brad Montgomery for the fix. (\n#3833\n)\n\n\nAdd an explicit \non_delete\n on the models. Thanks to Mads Jensen for the fix. (\n#3832\n)\n\n\nFix \nDateField.to_representation\n to work with Python 2 unicode. Thanks to Mikalai Radchuk for the fix. (\n#3819\n)\n\n\nFixed \nTimeField\n not handling string times. Thanks to Areski Belaid for the fix. (\n#3809\n)\n\n\nAvoid updates of \nMeta.extra_kwargs\n. Thanks to Kevin Massey for the report and fix. (\n#3805\n, \n#3804\n)\n\n\nFix nested validation error being rendered incorrectly. Thanks to Craig de Stigter for the fix. (\n#3801\n)\n\n\nDocument how to avoid CSRF and missing button issues with \ndjango-crispy-forms\n. Thanks to Emmanuelle Delescolle, Jos\u00e9 Padilla and Luis San Pablo for the report, analysis and fix. (\n#3787\n, \n#3636\n, \n#3637\n)\n\n\nImprove Rest Framework Settings file setup time. Thanks to Miles Hutson for the report and Mads Jensen for the fix. (\n#3786\n, \n#3815\n)\n\n\nImprove authtoken compatibility with Django 1.9. Thanks to S. Andrew Sheppard for the fix. (\n#3785\n)\n\n\nFix \nMin/MaxValueValidator\n transfer from a model's \nDecimalField\n. Thanks to Kevin Brown for the fix. (\n#3774\n)\n\n\nImprove HTML title in the Browsable API. Thanks to Mike Lissner for the report and fix. (\n#3769\n)\n\n\nFix \nAutoFilterSet\n to inherit from \ndefault_filter_set\n. Thanks to Tom Linford for the fix. (\n#3753\n)\n\n\nFix transifex config to handle the new Chinese language codes. Thanks to @nypisces for the report and fix. (\n#3739\n)\n\n\nDateTimeField\n does not handle empty values correctly. Thanks to Mick Parker for the report and fix. (\n#3731\n, \n#3726\n)\n\n\nRaise error when setting a removed rest_framework setting. Thanks to Luis San Pablo for the fix. (\n#3715\n)\n\n\nAdd missing csrf_token in AdminRenderer post form. Thanks to Piotr \u015aniegowski for the fix. (\n#3703\n)\n\n\nRefactored \n_get_reverse_relationships()\n to use correct \nto_field\n. Thanks to Benjamin Phillips for the fix. (\n#3696\n)\n\n\nDocument the use of \nget_queryset\n for \nRelatedField\n. Thanks to Ryan Hiebert for the fix. (\n#3605\n)\n\n\nFix empty pk detection in HyperlinkRelatedField.get_url. Thanks to @jslang for the fix (\n#3962\n)\n\n\n\n\n3.3.2\n\n\nDate\n: \n14th December 2015\n.\n\n\n\n\nListField\n enforces input is a list. (\n#3513\n)\n\n\nFix regression hiding raw data form. (\n#3600\n, \n#3578\n)\n\n\nFix Python 3.5 compatibility. (\n#3534\n, \n#3626\n)\n\n\nAllow setting a custom Django Paginator in \npagination.PageNumberPagination\n. (\n#3631\n, \n#3684\n)\n\n\nFix relational fields without \nto_fields\n attribute. (\n#3635\n, \n#3634\n)\n\n\nFix \ntemplate.render\n deprecation warnings for Django 1.9. (\n#3654\n)\n\n\nSort response headers in browsable API renderer. (\n#3655\n)\n\n\nUse related_objects api for Django 1.9+. (\n#3656\n, \n#3252\n)\n\n\nAdd confirm modal when deleting. (\n#3228\n, \n#3662\n)\n\n\nReveal previously hidden AttributeErrors and TypeErrors while calling has_[object_]permissions. (\n#3668\n)\n\n\nMake DRF compatible with multi template engine in Django 1.8. (\n#3672\n)\n\n\nUpdate \nNestedBoundField\n to also handle empty string when rendering its form. (\n#3677\n)\n\n\nFix UUID validation to properly catch invalid input types. (\n#3687\n, \n#3679\n)\n\n\nFix caching issues. (\n#3628\n, \n#3701\n)\n\n\nFix Admin and API browser for views without a filter_class. (\n#3705\n, \n#3596\n, \n#3597\n)\n\n\nAdd app_name to rest_framework.urls. (\n#3714\n)\n\n\nImprove authtoken's views to support url versioning. (\n#3718\n, \n#3723\n)\n\n\n\n\n3.3.1\n\n\nDate\n: \n4th November 2015\n.\n\n\n\n\nResolve parsing bug when accessing \nrequest.POST\n (\n#3592\n)\n\n\nCorrectly deal with \nto_field\n referring to primary key. (\n#3593\n)\n\n\nAllow filter HTML to render when no \nfilter_class\n is defined. (\n#3560\n)\n\n\nFix admin rendering issues. (\n#3564\n, \n#3556\n)\n\n\nFix issue with DecimalValidator. (\n#3568\n)\n\n\n\n\n3.3.0\n\n\nDate\n: \n28th October 2015\n.\n\n\n\n\nHTML controls for filters. (\n#3315\n)\n\n\nForms API. (\n#3475\n)\n\n\nAJAX browsable API. (\n#3410\n)\n\n\nAdded JSONField. (\n#3454\n)\n\n\nCorrectly map \nto_field\n when creating \nModelSerializer\n relational fields. (\n#3526\n)\n\n\nInclude keyword arguments when mapping \nFilePathField\n to a serializer field. (\n#3536\n)\n\n\nMap appropriate model \nerror_messages\n on \nModelSerializer\n uniqueness constraints. (\n#3435\n)\n\n\nInclude \nmax_length\n constraint for \nModelSerializer\n fields mapped from TextField. (\n#3509\n)\n\n\nAdded support for Django 1.9. (\n#3450\n, \n#3525\n)\n\n\nRemoved support for Django 1.5 & 1.6. (\n#3421\n, \n#3429\n)\n\n\nRemoved 'south' migrations. (\n#3495\n)\n\n\n\n\n\n\n3.2.x series\n\n\n3.2.5\n\n\nDate\n: \n27th October 2015\n.\n\n\n\n\nEscape \nusername\n in optional logout tag. (\n#3550\n)\n\n\n\n\n3.2.4\n\n\nDate\n: \n21th September 2015\n.\n\n\n\n\nDon't error on missing \nViewSet.search_fields\n attribute. (\n#3324\n, \n#3323\n)\n\n\nFix \nallow_empty\n not working on serializers with \nmany=True\n. (\n#3361\n, \n#3364\n)\n\n\nLet \nDurationField\n accepts integers. (\n#3359\n)\n\n\nMulti-level dictionaries not supported in multipart requests. (\n#3314\n)\n\n\nFix \nListField\n truncation on HTTP PATCH (\n#3415\n, \n#2761\n)\n\n\n\n\n3.2.3\n\n\nDate\n: \n24th August 2015\n.\n\n\n\n\nAdded \nhtml_cutoff\n and \nhtml_cutoff_text\n for limiting select dropdowns. (\n#3313\n)\n\n\nAdded regex style to \nSearchFilter\n. (\n#3316\n)\n\n\nResolve issues with setting blank HTML fields. (\n#3318\n) (\n#3321\n)\n\n\nCorrectly display existing 'select multiple' values in browsable API forms. (\n#3290\n)\n\n\nResolve duplicated validation message for \nIPAddressField\n. ([#3249[gh3249]) (\n#3250\n)\n\n\nFix to ensure admin renderer continues to work when pagination is disabled. (\n#3275\n)\n\n\nResolve error with \nLimitOffsetPagination\n when count=0, offset=0. (\n#3303\n)\n\n\n\n\n3.2.2\n\n\nDate\n: \n13th August 2015\n.\n\n\n\n\nAdd \ndisplay_value()\n method for use when displaying relational field select inputs. (\n#3254\n)\n\n\nFix issue with \nBooleanField\n checkboxes incorrectly displaying as checked. (\n#3258\n)\n\n\nEnsure empty checkboxes properly set \nBooleanField\n to \nFalse\n in all cases. (\n#2776\n)\n\n\nAllow \nWSGIRequest.FILES\n property without raising incorrect deprecated error. (\n#3261\n)\n\n\nResolve issue with rendering nested serializers in forms. (\n#3260\n)\n\n\nRaise an error if user accidentally pass a serializer instance to a response, rather than data. (\n#3241\n)\n\n\n\n\n3.2.1\n\n\nDate\n: \n7th August 2015\n.\n\n\n\n\nFix for relational select widgets rendering without any choices. (\n#3237\n)\n\n\nFix for \n1\n, \n0\n rendering as \ntrue\n, \nfalse\n in the admin interface. \n#3227\n)\n\n\nFix for ListFields with single value in HTML form input. (\n#3238\n)\n\n\nAllow \nrequest.FILES\n for compat with Django's \nHTTPRequest\n class. (\n#3239\n)\n\n\n\n\n3.2.0\n\n\nDate\n: \n6th August 2015\n.\n\n\n\n\nAdd \nAdminRenderer\n. (\n#2926\n)\n\n\nAdd \nFilePathField\n. (\n#1854\n)\n\n\nAdd \nallow_empty\n to \nListField\n. (\n#2250\n)\n\n\nSupport django-guardian 1.3. (\n#3165\n)\n\n\nSupport grouped choices. (\n#3225\n)\n\n\nSupport error forms in browsable API. (\n#3024\n)\n\n\nAllow permission classes to customize the error message. (\n#2539\n)\n\n\nSupport \nsource=\n on hyperlinked fields. (\n#2690\n)\n\n\nListField(allow_null=True)\n now allows null as the list value, not null items in the list. (\n#2766\n)\n\n\nManyToMany()\n maps to \nallow_empty=False\n, \nManyToMany(blank=True)\n maps to \nallow_empty=True\n. (\n#2804\n)\n\n\nSupport custom serialization styles for primary key fields. (\n#2789\n)\n\n\nOPTIONS\n requests support nested representations. (\n#2915\n)\n\n\nSet \nview.action == \"metadata\"\n for viewsets with \nOPTIONS\n requests. (\n#3115\n)\n\n\nSupport \nallow_blank\n on \nUUIDField\n. ([#3130][gh#3130])\n\n\nDo not display view docstrings with 401 or 403 response codes. (\n#3216\n)\n\n\nResolve Django 1.8 deprecation warnings. (\n#2886\n)\n\n\nFix for \nDecimalField\n validation. (\n#3139\n)\n\n\nFix behavior of \nallow_blank=False\n when used with \ntrim_whitespace=True\n. (\n#2712\n)\n\n\nFix issue with some field combinations incorrectly mapping to an invalid \nallow_blank\n argument. (\n#3011\n)\n\n\nFix for output representations with prefetches and modified querysets. (\n#2704\n, \n#2727\n)\n\n\nFix assertion error when CursorPagination is provided with certain invalid query parameters. (#2920)\ngh2920\n.\n\n\nFix \nUnicodeDecodeError\n when invalid characters included in header with \nTokenAuthentication\n. (\n#2928\n)\n\n\nFix transaction rollbacks with \n@non_atomic_requests\n decorator. (\n#3016\n)\n\n\nFix duplicate results issue with Oracle databases using \nSearchFilter\n. (\n#2935\n)\n\n\nFix checkbox alignment and rendering in browsable API forms. (\n#2783\n)\n\n\nFix for unsaved file objects which should use \n\"url\": null\n in the representation. (\n#2759\n)\n\n\nFix field value rendering in browsable API. (\n#2416\n)\n\n\nFix \nHStoreField\n to include \nallow_blank=True\n in \nDictField\n mapping. (\n#2659\n)\n\n\nNumerous other cleanups, improvements to error messaging, private API & minor fixes.\n\n\n\n\n\n\n3.1.x series\n\n\n3.1.3\n\n\nDate\n: \n4th June 2015\n.\n\n\n\n\nAdd \nDurationField\n. (\n#2481\n, \n#2989\n)\n\n\nAdd \nformat\n argument to \nUUIDField\n. (\n#2788\n, \n#3000\n)\n\n\nMultipleChoiceField\n empties incorrectly on a partial update using multipart/form-data (\n#2993\n, \n#2894\n)\n\n\nFix a bug in options related to read-only \nRelatedField\n. (\n#2981\n, \n#2811\n)\n\n\nFix nested serializers with \nunique_together\n relations. (\n#2975\n)\n\n\nAllow unexpected values for \nChoiceField\n/\nMultipleChoiceField\n representations. (\n#2839\n, \n#2940\n)\n\n\nRollback the transaction on error if \nATOMIC_REQUESTS\n is set. (\n#2887\n, \n#2034\n)\n\n\nSet the action on a view when override_method regardless of its None-ness. (\n#2933\n)\n\n\nDecimalField\n accepts \n2E+2\n as 200 and validates decimal place correctly. (\n#2948\n, \n#2947\n)\n\n\nSupport basic authentication with custom \nUserModel\n that change \nusername\n. (\n#2952\n)\n\n\nIPAddressField\n improvements. (\n#2747\n, \n#2618\n, \n#3008\n)\n\n\nImprove \nDecimalField\n for easier subclassing. (\n#2695\n)\n\n\n\n\n3.1.2\n\n\nDate\n: \n13rd May 2015\n.\n\n\n\n\nDateField.to_representation\n can handle str and empty values. (\n#2656\n, \n#2687\n, \n#2869\n)\n\n\nUse default reason phrases from HTTP standard. (\n#2764\n, \n#2763\n)\n\n\nRaise error when \nModelSerializer\n used with abstract model. (\n#2757\n, \n#2630\n)\n\n\nHandle reversal of non-API view_name in \nHyperLinkedRelatedField\n (\n#2724\n, \n#2711\n)\n\n\nDon't require pk strictly for related fields. (\n#2745\n, \n#2754\n)\n\n\nMetadata detects null boolean field type. (\n#2762\n)\n\n\nProper handling of depth in nested serializers. (\n#2798\n)\n\n\nDisplay viewset without paginator. (\n#2807\n)\n\n\nDon't check for deprecated \n.model\n attribute in permissions (\n#2818\n)\n\n\nRestrict integer field to integers and strings. (\n#2835\n, \n#2836\n)\n\n\nImprove \nIntegerField\n to use compiled decimal regex. (\n#2853\n)\n\n\nPrevent empty \nqueryset\n to raise AssertionError. (\n#2862\n)\n\n\nDjangoModelPermissions\n rely on \nget_queryset\n. (\n#2863\n)\n\n\nCheck \nAcceptHeaderVersioning\n with content negotiation in place. (\n#2868\n)\n\n\nAllow \nDjangoObjectPermissions\n to use views that define \nget_queryset\n. (\n#2905\n)\n\n\n\n\n3.1.1\n\n\nDate\n: \n23rd March 2015\n.\n\n\n\n\nSecurity fix\n: Escape tab switching cookie name in browsable API.\n\n\nDisplay input forms in browsable API if \nserializer_class\n is used, even when \nget_serializer\n method does not exist on the view. (\n#2743\n)\n\n\nUse a password input for the AuthTokenSerializer. (\n#2741\n)\n\n\nFix missing anchor closing tag after next button. (\n#2691\n)\n\n\nFix \nlookup_url_kwarg\n handling in viewsets. (\n#2685\n, \n#2591\n)\n\n\nFix problem with importing \nrest_framework.views\n in \napps.py\n (\n#2678\n)\n\n\nLimitOffsetPagination raises \nTypeError\n if PAGE_SIZE not set (\n#2667\n, \n#2700\n)\n\n\nGerman translation for \nmin_value\n field error message references \nmax_value\n. (\n#2645\n)\n\n\nRemove \nMergeDict\n. (\n#2640\n)\n\n\nSupport serializing unsaved models with related fields. (\n#2637\n, \n#2641\n)\n\n\nAllow blank/null on radio.html choices. (\n#2631\n)\n\n\n\n\n3.1.0\n\n\nDate\n: \n5th March 2015\n.\n\n\nFor full details see the \n3.1 release announcement\n.\n\n\n\n\n3.0.x series\n\n\n3.0.5\n\n\nDate\n: \n10th February 2015\n.\n\n\n\n\nFix a bug where \n_closable_objects\n breaks pickling. (\n#1850\n, \n#2492\n)\n\n\nAllow non-standard \nUser\n models with \nThrottling\n. (\n#2524\n)\n\n\nSupport custom \nUser.db_table\n in TokenAuthentication migration. (\n#2479\n)\n\n\nFix misleading \nAttributeError\n tracebacks on \nRequest\n objects. (\n#2530\n, \n#2108\n)\n\n\nManyRelatedField.get_value\n clearing field on partial update. (\n#2475\n)\n\n\nRemoved '.model' shortcut from code. (\n#2486\n)\n\n\nFix \ndetail_route\n and \nlist_route\n mutable argument. (\n#2518\n)\n\n\nPrefetching the user object when getting the token in \nTokenAuthentication\n. (\n#2519\n)\n\n\n\n\n3.0.4\n\n\nDate\n: \n28th January 2015\n.\n\n\n\n\nDjango 1.8a1 support. (\n#2425\n, \n#2446\n, \n#2441\n)\n\n\nAdd \nDictField\n and support Django 1.8 \nHStoreField\n. (\n#2451\n, \n#2106\n)\n\n\nAdd \nUUIDField\n and support Django 1.8 \nUUIDField\n. (\n#2448\n, \n#2433\n, \n#2432\n)\n\n\nBaseRenderer.render\n now raises \nNotImplementedError\n. (\n#2434\n)\n\n\nFix timedelta JSON serialization on Python 2.6. (\n#2430\n)\n\n\nResultDict\n and \nResultList\n now appear as standard dict/list. (\n#2421\n)\n\n\nFix visible \nHiddenField\n in the HTML form of the web browsable API page. (\n#2410\n)\n\n\nUse \nOrderedDict\n for \nRelatedField.choices\n. (\n#2408\n)\n\n\nFix ident format when using \nHTTP_X_FORWARDED_FOR\n. (\n#2401\n)\n\n\nFix invalid key with memcached while using throttling. (\n#2400\n)\n\n\nFix \nFileUploadParser\n with version 3.x. (\n#2399\n)\n\n\nFix the serializer inheritance. (\n#2388\n)\n\n\nFix caching issues with \nReturnDict\n. (\n#2360\n)\n\n\n\n\n3.0.3\n\n\nDate\n: \n8th January 2015\n.\n\n\n\n\nFix \nMinValueValidator\n on \nmodels.DateField\n. (\n#2369\n)\n\n\nFix serializer missing context when pagination is used. (\n#2355\n)\n\n\nNamespaced router URLs are now supported by the \nDefaultRouter\n. (\n#2351\n)\n\n\nrequired=False\n allows omission of value for output. (\n#2342\n)\n\n\nUse textarea input for \nmodels.TextField\n. (\n#2340\n)\n\n\nUse custom \nListSerializer\n for pagination if required. (\n#2331\n, \n#2327\n)\n\n\nBetter behavior with null and '' for blank HTML fields. (\n#2330\n)\n\n\nEnsure fields in \nexclude\n are model fields. (\n#2319\n)\n\n\nFix \nIntegerField\n and \nmax_length\n argument incompatibility. (\n#2317\n)\n\n\nFix the YAML encoder for 3.0 serializers. (\n#2315\n, \n#2283\n)\n\n\nFix the behavior of empty HTML fields. (\n#2311\n, \n#1101\n)\n\n\nFix Metaclass attribute depth ignoring fields attribute. (\n#2287\n)\n\n\nFix \nformat_suffix_patterns\n to work with Django's \ni18n_patterns\n. (\n#2278\n)\n\n\nAbility to customize router URLs for custom actions, using \nurl_path\n. (\n#2010\n)\n\n\nDon't install Django REST Framework as egg. (\n#2386\n)\n\n\n\n\n3.0.2\n\n\nDate\n: \n17th December 2014\n.\n\n\n\n\nEnsure \nrequest.user\n is made available to response middleware. (\n#2155\n)\n\n\nClient.logout()\n also cancels any existing \nforce_authenticate\n. (\n#2218\n, \n#2259\n)\n\n\nExtra assertions and better checks to preventing incorrect serializer API use. (\n#2228\n, \n#2234\n, \n#2262\n, \n#2263\n, \n#2266\n, \n#2267\n, \n#2289\n, \n#2291\n)\n\n\nFixed \nmin_length\n message for \nCharField\n. (\n#2255\n)\n\n\nFix \nUnicodeDecodeError\n, which can occur on serializer \nrepr\n. (\n#2270\n, \n#2279\n)\n\n\nFix empty HTML values when a default is provided. (\n#2280\n, \n#2294\n)\n\n\nFix \nSlugRelatedField\n raising \nUnicodeEncodeError\n when used as a multiple choice input. (\n#2290\n)\n\n\n\n\n3.0.1\n\n\nDate\n: \n11th December 2014\n.\n\n\n\n\nMore helpful error message when the default Serializer \ncreate()\n fails. (\n#2013\n)\n\n\nRaise error when attempting to save serializer if data is not valid. (\n#2098\n)\n\n\nFix \nFileUploadParser\n breaks with empty file names and multiple upload handlers. (\n#2109\n)\n\n\nImprove \nBindingDict\n to support standard dict-functions. (\n#2135\n, \n#2163\n)\n\n\nAdd \nvalidate()\n to \nListSerializer\n. (\n#2168\n, \n#2225\n, \n#2232\n)\n\n\nFix JSONP renderer failing to escape some characters. (\n#2169\n, \n#2195\n)\n\n\nAdd missing default style for \nFileField\n. (\n#2172\n)\n\n\nActions are required when calling \nViewSet.as_view()\n. (\n#2175\n)\n\n\nAdd \nallow_blank\n to \nChoiceField\n. (\n#2184\n, \n#2239\n)\n\n\nCosmetic fixes in the HTML renderer. (\n#2187\n)\n\n\nRaise error if \nfields\n on serializer is not a list of strings. (\n#2193\n, \n#2213\n)\n\n\nImprove checks for nested creates and updates. (\n#2194\n, \n#2196\n)\n\n\nvalidated_attrs\n argument renamed to \nvalidated_data\n in \nSerializer\n \ncreate()\n/\nupdate()\n. (\n#2197\n)\n\n\nRemove deprecated code to reflect the dropped Django versions. (\n#2200\n)\n\n\nBetter serializer errors for nested writes. (\n#2202\n, \n#2215\n)\n\n\nFix pagination and custom permissions incompatibility. (\n#2205\n)\n\n\nRaise error if \nfields\n on serializer is not a list of strings. (\n#2213\n)\n\n\nAdd missing translation markers for relational fields. (\n#2231\n)\n\n\nImprove field lookup behavior for dicts/mappings. (\n#2244\n, \n#2243\n)\n\n\nOptimized hyperlinked PK. (\n#2242\n)\n\n\n\n\n3.0.0\n\n\nDate\n: 1st December 2014\n\n\nFor full details see the \n3.0 release announcement\n.\n\n\n\n\nFor older release notes, \nplease see the version 2.x documentation\n.", "title": "Release Notes" }, { @@ -4960,6 +4955,11 @@ "text": "", "title": "3.9.x series" }, + { + "location": "/community/release-notes/#391", + "text": "Date : 16th Janurary 2019 Resolve XSS issue in browsable API. #6330 Resolve issues with composable permissions. #6299 Respect limit_choices_to on foreign keys. #6371", + "title": "3.9.1" + }, { "location": "/community/release-notes/#390", "text": "Date : 18th October 2018 Improvements to ViewSet extra actions #5605 Fix action support for ViewSet suffixes #6081 Allow action docs sections #6060 Deprecate the Router.register base_name argument in favor of basename . #5990 Deprecate the Router.get_default_base_name method in favor of Router.get_default_basename . #5990 Change CharField to disallow null bytes. #6073 \n To revert to the old behavior, subclass CharField and remove ProhibitNullCharactersValidator from the validators.\n python\n class NullableCharField(serializers.CharField):\n def __init__(self, *args, **kwargs):\n super().__init__(*args, **kwargs)\n self.validators = [v for v in self.validators if not isinstance(v, ProhibitNullCharactersValidator)] Add OpenAPIRenderer and generate_schema management command. #6229 Add OpenAPIRenderer by default, and add schema docs. #6233 Allow permissions to be composed #5753 Allow nullable BooleanField in Django 2.1 #6183 Add testing of Python 3.7 support #6141 Test using Django 2.1 final release. #6109 Added djangorestframework-datatables to third-party packages #5931 Change ISO 8601 date format to exclude year/month #5936 Update all pypi.python.org URLs to pypi.org #5942 Ensure that html forms (multipart form data) respect optional fields #5927 Allow hashing of ErrorDetail. #5932 Correct schema parsing for JSONField #5878 Render descriptions (from help_text) using safe #5869 Removed input value from deault_error_message #5881 Added min_value/max_value support in DurationField #5643 Fixed instance being overwritten in pk-only optimization try/except block #5747 Fixed AttributeError from items filter when value is None #5981 Fixed Javascript e.indexOf is not a function error #5982 Fix schemas for extra actions #5992 Improved get_error_detail to use error_dict/error_list #5785 Imprvied URLs in Admin renderer #5988 Add \"Community\" section to docs, minor cleanup #5993 Moved guardian imports out of compat #6054 Deprecate the DjangoObjectPermissionsFilter class, moved to the djangorestframework-guardian package. #6075 Drop Django 1.10 support #5657 Only catch TypeError/ValueError for object lookups #6028 Handle models without .objects manager in ModelSerializer. #6111 Improve ModelSerializer.create() error message. #6112 Fix CSRF cookie check failure when using session auth with django 1.11.6+ #6113 Updated JWT docs. #6138 Fix autoescape not getting passed to urlize_quoted_links filter #6191", @@ -6157,7 +6157,7 @@ }, { "location": "/community/jobs/", - "text": "Jobs\n\n\nLooking for a new Django REST Framework related role? On this site we provide a list of job resources that may be helpful. It's also worth checking out if any of \nour sponsors are hiring\n.\n\n\nPlaces to look for Django REST Framework Jobs\n\n\n\n\nhttps://www.djangoproject.com/community/jobs/\n\n\nhttps://www.python.org/jobs/\n\n\nhttps://djangogigs.com\n\n\nhttps://djangojobs.net/jobs/\n\n\nhttp://djangojobbers.com\n\n\nhttps://www.indeed.com/q-Django-jobs.html\n\n\nhttps://stackoverflow.com/jobs/developer-jobs-using-django\n\n\nhttps://www.upwork.com/o/jobs/browse/skill/django-framework/\n\n\nhttps://www.technojobs.co.uk/django-jobs\n\n\nhttps://remoteok.io/remote-django-jobs\n\n\nhttps://www.remotepython.com/jobs/\n\n\nhttps://weworkcontract.com/python-contract-jobs\n\n\n\n\nKnow of any other great resources for Django REST Framework jobs that are missing in our list? Please \nsubmit a pull request\n or \nemail us\n.\n\n\nWonder how else you can help? One of the best ways you can help Django REST Framework is to ask interviewers if their company is signed up for \nREST Framework sponsorship\n yet.", + "text": "Jobs\n\n\nLooking for a new Django REST Framework related role? On this site we provide a list of job resources that may be helpful. It's also worth checking out if any of \nour sponsors are hiring\n.\n\n\nPlaces to look for Django REST Framework Jobs\n\n\n\n\nhttps://www.djangoproject.com/community/jobs/\n\n\nhttps://www.python.org/jobs/\n\n\nhttps://djangogigs.com\n\n\nhttps://djangojobs.net/jobs/\n\n\nhttps://www.indeed.com/q-Django-jobs.html\n\n\nhttps://stackoverflow.com/jobs/developer-jobs-using-django\n\n\nhttps://www.upwork.com/o/jobs/browse/skill/django-framework/\n\n\nhttps://www.technojobs.co.uk/django-jobs\n\n\nhttps://remoteok.io/remote-django-jobs\n\n\nhttps://www.remotepython.com/jobs/\n\n\n\n\nKnow of any other great resources for Django REST Framework jobs that are missing in our list? Please \nsubmit a pull request\n or \nemail us\n.\n\n\nWonder how else you can help? One of the best ways you can help Django REST Framework is to ask interviewers if their company is signed up for \nREST Framework sponsorship\n yet.", "title": "Jobs" }, { @@ -6167,7 +6167,7 @@ }, { "location": "/community/jobs/#places-to-look-for-django-rest-framework-jobs", - "text": "https://www.djangoproject.com/community/jobs/ https://www.python.org/jobs/ https://djangogigs.com https://djangojobs.net/jobs/ http://djangojobbers.com https://www.indeed.com/q-Django-jobs.html https://stackoverflow.com/jobs/developer-jobs-using-django https://www.upwork.com/o/jobs/browse/skill/django-framework/ https://www.technojobs.co.uk/django-jobs https://remoteok.io/remote-django-jobs https://www.remotepython.com/jobs/ https://weworkcontract.com/python-contract-jobs Know of any other great resources for Django REST Framework jobs that are missing in our list? Please submit a pull request or email us . Wonder how else you can help? One of the best ways you can help Django REST Framework is to ask interviewers if their company is signed up for REST Framework sponsorship yet.", + "text": "https://www.djangoproject.com/community/jobs/ https://www.python.org/jobs/ https://djangogigs.com https://djangojobs.net/jobs/ https://www.indeed.com/q-Django-jobs.html https://stackoverflow.com/jobs/developer-jobs-using-django https://www.upwork.com/o/jobs/browse/skill/django-framework/ https://www.technojobs.co.uk/django-jobs https://remoteok.io/remote-django-jobs https://www.remotepython.com/jobs/ Know of any other great resources for Django REST Framework jobs that are missing in our list? Please submit a pull request or email us . Wonder how else you can help? One of the best ways you can help Django REST Framework is to ask interviewers if their company is signed up for REST Framework sponsorship yet.", "title": "Places to look for Django REST Framework Jobs" } ] diff --git a/sitemap.xml b/sitemap.xml index 53c23ebe7..bc75617df 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -4,7 +4,7 @@ https://www.django-rest-framework.org// - 2018-12-18 + 2019-01-16 daily @@ -13,49 +13,49 @@ https://www.django-rest-framework.org//tutorial/quickstart/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//tutorial/1-serialization/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//tutorial/2-requests-and-responses/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//tutorial/3-class-based-views/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//tutorial/4-authentication-and-permissions/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//tutorial/5-relationships-and-hyperlinked-apis/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//tutorial/6-viewsets-and-routers/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//tutorial/7-schemas-and-client-libraries/ - 2018-12-18 + 2019-01-16 daily @@ -65,169 +65,169 @@ https://www.django-rest-framework.org//api-guide/requests/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/responses/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/views/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/generic-views/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/viewsets/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/routers/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/parsers/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/renderers/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/serializers/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/fields/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/relations/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/validators/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/authentication/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/permissions/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/caching/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/throttling/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/filtering/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/pagination/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/versioning/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/content-negotiation/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/metadata/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/schemas/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/format-suffixes/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/reverse/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/exceptions/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/status-codes/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/testing/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//api-guide/settings/ - 2018-12-18 + 2019-01-16 daily @@ -237,49 +237,49 @@ https://www.django-rest-framework.org//topics/documenting-your-api/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//topics/api-clients/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//topics/internationalization/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//topics/ajax-csrf-cors/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//topics/html-and-forms/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//topics/browser-enhancements/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//topics/browsable-api/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//topics/rest-hypermedia-hateoas/ - 2018-12-18 + 2019-01-16 daily @@ -289,115 +289,115 @@ https://www.django-rest-framework.org//community/tutorials-and-resources/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/third-party-packages/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/contributing/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/project-management/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/release-notes/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.9-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.8-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.7-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.6-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.5-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.4-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.3-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.2-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.1-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/3.0-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/kickstarter-announcement/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/mozilla-grant/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/funding/ - 2018-12-18 + 2019-01-16 daily https://www.django-rest-framework.org//community/jobs/ - 2018-12-18 + 2019-01-16 daily diff --git a/topics/browsable-api/index.html b/topics/browsable-api/index.html index 61a87ee59..86ad2f387 100644 --- a/topics/browsable-api/index.html +++ b/topics/browsable-api/index.html @@ -496,7 +496,9 @@

    Login Template

    To add branding and customize the look-and-feel of the login template, create a template called login.html and add it to your project, eg: templates/rest_framework/login.html. The template should extend from rest_framework/login_base.html.

    You can add your site name or branding by including the branding block:

    -
    {% block branding %}
    +
    {% extends "rest_framework/login_base.html" %}
    +
    +{% block branding %}
         <h3 style="margin: 0 0 20px;">My Site Name</h3>
     {% endblock %}
     
    diff --git a/tutorial/4-authentication-and-permissions/index.html b/tutorial/4-authentication-and-permissions/index.html index 54042d5f8..d16291fc1 100644 --- a/tutorial/4-authentication-and-permissions/index.html +++ b/tutorial/4-authentication-and-permissions/index.html @@ -605,20 +605,20 @@ class IsOwnerOrReadOnly(permissions.BasePermission):

    When we interact with the API through the web browser, we can login, and the browser session will then provide the required authentication for the requests.

    If we're interacting with the API programmatically we need to explicitly provide the authentication credentials on each request.

    If we try to create a snippet without authenticating, we'll get an error:

    -
    http POST http://127.0.0.1:8000/snippets/ code="print 123"
    +
    http POST http://127.0.0.1:8000/snippets/ code="print(123)"
     
     {
         "detail": "Authentication credentials were not provided."
     }
     

    We can make a successful request by including the username and password of one of the users we created earlier.

    -
    http -a admin:password123 POST http://127.0.0.1:8000/snippets/ code="print 789"
    +
    http -a admin:password123 POST http://127.0.0.1:8000/snippets/ code="print(789)"
     
     {
         "id": 1,
         "owner": "admin",
         "title": "foo",
    -    "code": "print 789",
    +    "code": "print(789)",
         "linenos": false,
         "language": "python",
         "style": "friendly"
    diff --git a/tutorial/quickstart/index.html b/tutorial/quickstart/index.html
    index bad72f2c8..697d748b9 100644
    --- a/tutorial/quickstart/index.html
    +++ b/tutorial/quickstart/index.html
    @@ -491,7 +491,7 @@ $ find .
     ./tutorial/urls.py
     ./tutorial/wsgi.py
     
    -

    It may look unusual that the application has been created within the project directory. Using the project's namespace avoids name clashes with external module (topic goes outside the scope of the quickstart).

    +

    It may look unusual that the application has been created within the project directory. Using the project's namespace avoids name clashes with external modules (a topic that goes outside the scope of the quickstart).

    Now sync your database for the first time:

    python manage.py migrate
     
    @@ -516,7 +516,7 @@ class GroupSerializer(serializers.HyperlinkedModelSerializer): model = Group fields = ('url', 'name')
    -

    Notice that we're using hyperlinked relations in this case, with HyperlinkedModelSerializer. You can also use primary key and various other relationships, but hyperlinking is good RESTful design.

    +

    Notice that we're using hyperlinked relations in this case with HyperlinkedModelSerializer. You can also use primary key and various other relationships, but hyperlinking is good RESTful design.

    Views

    Right, we'd better write some views then. Open tutorial/quickstart/views.py and get typing.

    from django.contrib.auth.models import User, Group
    @@ -543,7 +543,7 @@ class GroupViewSet(viewsets.ModelViewSet):
     

    We can easily break these down into individual views if we need to, but using viewsets keeps the view logic nicely organized as well as being very concise.

    URLs

    Okay, now let's wire up the API URLs. On to tutorial/urls.py...

    -
    from django.conf.urls import url, include
    +
    from django.urls import include, path
     from rest_framework import routers
     from tutorial.quickstart import views
     
    @@ -554,15 +554,15 @@ router.register(r'groups', views.GroupViewSet)
     # Wire up our API using automatic URL routing.
     # Additionally, we include login URLs for the browsable API.
     urlpatterns = [
    -    url(r'^', include(router.urls)),
    -    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
    +    path('', include(router.urls)),
    +    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
     ]
     

    Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.

    Again, if we need more control over the API URLs we can simply drop down to using regular class-based views, and writing the URL conf explicitly.

    Finally, we're including default login and logout views for use with the browsable API. That's optional, but useful if your API requires authentication and you want to use the browsable API.

    Pagination

    -

    Pagination allows you to control how many objects per page are returned. To enable it add following lines to the tutorial/settings.py

    +

    Pagination allows you to control how many objects per page are returned. To enable it add the following lines to tutorial/settings.py

    REST_FRAMEWORK = {
         'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
         'PAGE_SIZE': 10