Django-rest-framework-social-oauth2 library provides an easy way to integrate social plugins (facebook, twitter, google, etc.) to your authentication system and an easy oauth2 setup. With this library, you will be able to authenticate users based on external tokens (e.g. facebook access token), convert these tokens to "in-house" oauth2 tokens and use and generate oauth2 tokens to authenticate your users.
Django-rest-knox library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).
drfpasswordless adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's own TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number.
If you are using the browsable API or admin API you may also want to install django-crispy-forms, which will enhance the presentation of the filter forms in HTML views, by allowing them to render Bootstrap 3 HTML.
-
pip install django-crispy-forms
-
-
With crispy forms installed and added to Django's INSTALLED_APPS, the browsable API will present a filtering control for DjangoFilterBackend, like so:
If all you need is simple equality-based filtering, you can set a filter_fields attribute on the view, or viewset, listing the set of fields you wish to filter against.
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
@@ -635,70 +629,9 @@ class UserListView(generics.ListAPIView):
This will automatically create a FilterSet class for the given fields, and will allow you to make requests such as:
You can also span relationships using django-filter, let's assume that each
-product has foreign key to Manufacturer model, so we create filter that
-filters using Manufacturer name. For example:
This is nice, but it exposes the Django's double underscore convention as part of the API. If you instead want to explicitly name the filter argument you can instead explicitly include it on the FilterSet class:
By default filtering is not enabled. If you want to use DjangoFilterBackend remember to make sure it is installed by using the 'DEFAULT_FILTER_BACKENDS' setting.
-
When using boolean fields, you should use the values True and False in the URL query parameters, rather than 0, 1, true or false. (The allowed boolean values are currently hardwired in Django's NullBooleanSelect implementation.)
-
django-filter supports filtering across relationships, using Django's double-underscore syntax.
-
-
+
For more advanced filtering requirements you can specify a FilterSet class that should be used by the view.
+You can read more about FilterSets in the django-filter documentation.
+It's also recommended that you read the section on DRF integration.
You can also make the filter controls available to the schema autogeneration
-that REST framework provides, by implementing a get_schema_fields() method,
-which should return a list of coreapi.Field instances.
+that REST framework provides, by implementing a get_schema_fields() method. This method should have the following signature:
+
get_schema_fields(self, view)
+
The method should return a list of coreapi.Field instances.
- GitHub
+ GitHub
Next
@@ -469,7 +469,7 @@
-
+ pagination.py
@@ -692,8 +692,9 @@ class StandardResultsSetPagination(PageNumberPagination):
API responses for list endpoints will now include a Link header, instead of including the pagination links as part of the body of the response, for example:
You can also make the pagination controls available to the schema autogeneration
-that REST framework provides, by implementing a get_schema_fields() method,
-which should return a list of coreapi.Field instances.
+that REST framework provides, by implementing a get_schema_fields() method. This method should have the following signature:
+
get_schema_fields(self, view)
+
The method should return a list of coreapi.Field instances.
A custom pagination style, using the 'Link' header'
- GitHub
+ GitHub
Next
@@ -451,7 +451,7 @@
-
+ routers.py
@@ -678,7 +678,7 @@ class CustomReadOnlyRouter(SimpleRouter):
lookup_field = 'username'
@detail_route()
- def group_names(self, request):
+ def group_names(self, request, pk=None):
"""
Returns a list of all the group names that the given
user belongs to.
diff --git a/api-guide/schemas/index.html b/api-guide/schemas/index.html
index 2942068af..913b67d40 100644
--- a/api-guide/schemas/index.html
+++ b/api-guide/schemas/index.html
@@ -57,7 +57,7 @@
If you need a little more control than the get_schema_view() shortcut gives you,
then you can use the SchemaGenerator class directly to auto-generate the
diff --git a/api-guide/serializers/index.html b/api-guide/serializers/index.html
index 3c12159e5..3e56828cb 100644
--- a/api-guide/serializers/index.html
+++ b/api-guide/serializers/index.html
@@ -57,7 +57,7 @@
The credentials method is appropriate for testing APIs that require authentication headers, such as basic authentication, OAuth1a and OAuth2 authentication, and simple token authentication schemes.
Sometimes you may want to bypass authentication, and simple force all requests by the test client to be automatically treated as authenticated.
+
Sometimes you may want to bypass authentication entirely and force all requests by the test client to be automatically treated as authenticated.
This 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.
Add 'rest_framework' to your INSTALLED_APPS setting.
INSTALLED_APPS = (
diff --git a/mkdocs/search_index.json b/mkdocs/search_index.json
index 96d15837b..f48eb68bd 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\nNote\n: This is the documentation for the \nversion 3\n of REST framework. Documentation for \nversion 2\n is also available.\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 \nMachinalis\n\n \nRollbar\n\n \nMicroPyramid\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, \nMachinalis\n, \nRollbar\n, and \nMicroPyramid\n.\n\n\n\n\nRequirements\n\n\nREST framework requires the following:\n\n\n\n\nPython (2.7, 3.2, 3.3, 3.4, 3.5)\n\n\nDjango (1.8, 1.9, 1.10)\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:tomchristie/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', namespace='rest_framework'))\n]\n\n\n\nNote that the URL path can be whatever you want, but you must include \n'rest_framework.urls'\n with the \n'rest_framework'\n namespace. You may leave out the namespace in Django 1.9+, and REST framework will set it for you.\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\nTutorial\n\n\nThe tutorial will walk you through the building blocks that make up REST framework. It'll take a little while to get through, but it'll give you a comprehensive understanding of how everything fits together, and is highly recommended reading.\n\n\n\n\n1 - Serialization\n\n\n2 - Requests \n Responses\n\n\n3 - Class-based views\n\n\n4 - Authentication \n permissions\n\n\n5 - Relationships \n hyperlinked APIs\n\n\n6 - Viewsets \n routers\n\n\n7 - Schemas \n client libraries\n\n\n\n\nThere is a live example API of the finished tutorial API for testing purposes, \navailable here\n.\n\n\nAPI Guide\n\n\nThe API guide is your complete reference manual to all the functionality provided by REST framework.\n\n\n\n\nRequests\n\n\nResponses\n\n\nViews\n\n\nGeneric views\n\n\nViewsets\n\n\nRouters\n\n\nParsers\n\n\nRenderers\n\n\nSerializers\n\n\nSerializer fields\n\n\nSerializer relations\n\n\nValidators\n\n\nAuthentication\n\n\nPermissions\n\n\nThrottling\n\n\nFiltering\n\n\nPagination\n\n\nVersioning\n\n\nContent negotiation\n\n\nMetadata\n\n\nSchemas\n\n\nFormat suffixes\n\n\nReturning URLs\n\n\nExceptions\n\n\nStatus codes\n\n\nTesting\n\n\nSettings\n\n\n\n\nTopics\n\n\nGeneral guides to using REST framework.\n\n\n\n\nDocumenting your API\n\n\nAPI Clients\n\n\nInternationalization\n\n\nAJAX, CSRF \n CORS\n\n\nHTML \n Forms\n\n\nBrowser enhancements\n\n\nThe Browsable API\n\n\nREST, Hypermedia \n HATEOAS\n\n\nThird Party Packages\n\n\nTutorials and Resources\n\n\nContributing to REST framework\n\n\nProject management\n\n\n3.0 Announcement\n\n\n3.1 Announcement\n\n\n3.2 Announcement\n\n\n3.3 Announcement\n\n\n3.4 Announcement\n\n\n3.5 Announcement\n\n\n3.6 Announcement\n\n\nKickstarter Announcement\n\n\nMozilla Grant\n\n\nFunding\n\n\nRelease Notes\n\n\nJobs\n\n\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 (c) 2011-2017, Tom Christie\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\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or\nother materials provided with the distribution.\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\nNote\n: This is the documentation for the \nversion 3\n of REST framework. Documentation for \nversion 2\n is also available.\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 \nMachinalis\n\n \nRollbar\n\n \nMicroPyramid\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, \nMachinalis\n, \nRollbar\n, and \nMicroPyramid\n.\n\n\n\n\nRequirements\n\n\nREST framework requires the following:\n\n\n\n\nPython (2.7, 3.2, 3.3, 3.4, 3.5, 3.6)\n\n\nDjango (1.8, 1.9, 1.10, 1.11)\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', namespace='rest_framework'))\n]\n\n\n\nNote that the URL path can be whatever you want, but you must include \n'rest_framework.urls'\n with the \n'rest_framework'\n namespace. You may leave out the namespace in Django 1.9+, and REST framework will set it for you.\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\nTutorial\n\n\nThe tutorial will walk you through the building blocks that make up REST framework. It'll take a little while to get through, but it'll give you a comprehensive understanding of how everything fits together, and is highly recommended reading.\n\n\n\n\n1 - Serialization\n\n\n2 - Requests \n Responses\n\n\n3 - Class-based views\n\n\n4 - Authentication \n permissions\n\n\n5 - Relationships \n hyperlinked APIs\n\n\n6 - Viewsets \n routers\n\n\n7 - Schemas \n client libraries\n\n\n\n\nThere is a live example API of the finished tutorial API for testing purposes, \navailable here\n.\n\n\nAPI Guide\n\n\nThe API guide is your complete reference manual to all the functionality provided by REST framework.\n\n\n\n\nRequests\n\n\nResponses\n\n\nViews\n\n\nGeneric views\n\n\nViewsets\n\n\nRouters\n\n\nParsers\n\n\nRenderers\n\n\nSerializers\n\n\nSerializer fields\n\n\nSerializer relations\n\n\nValidators\n\n\nAuthentication\n\n\nPermissions\n\n\nThrottling\n\n\nFiltering\n\n\nPagination\n\n\nVersioning\n\n\nContent negotiation\n\n\nMetadata\n\n\nSchemas\n\n\nFormat suffixes\n\n\nReturning URLs\n\n\nExceptions\n\n\nStatus codes\n\n\nTesting\n\n\nSettings\n\n\n\n\nTopics\n\n\nGeneral guides to using REST framework.\n\n\n\n\nDocumenting your API\n\n\nAPI Clients\n\n\nInternationalization\n\n\nAJAX, CSRF \n CORS\n\n\nHTML \n Forms\n\n\nBrowser enhancements\n\n\nThe Browsable API\n\n\nREST, Hypermedia \n HATEOAS\n\n\nThird Party Packages\n\n\nTutorials and Resources\n\n\nContributing to REST framework\n\n\nProject management\n\n\n3.0 Announcement\n\n\n3.1 Announcement\n\n\n3.2 Announcement\n\n\n3.3 Announcement\n\n\n3.4 Announcement\n\n\n3.5 Announcement\n\n\n3.6 Announcement\n\n\nKickstarter Announcement\n\n\nMozilla Grant\n\n\nFunding\n\n\nRelease Notes\n\n\nJobs\n\n\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 (c) 2011-2017, Tom Christie\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\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or\nother materials provided with the distribution.\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.2, 3.3, 3.4, 3.5) Django (1.8, 1.9, 1.10) 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.2, 3.3, 3.4, 3.5, 3.6) Django (1.8, 1.9, 1.10, 1.11) 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:tomchristie/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', namespace='rest_framework'))\n] Note that the URL path can be whatever you want, but you must include 'rest_framework.urls' with the 'rest_framework' namespace. You may leave out the namespace in Django 1.9+, and REST framework will set it for you.",
+ "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', namespace='rest_framework'))\n] Note that the URL path can be whatever you want, but you must include 'rest_framework.urls' with the 'rest_framework' namespace. You may leave out the namespace in Django 1.9+, and REST framework will set it for you.",
"title": "Installation"
},
{
@@ -107,7 +107,7 @@
},
{
"location": "/tutorial/1-serialization/",
- "text": "Tutorial 1: Serialization\n\n\nIntroduction\n\n\nThis tutorial will cover creating a simple pastebin code highlighting Web API. Along the way it will introduce the various components that make up REST framework, and give you a comprehensive understanding of how everything fits together.\n\n\nThe tutorial is fairly in-depth, so you should probably get a cookie and a cup of your favorite brew before getting started. If you just want a quick overview, you should head over to the \nquickstart\n documentation instead.\n\n\n\n\nNote\n: The code for this tutorial is available in the \ntomchristie/rest-framework-tutorial\n repository on GitHub. The completed implementation is also online as a sandbox version for testing, \navailable here\n.\n\n\n\n\nSetting up a new environment\n\n\nBefore we do anything else we'll create a new virtual environment, using \nvirtualenv\n. This will make sure our package configuration is kept nicely isolated from any other projects we're working on.\n\n\nvirtualenv env\nsource env/bin/activate\n\n\n\nNow that we're inside a virtualenv environment, we can install our package requirements.\n\n\npip install django\npip install djangorestframework\npip install pygments # We'll be using this for the code highlighting\n\n\n\nNote:\n To exit the virtualenv environment at any time, just type \ndeactivate\n. For more information see the \nvirtualenv documentation\n.\n\n\nGetting started\n\n\nOkay, we're ready to get coding.\nTo get started, let's create a new project to work with.\n\n\ncd ~\ndjango-admin.py startproject tutorial\ncd tutorial\n\n\n\nOnce that's done we can create an app that we'll use to create a simple Web API.\n\n\npython manage.py startapp snippets\n\n\n\nWe'll need to add our new \nsnippets\n app and the \nrest_framework\n app to \nINSTALLED_APPS\n. Let's edit the \ntutorial/settings.py\n file:\n\n\nINSTALLED_APPS = (\n ...\n 'rest_framework',\n 'snippets.apps.SnippetsConfig',\n)\n\n\n\nPlease note that if you're using Django \n1.9, you need to replace \nsnippets.apps.SnippetsConfig\n with \nsnippets\n.\n\n\nOkay, we're ready to roll.\n\n\nCreating a model to work with\n\n\nFor the purposes of this tutorial we're going to start by creating a simple \nSnippet\n model that is used to store code snippets. Go ahead and edit the \nsnippets/models.py\n file. Note: Good programming practices include comments. Although you will find them in our repository version of this tutorial code, we have omitted them here to focus on the code itself.\n\n\nfrom django.db import models\nfrom pygments.lexers import get_all_lexers\nfrom pygments.styles import get_all_styles\n\nLEXERS = [item for item in get_all_lexers() if item[1]]\nLANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])\nSTYLE_CHOICES = sorted((item, item) for item in get_all_styles())\n\n\nclass Snippet(models.Model):\n created = models.DateTimeField(auto_now_add=True)\n title = models.CharField(max_length=100, blank=True, default='')\n code = models.TextField()\n linenos = models.BooleanField(default=False)\n language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)\n style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)\n\n class Meta:\n ordering = ('created',)\n\n\n\nWe'll also need to create an initial migration for our snippet model, and sync the database for the first time.\n\n\npython manage.py makemigrations snippets\npython manage.py migrate\n\n\n\nCreating a Serializer class\n\n\nThe first thing we need to get started on our Web API is to provide a way of serializing and deserializing the snippet instances into representations such as \njson\n. We can do this by declaring serializers that work very similar to Django's forms. Create a file in the \nsnippets\n directory named \nserializers.py\n and add the following.\n\n\nfrom rest_framework import serializers\nfrom snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES\n\n\nclass SnippetSerializer(serializers.Serializer):\n id = serializers.IntegerField(read_only=True)\n title = serializers.CharField(required=False, allow_blank=True, max_length=100)\n code = serializers.CharField(style={'base_template': 'textarea.html'})\n linenos = serializers.BooleanField(required=False)\n language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')\n style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')\n\n def create(self, validated_data):\n \"\"\"\n Create and return a new `Snippet` instance, given the validated data.\n \"\"\"\n return Snippet.objects.create(**validated_data)\n\n def update(self, instance, validated_data):\n \"\"\"\n Update and return an existing `Snippet` instance, given the validated data.\n \"\"\"\n instance.title = validated_data.get('title', instance.title)\n instance.code = validated_data.get('code', instance.code)\n instance.linenos = validated_data.get('linenos', instance.linenos)\n instance.language = validated_data.get('language', instance.language)\n instance.style = validated_data.get('style', instance.style)\n instance.save()\n return instance\n\n\n\nThe first part of the serializer class defines the fields that get serialized/deserialized. The \ncreate()\n and \nupdate()\n methods define how fully fledged instances are created or modified when calling \nserializer.save()\n\n\nA serializer class is very similar to a Django \nForm\n class, and includes similar validation flags on the various fields, such as \nrequired\n, \nmax_length\n and \ndefault\n.\n\n\nThe field flags can also control how the serializer should be displayed in certain circumstances, such as when rendering to HTML. The \n{'base_template': 'textarea.html'}\n flag above is equivalent to using \nwidget=widgets.Textarea\n on a Django \nForm\n class. This is particularly useful for controlling how the browsable API should be displayed, as we'll see later in the tutorial.\n\n\nWe can actually also save ourselves some time by using the \nModelSerializer\n class, as we'll see later, but for now we'll keep our serializer definition explicit.\n\n\nWorking with Serializers\n\n\nBefore we go any further we'll familiarize ourselves with using our new Serializer class. Let's drop into the Django shell.\n\n\npython manage.py shell\n\n\n\nOkay, once we've got a few imports out of the way, let's create a couple of code snippets to work with.\n\n\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom rest_framework.renderers import JSONRenderer\nfrom rest_framework.parsers import JSONParser\n\nsnippet = Snippet(code='foo = \"bar\"\\n')\nsnippet.save()\n\nsnippet = Snippet(code='print \"hello, world\"\\n')\nsnippet.save()\n\n\n\nWe've now got a few snippet instances to play with. Let's take a look at serializing one of those instances.\n\n\nserializer = SnippetSerializer(snippet)\nserializer.data\n# {'id': 2, 'title': u'', 'code': u'print \"hello, world\"\\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}\n\n\n\nAt this point we've translated the model instance into Python native datatypes. To finalize the serialization process we render the data into \njson\n.\n\n\ncontent = JSONRenderer().render(serializer.data)\ncontent\n# '{\"id\": 2, \"title\": \"\", \"code\": \"print \\\\\"hello, world\\\\\"\\\\n\", \"linenos\": false, \"language\": \"python\", \"style\": \"friendly\"}'\n\n\n\nDeserialization is similar. First we parse a stream into Python native datatypes...\n\n\nfrom django.utils.six import BytesIO\n\nstream = BytesIO(content)\ndata = JSONParser().parse(stream)\n\n\n\n...then we restore those native datatypes into a fully populated object instance.\n\n\nserializer = SnippetSerializer(data=data)\nserializer.is_valid()\n# True\nserializer.validated_data\n# OrderedDict([('title', ''), ('code', 'print \"hello, world\"\\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])\nserializer.save()\n# \nSnippet: Snippet object\n\n\n\n\nNotice how similar the API is to working with forms. The similarity should become even more apparent when we start writing views that use our serializer.\n\n\nWe can also serialize querysets instead of model instances. To do so we simply add a \nmany=True\n flag to the serializer arguments.\n\n\nserializer = SnippetSerializer(Snippet.objects.all(), many=True)\nserializer.data\n# [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = \"bar\"\\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', u''), ('code', u'print \"hello, world\"\\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', u''), ('code', u'print \"hello, world\"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]\n\n\n\nUsing ModelSerializers\n\n\nOur \nSnippetSerializer\n class is replicating a lot of information that's also contained in the \nSnippet\n model. It would be nice if we could keep our code a bit more concise.\n\n\nIn the same way that Django provides both \nForm\n classes and \nModelForm\n classes, REST framework includes both \nSerializer\n classes, and \nModelSerializer\n classes.\n\n\nLet's look at refactoring our serializer using the \nModelSerializer\n class.\nOpen the file \nsnippets/serializers.py\n again, and replace the \nSnippetSerializer\n class with the following.\n\n\nclass SnippetSerializer(serializers.ModelSerializer):\n class Meta:\n model = Snippet\n fields = ('id', 'title', 'code', 'linenos', 'language', 'style')\n\n\n\nOne nice property that serializers have is that you can inspect all the fields in a serializer instance, by printing its representation. Open the Django shell with \npython manage.py shell\n, then try the following:\n\n\nfrom snippets.serializers import SnippetSerializer\nserializer = SnippetSerializer()\nprint(repr(serializer))\n# SnippetSerializer():\n# id = IntegerField(label='ID', read_only=True)\n# title = CharField(allow_blank=True, max_length=100, required=False)\n# code = CharField(style={'base_template': 'textarea.html'})\n# linenos = BooleanField(required=False)\n# language = ChoiceField(choices=[('Clipper', 'FoxPro'), ('Cucumber', 'Gherkin'), ('RobotFramework', 'RobotFramework'), ('abap', 'ABAP'), ('ada', 'Ada')...\n# style = ChoiceField(choices=[('autumn', 'autumn'), ('borland', 'borland'), ('bw', 'bw'), ('colorful', 'colorful')...\n\n\n\nIt's important to remember that \nModelSerializer\n classes don't do anything particularly magical, they are simply a shortcut for creating serializer classes:\n\n\n\n\nAn automatically determined set of fields.\n\n\nSimple default implementations for the \ncreate()\n and \nupdate()\n methods.\n\n\n\n\nWriting regular Django views using our Serializer\n\n\nLet's see how we can write some API views using our new Serializer class.\nFor the moment we won't use any of REST framework's other features, we'll just write the views as regular Django views.\n\n\nEdit the \nsnippets/views.py\n file, and add the following.\n\n\nfrom django.http import HttpResponse, JsonResponse\nfrom django.views.decorators.csrf import csrf_exempt\nfrom rest_framework.renderers import JSONRenderer\nfrom rest_framework.parsers import JSONParser\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\n\n\n\nThe root of our API is going to be a view that supports listing all the existing snippets, or creating a new snippet.\n\n\n@csrf_exempt\ndef snippet_list(request):\n \"\"\"\n List all code snippets, or create a new snippet.\n \"\"\"\n if request.method == 'GET':\n snippets = Snippet.objects.all()\n serializer = SnippetSerializer(snippets, many=True)\n return JsonResponse(serializer.data, safe=False)\n\n elif request.method == 'POST':\n data = JSONParser().parse(request)\n serializer = SnippetSerializer(data=data)\n if serializer.is_valid():\n serializer.save()\n return JsonResponse(serializer.data, status=201)\n return JsonResponse(serializer.errors, status=400)\n\n\n\nNote that because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as \ncsrf_exempt\n. This isn't something that you'd normally want to do, and REST framework views actually use more sensible behavior than this, but it'll do for our purposes right now.\n\n\nWe'll also need a view which corresponds to an individual snippet, and can be used to retrieve, update or delete the snippet.\n\n\n@csrf_exempt\ndef snippet_detail(request, pk):\n \"\"\"\n Retrieve, update or delete a code snippet.\n \"\"\"\n try:\n snippet = Snippet.objects.get(pk=pk)\n except Snippet.DoesNotExist:\n return HttpResponse(status=404)\n\n if request.method == 'GET':\n serializer = SnippetSerializer(snippet)\n return JsonResponse(serializer.data)\n\n elif request.method == 'PUT':\n data = JSONParser().parse(request)\n serializer = SnippetSerializer(snippet, data=data)\n if serializer.is_valid():\n serializer.save()\n return JsonResponse(serializer.data)\n return JsonResponse(serializer.errors, status=400)\n\n elif request.method == 'DELETE':\n snippet.delete()\n return HttpResponse(status=204)\n\n\n\nFinally we need to wire these views up. Create the \nsnippets/urls.py\n file:\n\n\nfrom django.conf.urls import url\nfrom snippets import views\n\nurlpatterns = [\n url(r'^snippets/$', views.snippet_list),\n url(r'^snippets/(?P\npk\n[0-9]+)/$', views.snippet_detail),\n]\n\n\n\nWe also need to wire up the root urlconf, in the \ntutorial/urls.py\n file, to include our snippet app's URLs.\n\n\nfrom django.conf.urls import url, include\n\nurlpatterns = [\n url(r'^', include('snippets.urls')),\n]\n\n\n\nIt's worth noting that there are a couple of edge cases we're not dealing with properly at the moment. If we send malformed \njson\n, or if a request is made with a method that the view doesn't handle, then we'll end up with a 500 \"server error\" response. Still, this'll do for now.\n\n\nTesting our first attempt at a Web API\n\n\nNow we can start up a sample server that serves our snippets.\n\n\nQuit out of the shell...\n\n\nquit()\n\n\n\n...and start up Django's development server.\n\n\npython manage.py runserver\n\nValidating models...\n\n0 errors found\nDjango version 1.8.3, using settings 'tutorial.settings'\nDevelopment server is running at http://127.0.0.1:8000/\nQuit the server with CONTROL-C.\n\n\n\nIn another terminal window, we can test the server.\n\n\nWe can test our API using \ncurl\n or \nhttpie\n. Httpie is a user friendly http client that's written in Python. Let's install that.\n\n\nYou can install httpie using pip:\n\n\npip install httpie\n\n\n\nFinally, we can get a list of all of the snippets:\n\n\nhttp http://127.0.0.1:8000/snippets/\n\nHTTP/1.1 200 OK\n...\n[\n {\n \"id\": 1,\n \"title\": \"\",\n \"code\": \"foo = \\\"bar\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n },\n {\n \"id\": 2,\n \"title\": \"\",\n \"code\": \"print \\\"hello, world\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n }\n]\n\n\n\nOr we can get a particular snippet by referencing its id:\n\n\nhttp http://127.0.0.1:8000/snippets/2/\n\nHTTP/1.1 200 OK\n...\n{\n \"id\": 2,\n \"title\": \"\",\n \"code\": \"print \\\"hello, world\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n}\n\n\n\nSimilarly, you can have the same json displayed by visiting these URLs in a web browser.\n\n\nWhere are we now\n\n\nWe're doing okay so far, we've got a serialization API that feels pretty similar to Django's Forms API, and some regular Django views.\n\n\nOur API views don't do anything particularly special at the moment, beyond serving \njson\n responses, and there are some error handling edge cases we'd still like to clean up, but it's a functioning Web API.\n\n\nWe'll see how we can start to improve things in \npart 2 of the tutorial\n.",
+ "text": "Tutorial 1: Serialization\n\n\nIntroduction\n\n\nThis tutorial will cover creating a simple pastebin code highlighting Web API. Along the way it will introduce the various components that make up REST framework, and give you a comprehensive understanding of how everything fits together.\n\n\nThe tutorial is fairly in-depth, so you should probably get a cookie and a cup of your favorite brew before getting started. If you just want a quick overview, you should head over to the \nquickstart\n documentation instead.\n\n\n\n\nNote\n: The code for this tutorial is available in the \ntomchristie/rest-framework-tutorial\n repository on GitHub. The completed implementation is also online as a sandbox version for testing, \navailable here\n.\n\n\n\n\nSetting up a new environment\n\n\nBefore we do anything else we'll create a new virtual environment, using \nvirtualenv\n. This will make sure our package configuration is kept nicely isolated from any other projects we're working on.\n\n\nvirtualenv env\nsource env/bin/activate\n\n\n\nNow that we're inside a virtualenv environment, we can install our package requirements.\n\n\npip install django\npip install djangorestframework\npip install pygments # We'll be using this for the code highlighting\n\n\n\nNote:\n To exit the virtualenv environment at any time, just type \ndeactivate\n. For more information see the \nvirtualenv documentation\n.\n\n\nGetting started\n\n\nOkay, we're ready to get coding.\nTo get started, let's create a new project to work with.\n\n\ncd ~\ndjango-admin.py startproject tutorial\ncd tutorial\n\n\n\nOnce that's done we can create an app that we'll use to create a simple Web API.\n\n\npython manage.py startapp snippets\n\n\n\nWe'll need to add our new \nsnippets\n app and the \nrest_framework\n app to \nINSTALLED_APPS\n. Let's edit the \ntutorial/settings.py\n file:\n\n\nINSTALLED_APPS = (\n ...\n 'rest_framework',\n 'snippets.apps.SnippetsConfig',\n)\n\n\n\nPlease note that if you're using Django \n1.9, you need to replace \nsnippets.apps.SnippetsConfig\n with \nsnippets\n.\n\n\nOkay, we're ready to roll.\n\n\nCreating a model to work with\n\n\nFor the purposes of this tutorial we're going to start by creating a simple \nSnippet\n model that is used to store code snippets. Go ahead and edit the \nsnippets/models.py\n file. Note: Good programming practices include comments. Although you will find them in our repository version of this tutorial code, we have omitted them here to focus on the code itself.\n\n\nfrom django.db import models\nfrom pygments.lexers import get_all_lexers\nfrom pygments.styles import get_all_styles\n\nLEXERS = [item for item in get_all_lexers() if item[1]]\nLANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])\nSTYLE_CHOICES = sorted((item, item) for item in get_all_styles())\n\n\nclass Snippet(models.Model):\n created = models.DateTimeField(auto_now_add=True)\n title = models.CharField(max_length=100, blank=True, default='')\n code = models.TextField()\n linenos = models.BooleanField(default=False)\n language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)\n style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)\n\n class Meta:\n ordering = ('created',)\n\n\n\nWe'll also need to create an initial migration for our snippet model, and sync the database for the first time.\n\n\npython manage.py makemigrations snippets\npython manage.py migrate\n\n\n\nCreating a Serializer class\n\n\nThe first thing we need to get started on our Web API is to provide a way of serializing and deserializing the snippet instances into representations such as \njson\n. We can do this by declaring serializers that work very similar to Django's forms. Create a file in the \nsnippets\n directory named \nserializers.py\n and add the following.\n\n\nfrom rest_framework import serializers\nfrom snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES\n\n\nclass SnippetSerializer(serializers.Serializer):\n id = serializers.IntegerField(read_only=True)\n title = serializers.CharField(required=False, allow_blank=True, max_length=100)\n code = serializers.CharField(style={'base_template': 'textarea.html'})\n linenos = serializers.BooleanField(required=False)\n language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')\n style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')\n\n def create(self, validated_data):\n \"\"\"\n Create and return a new `Snippet` instance, given the validated data.\n \"\"\"\n return Snippet.objects.create(**validated_data)\n\n def update(self, instance, validated_data):\n \"\"\"\n Update and return an existing `Snippet` instance, given the validated data.\n \"\"\"\n instance.title = validated_data.get('title', instance.title)\n instance.code = validated_data.get('code', instance.code)\n instance.linenos = validated_data.get('linenos', instance.linenos)\n instance.language = validated_data.get('language', instance.language)\n instance.style = validated_data.get('style', instance.style)\n instance.save()\n return instance\n\n\n\nThe first part of the serializer class defines the fields that get serialized/deserialized. The \ncreate()\n and \nupdate()\n methods define how fully fledged instances are created or modified when calling \nserializer.save()\n\n\nA serializer class is very similar to a Django \nForm\n class, and includes similar validation flags on the various fields, such as \nrequired\n, \nmax_length\n and \ndefault\n.\n\n\nThe field flags can also control how the serializer should be displayed in certain circumstances, such as when rendering to HTML. The \n{'base_template': 'textarea.html'}\n flag above is equivalent to using \nwidget=widgets.Textarea\n on a Django \nForm\n class. This is particularly useful for controlling how the browsable API should be displayed, as we'll see later in the tutorial.\n\n\nWe can actually also save ourselves some time by using the \nModelSerializer\n class, as we'll see later, but for now we'll keep our serializer definition explicit.\n\n\nWorking with Serializers\n\n\nBefore we go any further we'll familiarize ourselves with using our new Serializer class. Let's drop into the Django shell.\n\n\npython manage.py shell\n\n\n\nOkay, once we've got a few imports out of the way, let's create a couple of code snippets to work with.\n\n\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom rest_framework.renderers import JSONRenderer\nfrom rest_framework.parsers import JSONParser\n\nsnippet = Snippet(code='foo = \"bar\"\\n')\nsnippet.save()\n\nsnippet = Snippet(code='print \"hello, world\"\\n')\nsnippet.save()\n\n\n\nWe've now got a few snippet instances to play with. Let's take a look at serializing one of those instances.\n\n\nserializer = SnippetSerializer(snippet)\nserializer.data\n# {'id': 2, 'title': u'', 'code': u'print \"hello, world\"\\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}\n\n\n\nAt this point we've translated the model instance into Python native datatypes. To finalize the serialization process we render the data into \njson\n.\n\n\ncontent = JSONRenderer().render(serializer.data)\ncontent\n# '{\"id\": 2, \"title\": \"\", \"code\": \"print \\\\\"hello, world\\\\\"\\\\n\", \"linenos\": false, \"language\": \"python\", \"style\": \"friendly\"}'\n\n\n\nDeserialization is similar. First we parse a stream into Python native datatypes...\n\n\nfrom django.utils.six import BytesIO\n\nstream = BytesIO(content)\ndata = JSONParser().parse(stream)\n\n\n\n...then we restore those native datatypes into a fully populated object instance.\n\n\nserializer = SnippetSerializer(data=data)\nserializer.is_valid()\n# True\nserializer.validated_data\n# OrderedDict([('title', ''), ('code', 'print \"hello, world\"\\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])\nserializer.save()\n# \nSnippet: Snippet object\n\n\n\n\nNotice how similar the API is to working with forms. The similarity should become even more apparent when we start writing views that use our serializer.\n\n\nWe can also serialize querysets instead of model instances. To do so we simply add a \nmany=True\n flag to the serializer arguments.\n\n\nserializer = SnippetSerializer(Snippet.objects.all(), many=True)\nserializer.data\n# [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = \"bar\"\\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', u''), ('code', u'print \"hello, world\"\\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', u''), ('code', u'print \"hello, world\"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]\n\n\n\nUsing ModelSerializers\n\n\nOur \nSnippetSerializer\n class is replicating a lot of information that's also contained in the \nSnippet\n model. It would be nice if we could keep our code a bit more concise.\n\n\nIn the same way that Django provides both \nForm\n classes and \nModelForm\n classes, REST framework includes both \nSerializer\n classes, and \nModelSerializer\n classes.\n\n\nLet's look at refactoring our serializer using the \nModelSerializer\n class.\nOpen the file \nsnippets/serializers.py\n again, and replace the \nSnippetSerializer\n class with the following.\n\n\nclass SnippetSerializer(serializers.ModelSerializer):\n class Meta:\n model = Snippet\n fields = ('id', 'title', 'code', 'linenos', 'language', 'style')\n\n\n\nOne nice property that serializers have is that you can inspect all the fields in a serializer instance, by printing its representation. Open the Django shell with \npython manage.py shell\n, then try the following:\n\n\nfrom snippets.serializers import SnippetSerializer\nserializer = SnippetSerializer()\nprint(repr(serializer))\n# SnippetSerializer():\n# id = IntegerField(label='ID', read_only=True)\n# title = CharField(allow_blank=True, max_length=100, required=False)\n# code = CharField(style={'base_template': 'textarea.html'})\n# linenos = BooleanField(required=False)\n# language = ChoiceField(choices=[('Clipper', 'FoxPro'), ('Cucumber', 'Gherkin'), ('RobotFramework', 'RobotFramework'), ('abap', 'ABAP'), ('ada', 'Ada')...\n# style = ChoiceField(choices=[('autumn', 'autumn'), ('borland', 'borland'), ('bw', 'bw'), ('colorful', 'colorful')...\n\n\n\nIt's important to remember that \nModelSerializer\n classes don't do anything particularly magical, they are simply a shortcut for creating serializer classes:\n\n\n\n\nAn automatically determined set of fields.\n\n\nSimple default implementations for the \ncreate()\n and \nupdate()\n methods.\n\n\n\n\nWriting regular Django views using our Serializer\n\n\nLet's see how we can write some API views using our new Serializer class.\nFor the moment we won't use any of REST framework's other features, we'll just write the views as regular Django views.\n\n\nEdit the \nsnippets/views.py\n file, and add the following.\n\n\nfrom django.http import HttpResponse, JsonResponse\nfrom django.views.decorators.csrf import csrf_exempt\nfrom rest_framework.renderers import JSONRenderer\nfrom rest_framework.parsers import JSONParser\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\n\n\n\nThe root of our API is going to be a view that supports listing all the existing snippets, or creating a new snippet.\n\n\n@csrf_exempt\ndef snippet_list(request):\n \"\"\"\n List all code snippets, or create a new snippet.\n \"\"\"\n if request.method == 'GET':\n snippets = Snippet.objects.all()\n serializer = SnippetSerializer(snippets, many=True)\n return JsonResponse(serializer.data, safe=False)\n\n elif request.method == 'POST':\n data = JSONParser().parse(request)\n serializer = SnippetSerializer(data=data)\n if serializer.is_valid():\n serializer.save()\n return JsonResponse(serializer.data, status=201)\n return JsonResponse(serializer.errors, status=400)\n\n\n\nNote that because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as \ncsrf_exempt\n. This isn't something that you'd normally want to do, and REST framework views actually use more sensible behavior than this, but it'll do for our purposes right now.\n\n\nWe'll also need a view which corresponds to an individual snippet, and can be used to retrieve, update or delete the snippet.\n\n\n@csrf_exempt\ndef snippet_detail(request, pk):\n \"\"\"\n Retrieve, update or delete a code snippet.\n \"\"\"\n try:\n snippet = Snippet.objects.get(pk=pk)\n except Snippet.DoesNotExist:\n return HttpResponse(status=404)\n\n if request.method == 'GET':\n serializer = SnippetSerializer(snippet)\n return JsonResponse(serializer.data)\n\n elif request.method == 'PUT':\n data = JSONParser().parse(request)\n serializer = SnippetSerializer(snippet, data=data)\n if serializer.is_valid():\n serializer.save()\n return JsonResponse(serializer.data)\n return JsonResponse(serializer.errors, status=400)\n\n elif request.method == 'DELETE':\n snippet.delete()\n return HttpResponse(status=204)\n\n\n\nFinally we need to wire these views up. Create the \nsnippets/urls.py\n file:\n\n\nfrom django.conf.urls import url\nfrom snippets import views\n\nurlpatterns = [\n url(r'^snippets/$', views.snippet_list),\n url(r'^snippets/(?P\npk\n[0-9]+)/$', views.snippet_detail),\n]\n\n\n\nWe also need to wire up the root urlconf, in the \ntutorial/urls.py\n file, to include our snippet app's URLs.\n\n\nfrom django.conf.urls import url, include\n\nurlpatterns = [\n url(r'^', include('snippets.urls')),\n]\n\n\n\nIt's worth noting that there are a couple of edge cases we're not dealing with properly at the moment. If we send malformed \njson\n, or if a request is made with a method that the view doesn't handle, then we'll end up with a 500 \"server error\" response. Still, this'll do for now.\n\n\nTesting our first attempt at a Web API\n\n\nNow we can start up a sample server that serves our snippets.\n\n\nQuit out of the shell...\n\n\nquit()\n\n\n\n...and start up Django's development server.\n\n\npython manage.py runserver\n\nValidating models...\n\n0 errors found\nDjango version 1.11, using settings 'tutorial.settings'\nDevelopment server is running at http://127.0.0.1:8000/\nQuit the server with CONTROL-C.\n\n\n\nIn another terminal window, we can test the server.\n\n\nWe can test our API using \ncurl\n or \nhttpie\n. Httpie is a user friendly http client that's written in Python. Let's install that.\n\n\nYou can install httpie using pip:\n\n\npip install httpie\n\n\n\nFinally, we can get a list of all of the snippets:\n\n\nhttp http://127.0.0.1:8000/snippets/\n\nHTTP/1.1 200 OK\n...\n[\n {\n \"id\": 1,\n \"title\": \"\",\n \"code\": \"foo = \\\"bar\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n },\n {\n \"id\": 2,\n \"title\": \"\",\n \"code\": \"print \\\"hello, world\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n }\n]\n\n\n\nOr we can get a particular snippet by referencing its id:\n\n\nhttp http://127.0.0.1:8000/snippets/2/\n\nHTTP/1.1 200 OK\n...\n{\n \"id\": 2,\n \"title\": \"\",\n \"code\": \"print \\\"hello, world\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n}\n\n\n\nSimilarly, you can have the same json displayed by visiting these URLs in a web browser.\n\n\nWhere are we now\n\n\nWe're doing okay so far, we've got a serialization API that feels pretty similar to Django's Forms API, and some regular Django views.\n\n\nOur API views don't do anything particularly special at the moment, beyond serving \njson\n responses, and there are some error handling edge cases we'd still like to clean up, but it's a functioning Web API.\n\n\nWe'll see how we can start to improve things in \npart 2 of the tutorial\n.",
"title": "1 - Serialization"
},
{
@@ -157,7 +157,7 @@
},
{
"location": "/tutorial/1-serialization/#testing-our-first-attempt-at-a-web-api",
- "text": "Now we can start up a sample server that serves our snippets. Quit out of the shell... quit() ...and start up Django's development server. python manage.py runserver\n\nValidating models...\n\n0 errors found\nDjango version 1.8.3, using settings 'tutorial.settings'\nDevelopment server is running at http://127.0.0.1:8000/\nQuit the server with CONTROL-C. In another terminal window, we can test the server. We can test our API using curl or httpie . Httpie is a user friendly http client that's written in Python. Let's install that. You can install httpie using pip: pip install httpie Finally, we can get a list of all of the snippets: http http://127.0.0.1:8000/snippets/\n\nHTTP/1.1 200 OK\n...\n[\n {\n \"id\": 1,\n \"title\": \"\",\n \"code\": \"foo = \\\"bar\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n },\n {\n \"id\": 2,\n \"title\": \"\",\n \"code\": \"print \\\"hello, world\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n }\n] Or we can get a particular snippet by referencing its id: http http://127.0.0.1:8000/snippets/2/\n\nHTTP/1.1 200 OK\n...\n{\n \"id\": 2,\n \"title\": \"\",\n \"code\": \"print \\\"hello, world\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n} Similarly, you can have the same json displayed by visiting these URLs in a web browser.",
+ "text": "Now we can start up a sample server that serves our snippets. Quit out of the shell... quit() ...and start up Django's development server. python manage.py runserver\n\nValidating models...\n\n0 errors found\nDjango version 1.11, using settings 'tutorial.settings'\nDevelopment server is running at http://127.0.0.1:8000/\nQuit the server with CONTROL-C. In another terminal window, we can test the server. We can test our API using curl or httpie . Httpie is a user friendly http client that's written in Python. Let's install that. You can install httpie using pip: pip install httpie Finally, we can get a list of all of the snippets: http http://127.0.0.1:8000/snippets/\n\nHTTP/1.1 200 OK\n...\n[\n {\n \"id\": 1,\n \"title\": \"\",\n \"code\": \"foo = \\\"bar\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n },\n {\n \"id\": 2,\n \"title\": \"\",\n \"code\": \"print \\\"hello, world\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n }\n] Or we can get a particular snippet by referencing its id: http http://127.0.0.1:8000/snippets/2/\n\nHTTP/1.1 200 OK\n...\n{\n \"id\": 2,\n \"title\": \"\",\n \"code\": \"print \\\"hello, world\\\"\\n\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n} Similarly, you can have the same json displayed by visiting these URLs in a web browser.",
"title": "Testing our first attempt at a Web API"
},
{
@@ -372,7 +372,7 @@
},
{
"location": "/tutorial/7-schemas-and-client-libraries/",
- "text": "Tutorial 7: Schemas \n client libraries\n\n\nA schema is a machine-readable document that describes the available API\nendpoints, their URLS, and what operations they support.\n\n\nSchemas can be a useful tool for auto-generated documentation, and can also\nbe used to drive dynamic client libraries that can interact with the API.\n\n\nCore API\n\n\nIn order to provide schema support REST framework uses \nCore API\n.\n\n\nCore API is a document specification for describing APIs. It is used to provide\nan internal representation format of the available endpoints and possible\ninteractions that an API exposes. It can either be used server-side, or\nclient-side.\n\n\nWhen used server-side, Core API allows an API to support rendering to a wide\nrange of schema or hypermedia formats.\n\n\nWhen used client-side, Core API allows for dynamically driven client libraries\nthat can interact with any API that exposes a supported schema or hypermedia\nformat.\n\n\nAdding a schema\n\n\nREST framework supports either explicitly defined schema views, or\nautomatically generated schemas. Since we're using viewsets and routers,\nwe can simply use the automatic schema generation.\n\n\nYou'll need to install the \ncoreapi\n python package in order to include an\nAPI schema.\n\n\n$ pip install coreapi\n\n\n\nWe can now include a schema for our API, by including an autogenerated schema\nview in our URL configuration.\n\n\nfrom rest_framework.schemas import get_schema_view\n\nschema_view = get_schema_view(title='Pastebin API')\n\nurlpatterns = [\n\n\n\nurl(r'^schema/$', schema_view),\n ...\n ]\n\n\nIf you visit the API root endpoint in a browser you should now see \ncorejson\n\nrepresentation become available as an option.\n\n\n\n\nWe can also request the schema from the command line, by specifying the desired\ncontent type in the \nAccept\n header.\n\n\n$ http http://127.0.0.1:8000/schema/ Accept:application/coreapi+json\nHTTP/1.0 200 OK\nAllow: GET, HEAD, OPTIONS\nContent-Type: application/coreapi+json\n\n{\n \"_meta\": {\n \"title\": \"Pastebin API\"\n },\n \"_type\": \"document\",\n ...\n\n\n\nThe default output style is to use the \nCore JSON\n encoding.\n\n\nOther schema formats, such as \nOpen API\n (formerly Swagger) are\nalso supported.\n\n\nUsing a command line client\n\n\nNow that our API is exposing a schema endpoint, we can use a dynamic client\nlibrary to interact with the API. To demonstrate this, let's use the\nCore API command line client.\n\n\nThe command line client is available as the \ncoreapi-cli\n package:\n\n\n$ pip install coreapi-cli\n\n\n\nNow check that it is available on the command line...\n\n\n$ coreapi\nUsage: coreapi [OPTIONS] COMMAND [ARGS]...\n\n Command line client for interacting with CoreAPI services.\n\n Visit http://www.coreapi.org for more information.\n\nOptions:\n --version Display the package version number.\n --help Show this message and exit.\n\nCommands:\n...\n\n\n\nFirst we'll load the API schema using the command line client.\n\n\n$ coreapi get http://127.0.0.1:8000/schema/\n\nPastebin API \"http://127.0.0.1:8000/schema/\"\n\n snippets: {\n highlight(id)\n list()\n read(id)\n }\n users: {\n list()\n read(id)\n }\n\n\n\nWe haven't authenticated yet, so right now we're only able to see the read only\nendpoints, in line with how we've set up the permissions on the API.\n\n\nLet's try listing the existing snippets, using the command line client:\n\n\n$ coreapi action snippets list\n[\n {\n \"url\": \"http://127.0.0.1:8000/snippets/1/\",\n \"id\": 1,\n \"highlight\": \"http://127.0.0.1:8000/snippets/1/highlight/\",\n \"owner\": \"lucy\",\n \"title\": \"Example\",\n \"code\": \"print('hello, world!')\",\n \"linenos\": true,\n \"language\": \"python\",\n \"style\": \"friendly\"\n },\n ...\n\n\n\nSome of the API endpoints require named parameters. For example, to get back\nthe highlight HTML for a particular snippet we need to provide an id.\n\n\n$ coreapi action snippets highlight --param id=1\n\n!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\"\n\n\n\nhtml\n\n\nhead\n\n \ntitle\nExample\n/title\n\n ...\n\n\n\nAuthenticating our client\n\n\nIf we want to be able to create, edit and delete snippets, we'll need to\nauthenticate as a valid user. In this case we'll just use basic auth.\n\n\nMake sure to replace the \nusername\n and \npassword\n below with your\nactual username and password.\n\n\n$ coreapi credentials add 127.0.0.1 \nusername\n:\npassword\n --auth basic\nAdded credentials\n127.0.0.1 \"Basic \n...\n\"\n\n\n\nNow if we fetch the schema again, we should be able to see the full\nset of available interactions.\n\n\n$ coreapi reload\nPastebin API \"http://127.0.0.1:8000/schema/\"\n\n snippets: {\n create(code, [title], [linenos], [language], [style])\n delete(id)\n highlight(id)\n list()\n partial_update(id, [title], [code], [linenos], [language], [style])\n read(id)\n update(id, code, [title], [linenos], [language], [style])\n }\n users: {\n list()\n read(id)\n }\n\n\n\nWe're now able to interact with these endpoints. For example, to create a new\nsnippet:\n\n\n$ coreapi action snippets create --param title=\"Example\" --param code=\"print('hello, world')\"\n{\n \"url\": \"http://127.0.0.1:8000/snippets/7/\",\n \"id\": 7,\n \"highlight\": \"http://127.0.0.1:8000/snippets/7/highlight/\",\n \"owner\": \"lucy\",\n \"title\": \"Example\",\n \"code\": \"print('hello, world')\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n}\n\n\n\nAnd to delete a snippet:\n\n\n$ coreapi action snippets delete --param id=7\n\n\n\nAs well as the command line client, developers can also interact with your\nAPI using client libraries. The Python client library is the first of these\nto be available, and a Javascript client library is planned to be released\nsoon.\n\n\nFor more details on customizing schema generation and using Core API\nclient libraries you'll need to refer to the full documentation.\n\n\nReviewing our work\n\n\nWith an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browsable, includes a schema-driven client library, and comes complete with authentication, per-object permissions, and multiple renderer formats.\n\n\nWe've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views.\n\n\nYou can review the final \ntutorial code\n on GitHub, or try out a live example in \nthe sandbox\n.\n\n\nOnwards and upwards\n\n\nWe've reached the end of our tutorial. If you want to get more involved in the REST framework project, here are a few places you can start:\n\n\n\n\nContribute on \nGitHub\n by reviewing and submitting issues, and making pull requests.\n\n\nJoin the \nREST framework discussion group\n, and help build the community.\n\n\nFollow \nthe author\n on Twitter and say hi.\n\n\n\n\nNow go build awesome things.",
+ "text": "Tutorial 7: Schemas \n client libraries\n\n\nA schema is a machine-readable document that describes the available API\nendpoints, their URLS, and what operations they support.\n\n\nSchemas can be a useful tool for auto-generated documentation, and can also\nbe used to drive dynamic client libraries that can interact with the API.\n\n\nCore API\n\n\nIn order to provide schema support REST framework uses \nCore API\n.\n\n\nCore API is a document specification for describing APIs. It is used to provide\nan internal representation format of the available endpoints and possible\ninteractions that an API exposes. It can either be used server-side, or\nclient-side.\n\n\nWhen used server-side, Core API allows an API to support rendering to a wide\nrange of schema or hypermedia formats.\n\n\nWhen used client-side, Core API allows for dynamically driven client libraries\nthat can interact with any API that exposes a supported schema or hypermedia\nformat.\n\n\nAdding a schema\n\n\nREST framework supports either explicitly defined schema views, or\nautomatically generated schemas. Since we're using viewsets and routers,\nwe can simply use the automatic schema generation.\n\n\nYou'll need to install the \ncoreapi\n python package in order to include an\nAPI schema.\n\n\n$ pip install coreapi\n\n\n\nWe can now include a schema for our API, by including an autogenerated schema\nview in our URL configuration.\n\n\n from rest_framework.schemas import get_schema_view\n\n schema_view = get_schema_view(title='Pastebin API')\n\n urlpatterns = [\n \u00a0 \u00a0url(r'^schema/$', schema_view),\n ...\n ]\n\n\n\n\nIf you visit the API root endpoint in a browser you should now see \ncorejson\n\nrepresentation become available as an option.\n\n\n\n\nWe can also request the schema from the command line, by specifying the desired\ncontent type in the \nAccept\n header.\n\n\n$ http http://127.0.0.1:8000/schema/ Accept:application/coreapi+json\nHTTP/1.0 200 OK\nAllow: GET, HEAD, OPTIONS\nContent-Type: application/coreapi+json\n\n{\n \"_meta\": {\n \"title\": \"Pastebin API\"\n },\n \"_type\": \"document\",\n ...\n\n\n\nThe default output style is to use the \nCore JSON\n encoding.\n\n\nOther schema formats, such as \nOpen API\n (formerly Swagger) are\nalso supported.\n\n\nUsing a command line client\n\n\nNow that our API is exposing a schema endpoint, we can use a dynamic client\nlibrary to interact with the API. To demonstrate this, let's use the\nCore API command line client.\n\n\nThe command line client is available as the \ncoreapi-cli\n package:\n\n\n$ pip install coreapi-cli\n\n\n\nNow check that it is available on the command line...\n\n\n$ coreapi\nUsage: coreapi [OPTIONS] COMMAND [ARGS]...\n\n Command line client for interacting with CoreAPI services.\n\n Visit http://www.coreapi.org for more information.\n\nOptions:\n --version Display the package version number.\n --help Show this message and exit.\n\nCommands:\n...\n\n\n\nFirst we'll load the API schema using the command line client.\n\n\n$ coreapi get http://127.0.0.1:8000/schema/\n\nPastebin API \"http://127.0.0.1:8000/schema/\"\n\n snippets: {\n highlight(id)\n list()\n read(id)\n }\n users: {\n list()\n read(id)\n }\n\n\n\nWe haven't authenticated yet, so right now we're only able to see the read only\nendpoints, in line with how we've set up the permissions on the API.\n\n\nLet's try listing the existing snippets, using the command line client:\n\n\n$ coreapi action snippets list\n[\n {\n \"url\": \"http://127.0.0.1:8000/snippets/1/\",\n \"id\": 1,\n \"highlight\": \"http://127.0.0.1:8000/snippets/1/highlight/\",\n \"owner\": \"lucy\",\n \"title\": \"Example\",\n \"code\": \"print('hello, world!')\",\n \"linenos\": true,\n \"language\": \"python\",\n \"style\": \"friendly\"\n },\n ...\n\n\n\nSome of the API endpoints require named parameters. For example, to get back\nthe highlight HTML for a particular snippet we need to provide an id.\n\n\n$ coreapi action snippets highlight --param id=1\n\n!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\"\n\n\n\nhtml\n\n\nhead\n\n \ntitle\nExample\n/title\n\n ...\n\n\n\nAuthenticating our client\n\n\nIf we want to be able to create, edit and delete snippets, we'll need to\nauthenticate as a valid user. In this case we'll just use basic auth.\n\n\nMake sure to replace the \nusername\n and \npassword\n below with your\nactual username and password.\n\n\n$ coreapi credentials add 127.0.0.1 \nusername\n:\npassword\n --auth basic\nAdded credentials\n127.0.0.1 \"Basic \n...\n\"\n\n\n\nNow if we fetch the schema again, we should be able to see the full\nset of available interactions.\n\n\n$ coreapi reload\nPastebin API \"http://127.0.0.1:8000/schema/\"\n\n snippets: {\n create(code, [title], [linenos], [language], [style])\n delete(id)\n highlight(id)\n list()\n partial_update(id, [title], [code], [linenos], [language], [style])\n read(id)\n update(id, code, [title], [linenos], [language], [style])\n }\n users: {\n list()\n read(id)\n }\n\n\n\nWe're now able to interact with these endpoints. For example, to create a new\nsnippet:\n\n\n$ coreapi action snippets create --param title=\"Example\" --param code=\"print('hello, world')\"\n{\n \"url\": \"http://127.0.0.1:8000/snippets/7/\",\n \"id\": 7,\n \"highlight\": \"http://127.0.0.1:8000/snippets/7/highlight/\",\n \"owner\": \"lucy\",\n \"title\": \"Example\",\n \"code\": \"print('hello, world')\",\n \"linenos\": false,\n \"language\": \"python\",\n \"style\": \"friendly\"\n}\n\n\n\nAnd to delete a snippet:\n\n\n$ coreapi action snippets delete --param id=7\n\n\n\nAs well as the command line client, developers can also interact with your\nAPI using client libraries. The Python client library is the first of these\nto be available, and a Javascript client library is planned to be released\nsoon.\n\n\nFor more details on customizing schema generation and using Core API\nclient libraries you'll need to refer to the full documentation.\n\n\nReviewing our work\n\n\nWith an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browsable, includes a schema-driven client library, and comes complete with authentication, per-object permissions, and multiple renderer formats.\n\n\nWe've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views.\n\n\nYou can review the final \ntutorial code\n on GitHub, or try out a live example in \nthe sandbox\n.\n\n\nOnwards and upwards\n\n\nWe've reached the end of our tutorial. If you want to get more involved in the REST framework project, here are a few places you can start:\n\n\n\n\nContribute on \nGitHub\n by reviewing and submitting issues, and making pull requests.\n\n\nJoin the \nREST framework discussion group\n, and help build the community.\n\n\nFollow \nthe author\n on Twitter and say hi.\n\n\n\n\nNow go build awesome things.",
"title": "7 - Schemas and client libraries"
},
{
@@ -387,7 +387,7 @@
},
{
"location": "/tutorial/7-schemas-and-client-libraries/#adding-a-schema",
- "text": "REST framework supports either explicitly defined schema views, or\nautomatically generated schemas. Since we're using viewsets and routers,\nwe can simply use the automatic schema generation. You'll need to install the coreapi python package in order to include an\nAPI schema. $ pip install coreapi We can now include a schema for our API, by including an autogenerated schema\nview in our URL configuration. from rest_framework.schemas import get_schema_view\n\nschema_view = get_schema_view(title='Pastebin API')\n\nurlpatterns = [ url(r'^schema/$', schema_view),\n ...\n ] If you visit the API root endpoint in a browser you should now see corejson \nrepresentation become available as an option. We can also request the schema from the command line, by specifying the desired\ncontent type in the Accept header. $ http http://127.0.0.1:8000/schema/ Accept:application/coreapi+json\nHTTP/1.0 200 OK\nAllow: GET, HEAD, OPTIONS\nContent-Type: application/coreapi+json\n\n{\n \"_meta\": {\n \"title\": \"Pastebin API\"\n },\n \"_type\": \"document\",\n ... The default output style is to use the Core JSON encoding. Other schema formats, such as Open API (formerly Swagger) are\nalso supported.",
+ "text": "REST framework supports either explicitly defined schema views, or\nautomatically generated schemas. Since we're using viewsets and routers,\nwe can simply use the automatic schema generation. You'll need to install the coreapi python package in order to include an\nAPI schema. $ pip install coreapi We can now include a schema for our API, by including an autogenerated schema\nview in our URL configuration. from rest_framework.schemas import get_schema_view\n\n schema_view = get_schema_view(title='Pastebin API')\n\n urlpatterns = [\n \u00a0 \u00a0url(r'^schema/$', schema_view),\n ...\n ] If you visit the API root endpoint in a browser you should now see corejson \nrepresentation become available as an option. We can also request the schema from the command line, by specifying the desired\ncontent type in the Accept header. $ http http://127.0.0.1:8000/schema/ Accept:application/coreapi+json\nHTTP/1.0 200 OK\nAllow: GET, HEAD, OPTIONS\nContent-Type: application/coreapi+json\n\n{\n \"_meta\": {\n \"title\": \"Pastebin API\"\n },\n \"_type\": \"document\",\n ... The default output style is to use the Core JSON encoding. Other schema formats, such as Open API (formerly Swagger) are\nalso supported.",
"title": "Adding a schema"
},
{
@@ -952,7 +952,7 @@
},
{
"location": "/api-guide/routers/",
- "text": "Routers\n\n\n\n\nResource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index... a resourceful route declares them in a single line of code.\n\n\n \nRuby on Rails Documentation\n\n\n\n\nSome Web frameworks such as Rails provide functionality for automatically determining how the URLs for an application should be mapped to the logic that deals with handling incoming requests.\n\n\nREST framework adds support for automatic URL routing to Django, and provides you with a simple, quick and consistent way of wiring your view logic to a set of URLs.\n\n\nUsage\n\n\nHere's an example of a simple URL conf, that uses \nSimpleRouter\n.\n\n\nfrom rest_framework import routers\n\nrouter = routers.SimpleRouter()\nrouter.register(r'users', UserViewSet)\nrouter.register(r'accounts', AccountViewSet)\nurlpatterns = router.urls\n\n\n\nThere are two mandatory arguments to the \nregister()\n method:\n\n\n\n\nprefix\n - The URL prefix to use for this set of routes.\n\n\nviewset\n - The viewset class.\n\n\n\n\nOptionally, you may also specify an additional argument:\n\n\n\n\nbase_name\n - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the \nqueryset\n attribute of the viewset, if it has one. Note that if the viewset does not include a \nqueryset\n attribute then you must set \nbase_name\n when registering the viewset.\n\n\n\n\nThe example above would generate the following URL patterns:\n\n\n\n\nURL pattern: \n^users/$\n Name: \n'user-list'\n\n\nURL pattern: \n^users/{pk}/$\n Name: \n'user-detail'\n\n\nURL pattern: \n^accounts/$\n Name: \n'account-list'\n\n\nURL pattern: \n^accounts/{pk}/$\n Name: \n'account-detail'\n\n\n\n\n\n\nNote\n: The \nbase_name\n argument is used to specify the initial part of the view name pattern. In the example above, that's the \nuser\n or \naccount\n part.\n\n\nTypically you won't \nneed\n to specify the \nbase_name\n argument, but if you have a viewset where you've defined a custom \nget_queryset\n method, then the viewset may not have a \n.queryset\n attribute set. If you try to register that viewset you'll see an error like this:\n\n\n'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.\n\n\n\nThis means you'll need to explicitly set the \nbase_name\n argument when registering the viewset, as it could not be automatically determined from the model name.\n\n\n\n\nUsing \ninclude\n with routers\n\n\nThe \n.urls\n attribute on a router instance is simply a standard list of URL patterns. There are a number of different styles for how you can include these URLs.\n\n\nFor example, you can append \nrouter.urls\n to a list of existing views\u2026\n\n\nrouter = routers.SimpleRouter()\nrouter.register(r'users', UserViewSet)\nrouter.register(r'accounts', AccountViewSet)\n\nurlpatterns = [\n url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),\n]\n\nurlpatterns += router.urls\n\n\n\nAlternatively you can use Django's \ninclude\n function, like so\u2026\n\n\nurlpatterns = [\n url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),\n url(r'^', include(router.urls)),\n]\n\n\n\nRouter URL patterns can also be namespaces.\n\n\nurlpatterns = [\n url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),\n url(r'^api/', include(router.urls, namespace='api')),\n]\n\n\n\nIf using namespacing with hyperlinked serializers you'll also need to ensure that any \nview_name\n parameters on the serializers correctly reflect the namespace. In the example above you'd need to include a parameter such as \nview_name='api:user-detail'\n for serializer fields hyperlinked to the user detail view.\n\n\nExtra link and actions\n\n\nAny methods on the viewset decorated with \n@detail_route\n or \n@list_route\n will also be routed.\nFor example, given a method like this on the \nUserViewSet\n class:\n\n\nfrom myapp.permissions import IsAdminOrIsSelf\nfrom rest_framework.decorators import detail_route\n\nclass UserViewSet(ModelViewSet):\n ...\n\n @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])\n def set_password(self, request, pk=None):\n ...\n\n\n\nThe following URL pattern would additionally be generated:\n\n\n\n\nURL pattern: \n^users/{pk}/set_password/$\n Name: \n'user-set-password'\n\n\n\n\nIf you do not want to use the default URL generated for your custom action, you can instead use the url_path parameter to customize it.\n\n\nFor example, if you want to change the URL for our custom action to \n^users/{pk}/change-password/$\n, you could write:\n\n\nfrom myapp.permissions import IsAdminOrIsSelf\nfrom rest_framework.decorators import detail_route\n\nclass UserViewSet(ModelViewSet):\n ...\n\n @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='change-password')\n def set_password(self, request, pk=None):\n ...\n\n\n\nThe above example would now generate the following URL pattern:\n\n\n\n\nURL pattern: \n^users/{pk}/change-password/$\n Name: \n'user-change-password'\n\n\n\n\nIn the case you do not want to use the default name generated for your custom action, you can use the url_name parameter to customize it.\n\n\nFor example, if you want to change the name of our custom action to \n'user-change-password'\n, you could write:\n\n\nfrom myapp.permissions import IsAdminOrIsSelf\nfrom rest_framework.decorators import detail_route\n\nclass UserViewSet(ModelViewSet):\n ...\n\n @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_name='change-password')\n def set_password(self, request, pk=None):\n ...\n\n\n\nThe above example would now generate the following URL pattern:\n\n\n\n\nURL pattern: \n^users/{pk}/set_password/$\n Name: \n'user-change-password'\n\n\n\n\nYou can also use url_path and url_name parameters together to obtain extra control on URL generation for custom views.\n\n\nFor more information see the viewset documentation on \nmarking extra actions for routing\n.\n\n\nAPI Guide\n\n\nSimpleRouter\n\n\nThis router includes routes for the standard set of \nlist\n, \ncreate\n, \nretrieve\n, \nupdate\n, \npartial_update\n and \ndestroy\n actions. The viewset can also mark additional methods to be routed, using the \n@detail_route\n or \n@list_route\n decorators.\n\n\n\n \nURL Style\nHTTP Method\nAction\nURL Name\n\n \n{prefix}/\nGET\nlist\n{basename}-list\n\n \nPOST\ncreate\n\n \n{prefix}/{methodname}/\nGET, or as specified by `methods` argument\n`@list_route` decorated method\n{basename}-{methodname}\n\n \n{prefix}/{lookup}/\nGET\nretrieve\n{basename}-detail\n\n \nPUT\nupdate\n\n \nPATCH\npartial_update\n\n \nDELETE\ndestroy\n\n \n{prefix}/{lookup}/{methodname}/\nGET, or as specified by `methods` argument\n`@detail_route` decorated method\n{basename}-{methodname}\n\n\n\n\n\nBy default the URLs created by \nSimpleRouter\n are appended with a trailing slash.\nThis behavior can be modified by setting the \ntrailing_slash\n argument to \nFalse\n when instantiating the router. For example:\n\n\nrouter = SimpleRouter(trailing_slash=False)\n\n\n\nTrailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.\n\n\nThe router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the \nlookup_value_regex\n attribute on the viewset. For example, you can limit the lookup to valid UUIDs:\n\n\nclass MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):\n lookup_field = 'my_model_id'\n lookup_value_regex = '[0-9a-f]{32}'\n\n\n\nDefaultRouter\n\n\nThis router is similar to \nSimpleRouter\n as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional \n.json\n style format suffixes.\n\n\n\n \nURL Style\nHTTP Method\nAction\nURL Name\n\n \n[.format]\nGET\nautomatically generated root view\napi-root\n\n \n{prefix}/[.format]\nGET\nlist\n{basename}-list\n\n \nPOST\ncreate\n\n \n{prefix}/{methodname}/[.format]\nGET, or as specified by `methods` argument\n`@list_route` decorated method\n{basename}-{methodname}\n\n \n{prefix}/{lookup}/[.format]\nGET\nretrieve\n{basename}-detail\n\n \nPUT\nupdate\n\n \nPATCH\npartial_update\n\n \nDELETE\ndestroy\n\n \n{prefix}/{lookup}/{methodname}/[.format]\nGET, or as specified by `methods` argument\n`@detail_route` decorated method\n{basename}-{methodname}\n\n\n\n\n\nAs with \nSimpleRouter\n the trailing slashes on the URL routes can be removed by setting the \ntrailing_slash\n argument to \nFalse\n when instantiating the router.\n\n\nrouter = DefaultRouter(trailing_slash=False)\n\n\n\nCustom Routers\n\n\nImplementing a custom router isn't something you'd need to do very often, but it can be useful if you have specific requirements about how the your URLs for your API are structured. Doing so allows you to encapsulate the URL structure in a reusable way that ensures you don't have to write your URL patterns explicitly for each new view.\n\n\nThe simplest way to implement a custom router is to subclass one of the existing router classes. The \n.routes\n attribute is used to template the URL patterns that will be mapped to each viewset. The \n.routes\n attribute is a list of \nRoute\n named tuples.\n\n\nThe arguments to the \nRoute\n named tuple are:\n\n\nurl\n: A string representing the URL to be routed. May include the following format strings:\n\n\n\n\n{prefix}\n - The URL prefix to use for this set of routes.\n\n\n{lookup}\n - The lookup field used to match against a single instance.\n\n\n{trailing_slash}\n - Either a '/' or an empty string, depending on the \ntrailing_slash\n argument.\n\n\n\n\nmapping\n: A mapping of HTTP method names to the view methods\n\n\nname\n: The name of the URL as used in \nreverse\n calls. May include the following format string:\n\n\n\n\n{basename}\n - The base to use for the URL names that are created.\n\n\n\n\ninitkwargs\n: A dictionary of any additional arguments that should be passed when instantiating the view. Note that the \nsuffix\n argument is reserved for identifying the viewset type, used when generating the view name and breadcrumb links.\n\n\nCustomizing dynamic routes\n\n\nYou can also customize how the \n@list_route\n and \n@detail_route\n decorators are routed.\nTo route either or both of these decorators, include a \nDynamicListRoute\n and/or \nDynamicDetailRoute\n named tuple in the \n.routes\n list.\n\n\nThe arguments to \nDynamicListRoute\n and \nDynamicDetailRoute\n are:\n\n\nurl\n: A string representing the URL to be routed. May include the same format strings as \nRoute\n, and additionally accepts the \n{methodname}\n and \n{methodnamehyphen}\n format strings.\n\n\nname\n: The name of the URL as used in \nreverse\n calls. May include the following format strings: \n{basename}\n, \n{methodname}\n and \n{methodnamehyphen}\n.\n\n\ninitkwargs\n: A dictionary of any additional arguments that should be passed when instantiating the view.\n\n\nExample\n\n\nThe following example will only route to the \nlist\n and \nretrieve\n actions, and does not use the trailing slash convention.\n\n\nfrom rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter\n\nclass CustomReadOnlyRouter(SimpleRouter):\n \"\"\"\n A router for read-only APIs, which doesn't use trailing slashes.\n \"\"\"\n routes = [\n Route(\n url=r'^{prefix}$',\n mapping={'get': 'list'},\n name='{basename}-list',\n initkwargs={'suffix': 'List'}\n ),\n Route(\n url=r'^{prefix}/{lookup}$',\n mapping={'get': 'retrieve'},\n name='{basename}-detail',\n initkwargs={'suffix': 'Detail'}\n ),\n DynamicDetailRoute(\n url=r'^{prefix}/{lookup}/{methodnamehyphen}$',\n name='{basename}-{methodnamehyphen}',\n initkwargs={}\n )\n ]\n\n\n\nLet's take a look at the routes our \nCustomReadOnlyRouter\n would generate for a simple viewset.\n\n\nviews.py\n:\n\n\nclass UserViewSet(viewsets.ReadOnlyModelViewSet):\n \"\"\"\n A viewset that provides the standard actions\n \"\"\"\n queryset = User.objects.all()\n serializer_class = UserSerializer\n lookup_field = 'username'\n\n @detail_route()\n def group_names(self, request):\n \"\"\"\n Returns a list of all the group names that the given\n user belongs to.\n \"\"\"\n user = self.get_object()\n groups = user.groups.all()\n return Response([group.name for group in groups])\n\n\n\nurls.py\n:\n\n\nrouter = CustomReadOnlyRouter()\nrouter.register('users', UserViewSet)\nurlpatterns = router.urls\n\n\n\nThe following mappings would be generated...\n\n\n\n \nURL\nHTTP Method\nAction\nURL Name\n\n \n/users\nGET\nlist\nuser-list\n\n \n/users/{username}\nGET\nretrieve\nuser-detail\n\n \n/users/{username}/group-names\nGET\ngroup_names\nuser-group-names\n\n\n\n\n\nFor another example of setting the \n.routes\n attribute, see the source code for the \nSimpleRouter\n class.\n\n\nAdvanced custom routers\n\n\nIf you want to provide totally custom behavior, you can override \nBaseRouter\n and override the \nget_urls(self)\n method. The method should inspect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the \nself.registry\n attribute.\n\n\nYou may also want to override the \nget_default_base_name(self, viewset)\n method, or else always explicitly set the \nbase_name\n argument when registering your viewsets with the router.\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\nModelRouter (wq.db.rest)\n\n\nThe \nwq.db package\n provides an advanced \nModelRouter\n class (and singleton instance) that extends \nDefaultRouter\n with a \nregister_model()\n API. Much like Django's \nadmin.site.register\n, the only required argument to \nrest.router.register_model\n is a model class. Reasonable defaults for a url prefix, serializer, and viewset will be inferred from the model and global configuration.\n\n\nfrom wq.db import rest\nfrom myapp.models import MyModel\n\nrest.router.register_model(MyModel)\n\n\n\nDRF-extensions\n\n\nThe \nDRF-extensions\n package\n provides \nrouters\n for creating \nnested viewsets\n, \ncollection level controllers\n with \ncustomizable endpoint names\n.",
+ "text": "Routers\n\n\n\n\nResource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index... a resourceful route declares them in a single line of code.\n\n\n \nRuby on Rails Documentation\n\n\n\n\nSome Web frameworks such as Rails provide functionality for automatically determining how the URLs for an application should be mapped to the logic that deals with handling incoming requests.\n\n\nREST framework adds support for automatic URL routing to Django, and provides you with a simple, quick and consistent way of wiring your view logic to a set of URLs.\n\n\nUsage\n\n\nHere's an example of a simple URL conf, that uses \nSimpleRouter\n.\n\n\nfrom rest_framework import routers\n\nrouter = routers.SimpleRouter()\nrouter.register(r'users', UserViewSet)\nrouter.register(r'accounts', AccountViewSet)\nurlpatterns = router.urls\n\n\n\nThere are two mandatory arguments to the \nregister()\n method:\n\n\n\n\nprefix\n - The URL prefix to use for this set of routes.\n\n\nviewset\n - The viewset class.\n\n\n\n\nOptionally, you may also specify an additional argument:\n\n\n\n\nbase_name\n - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the \nqueryset\n attribute of the viewset, if it has one. Note that if the viewset does not include a \nqueryset\n attribute then you must set \nbase_name\n when registering the viewset.\n\n\n\n\nThe example above would generate the following URL patterns:\n\n\n\n\nURL pattern: \n^users/$\n Name: \n'user-list'\n\n\nURL pattern: \n^users/{pk}/$\n Name: \n'user-detail'\n\n\nURL pattern: \n^accounts/$\n Name: \n'account-list'\n\n\nURL pattern: \n^accounts/{pk}/$\n Name: \n'account-detail'\n\n\n\n\n\n\nNote\n: The \nbase_name\n argument is used to specify the initial part of the view name pattern. In the example above, that's the \nuser\n or \naccount\n part.\n\n\nTypically you won't \nneed\n to specify the \nbase_name\n argument, but if you have a viewset where you've defined a custom \nget_queryset\n method, then the viewset may not have a \n.queryset\n attribute set. If you try to register that viewset you'll see an error like this:\n\n\n'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.\n\n\n\nThis means you'll need to explicitly set the \nbase_name\n argument when registering the viewset, as it could not be automatically determined from the model name.\n\n\n\n\nUsing \ninclude\n with routers\n\n\nThe \n.urls\n attribute on a router instance is simply a standard list of URL patterns. There are a number of different styles for how you can include these URLs.\n\n\nFor example, you can append \nrouter.urls\n to a list of existing views\u2026\n\n\nrouter = routers.SimpleRouter()\nrouter.register(r'users', UserViewSet)\nrouter.register(r'accounts', AccountViewSet)\n\nurlpatterns = [\n url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),\n]\n\nurlpatterns += router.urls\n\n\n\nAlternatively you can use Django's \ninclude\n function, like so\u2026\n\n\nurlpatterns = [\n url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),\n url(r'^', include(router.urls)),\n]\n\n\n\nRouter URL patterns can also be namespaces.\n\n\nurlpatterns = [\n url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),\n url(r'^api/', include(router.urls, namespace='api')),\n]\n\n\n\nIf using namespacing with hyperlinked serializers you'll also need to ensure that any \nview_name\n parameters on the serializers correctly reflect the namespace. In the example above you'd need to include a parameter such as \nview_name='api:user-detail'\n for serializer fields hyperlinked to the user detail view.\n\n\nExtra link and actions\n\n\nAny methods on the viewset decorated with \n@detail_route\n or \n@list_route\n will also be routed.\nFor example, given a method like this on the \nUserViewSet\n class:\n\n\nfrom myapp.permissions import IsAdminOrIsSelf\nfrom rest_framework.decorators import detail_route\n\nclass UserViewSet(ModelViewSet):\n ...\n\n @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])\n def set_password(self, request, pk=None):\n ...\n\n\n\nThe following URL pattern would additionally be generated:\n\n\n\n\nURL pattern: \n^users/{pk}/set_password/$\n Name: \n'user-set-password'\n\n\n\n\nIf you do not want to use the default URL generated for your custom action, you can instead use the url_path parameter to customize it.\n\n\nFor example, if you want to change the URL for our custom action to \n^users/{pk}/change-password/$\n, you could write:\n\n\nfrom myapp.permissions import IsAdminOrIsSelf\nfrom rest_framework.decorators import detail_route\n\nclass UserViewSet(ModelViewSet):\n ...\n\n @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='change-password')\n def set_password(self, request, pk=None):\n ...\n\n\n\nThe above example would now generate the following URL pattern:\n\n\n\n\nURL pattern: \n^users/{pk}/change-password/$\n Name: \n'user-change-password'\n\n\n\n\nIn the case you do not want to use the default name generated for your custom action, you can use the url_name parameter to customize it.\n\n\nFor example, if you want to change the name of our custom action to \n'user-change-password'\n, you could write:\n\n\nfrom myapp.permissions import IsAdminOrIsSelf\nfrom rest_framework.decorators import detail_route\n\nclass UserViewSet(ModelViewSet):\n ...\n\n @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_name='change-password')\n def set_password(self, request, pk=None):\n ...\n\n\n\nThe above example would now generate the following URL pattern:\n\n\n\n\nURL pattern: \n^users/{pk}/set_password/$\n Name: \n'user-change-password'\n\n\n\n\nYou can also use url_path and url_name parameters together to obtain extra control on URL generation for custom views.\n\n\nFor more information see the viewset documentation on \nmarking extra actions for routing\n.\n\n\nAPI Guide\n\n\nSimpleRouter\n\n\nThis router includes routes for the standard set of \nlist\n, \ncreate\n, \nretrieve\n, \nupdate\n, \npartial_update\n and \ndestroy\n actions. The viewset can also mark additional methods to be routed, using the \n@detail_route\n or \n@list_route\n decorators.\n\n\n\n \nURL Style\nHTTP Method\nAction\nURL Name\n\n \n{prefix}/\nGET\nlist\n{basename}-list\n\n \nPOST\ncreate\n\n \n{prefix}/{methodname}/\nGET, or as specified by `methods` argument\n`@list_route` decorated method\n{basename}-{methodname}\n\n \n{prefix}/{lookup}/\nGET\nretrieve\n{basename}-detail\n\n \nPUT\nupdate\n\n \nPATCH\npartial_update\n\n \nDELETE\ndestroy\n\n \n{prefix}/{lookup}/{methodname}/\nGET, or as specified by `methods` argument\n`@detail_route` decorated method\n{basename}-{methodname}\n\n\n\n\n\nBy default the URLs created by \nSimpleRouter\n are appended with a trailing slash.\nThis behavior can be modified by setting the \ntrailing_slash\n argument to \nFalse\n when instantiating the router. For example:\n\n\nrouter = SimpleRouter(trailing_slash=False)\n\n\n\nTrailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.\n\n\nThe router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the \nlookup_value_regex\n attribute on the viewset. For example, you can limit the lookup to valid UUIDs:\n\n\nclass MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):\n lookup_field = 'my_model_id'\n lookup_value_regex = '[0-9a-f]{32}'\n\n\n\nDefaultRouter\n\n\nThis router is similar to \nSimpleRouter\n as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional \n.json\n style format suffixes.\n\n\n\n \nURL Style\nHTTP Method\nAction\nURL Name\n\n \n[.format]\nGET\nautomatically generated root view\napi-root\n\n \n{prefix}/[.format]\nGET\nlist\n{basename}-list\n\n \nPOST\ncreate\n\n \n{prefix}/{methodname}/[.format]\nGET, or as specified by `methods` argument\n`@list_route` decorated method\n{basename}-{methodname}\n\n \n{prefix}/{lookup}/[.format]\nGET\nretrieve\n{basename}-detail\n\n \nPUT\nupdate\n\n \nPATCH\npartial_update\n\n \nDELETE\ndestroy\n\n \n{prefix}/{lookup}/{methodname}/[.format]\nGET, or as specified by `methods` argument\n`@detail_route` decorated method\n{basename}-{methodname}\n\n\n\n\n\nAs with \nSimpleRouter\n the trailing slashes on the URL routes can be removed by setting the \ntrailing_slash\n argument to \nFalse\n when instantiating the router.\n\n\nrouter = DefaultRouter(trailing_slash=False)\n\n\n\nCustom Routers\n\n\nImplementing a custom router isn't something you'd need to do very often, but it can be useful if you have specific requirements about how the your URLs for your API are structured. Doing so allows you to encapsulate the URL structure in a reusable way that ensures you don't have to write your URL patterns explicitly for each new view.\n\n\nThe simplest way to implement a custom router is to subclass one of the existing router classes. The \n.routes\n attribute is used to template the URL patterns that will be mapped to each viewset. The \n.routes\n attribute is a list of \nRoute\n named tuples.\n\n\nThe arguments to the \nRoute\n named tuple are:\n\n\nurl\n: A string representing the URL to be routed. May include the following format strings:\n\n\n\n\n{prefix}\n - The URL prefix to use for this set of routes.\n\n\n{lookup}\n - The lookup field used to match against a single instance.\n\n\n{trailing_slash}\n - Either a '/' or an empty string, depending on the \ntrailing_slash\n argument.\n\n\n\n\nmapping\n: A mapping of HTTP method names to the view methods\n\n\nname\n: The name of the URL as used in \nreverse\n calls. May include the following format string:\n\n\n\n\n{basename}\n - The base to use for the URL names that are created.\n\n\n\n\ninitkwargs\n: A dictionary of any additional arguments that should be passed when instantiating the view. Note that the \nsuffix\n argument is reserved for identifying the viewset type, used when generating the view name and breadcrumb links.\n\n\nCustomizing dynamic routes\n\n\nYou can also customize how the \n@list_route\n and \n@detail_route\n decorators are routed.\nTo route either or both of these decorators, include a \nDynamicListRoute\n and/or \nDynamicDetailRoute\n named tuple in the \n.routes\n list.\n\n\nThe arguments to \nDynamicListRoute\n and \nDynamicDetailRoute\n are:\n\n\nurl\n: A string representing the URL to be routed. May include the same format strings as \nRoute\n, and additionally accepts the \n{methodname}\n and \n{methodnamehyphen}\n format strings.\n\n\nname\n: The name of the URL as used in \nreverse\n calls. May include the following format strings: \n{basename}\n, \n{methodname}\n and \n{methodnamehyphen}\n.\n\n\ninitkwargs\n: A dictionary of any additional arguments that should be passed when instantiating the view.\n\n\nExample\n\n\nThe following example will only route to the \nlist\n and \nretrieve\n actions, and does not use the trailing slash convention.\n\n\nfrom rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter\n\nclass CustomReadOnlyRouter(SimpleRouter):\n \"\"\"\n A router for read-only APIs, which doesn't use trailing slashes.\n \"\"\"\n routes = [\n Route(\n url=r'^{prefix}$',\n mapping={'get': 'list'},\n name='{basename}-list',\n initkwargs={'suffix': 'List'}\n ),\n Route(\n url=r'^{prefix}/{lookup}$',\n mapping={'get': 'retrieve'},\n name='{basename}-detail',\n initkwargs={'suffix': 'Detail'}\n ),\n DynamicDetailRoute(\n url=r'^{prefix}/{lookup}/{methodnamehyphen}$',\n name='{basename}-{methodnamehyphen}',\n initkwargs={}\n )\n ]\n\n\n\nLet's take a look at the routes our \nCustomReadOnlyRouter\n would generate for a simple viewset.\n\n\nviews.py\n:\n\n\nclass UserViewSet(viewsets.ReadOnlyModelViewSet):\n \"\"\"\n A viewset that provides the standard actions\n \"\"\"\n queryset = User.objects.all()\n serializer_class = UserSerializer\n lookup_field = 'username'\n\n @detail_route()\n def group_names(self, request, pk=None):\n \"\"\"\n Returns a list of all the group names that the given\n user belongs to.\n \"\"\"\n user = self.get_object()\n groups = user.groups.all()\n return Response([group.name for group in groups])\n\n\n\nurls.py\n:\n\n\nrouter = CustomReadOnlyRouter()\nrouter.register('users', UserViewSet)\nurlpatterns = router.urls\n\n\n\nThe following mappings would be generated...\n\n\n\n \nURL\nHTTP Method\nAction\nURL Name\n\n \n/users\nGET\nlist\nuser-list\n\n \n/users/{username}\nGET\nretrieve\nuser-detail\n\n \n/users/{username}/group-names\nGET\ngroup_names\nuser-group-names\n\n\n\n\n\nFor another example of setting the \n.routes\n attribute, see the source code for the \nSimpleRouter\n class.\n\n\nAdvanced custom routers\n\n\nIf you want to provide totally custom behavior, you can override \nBaseRouter\n and override the \nget_urls(self)\n method. The method should inspect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the \nself.registry\n attribute.\n\n\nYou may also want to override the \nget_default_base_name(self, viewset)\n method, or else always explicitly set the \nbase_name\n argument when registering your viewsets with the router.\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\nModelRouter (wq.db.rest)\n\n\nThe \nwq.db package\n provides an advanced \nModelRouter\n class (and singleton instance) that extends \nDefaultRouter\n with a \nregister_model()\n API. Much like Django's \nadmin.site.register\n, the only required argument to \nrest.router.register_model\n is a model class. Reasonable defaults for a url prefix, serializer, and viewset will be inferred from the model and global configuration.\n\n\nfrom wq.db import rest\nfrom myapp.models import MyModel\n\nrest.router.register_model(MyModel)\n\n\n\nDRF-extensions\n\n\nThe \nDRF-extensions\n package\n provides \nrouters\n for creating \nnested viewsets\n, \ncollection level controllers\n with \ncustomizable endpoint names\n.",
"title": "Routers"
},
{
@@ -1002,7 +1002,7 @@
},
{
"location": "/api-guide/routers/#example",
- "text": "The following example will only route to the list and retrieve actions, and does not use the trailing slash convention. from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter\n\nclass CustomReadOnlyRouter(SimpleRouter):\n \"\"\"\n A router for read-only APIs, which doesn't use trailing slashes.\n \"\"\"\n routes = [\n Route(\n url=r'^{prefix}$',\n mapping={'get': 'list'},\n name='{basename}-list',\n initkwargs={'suffix': 'List'}\n ),\n Route(\n url=r'^{prefix}/{lookup}$',\n mapping={'get': 'retrieve'},\n name='{basename}-detail',\n initkwargs={'suffix': 'Detail'}\n ),\n DynamicDetailRoute(\n url=r'^{prefix}/{lookup}/{methodnamehyphen}$',\n name='{basename}-{methodnamehyphen}',\n initkwargs={}\n )\n ] Let's take a look at the routes our CustomReadOnlyRouter would generate for a simple viewset. views.py : class UserViewSet(viewsets.ReadOnlyModelViewSet):\n \"\"\"\n A viewset that provides the standard actions\n \"\"\"\n queryset = User.objects.all()\n serializer_class = UserSerializer\n lookup_field = 'username'\n\n @detail_route()\n def group_names(self, request):\n \"\"\"\n Returns a list of all the group names that the given\n user belongs to.\n \"\"\"\n user = self.get_object()\n groups = user.groups.all()\n return Response([group.name for group in groups]) urls.py : router = CustomReadOnlyRouter()\nrouter.register('users', UserViewSet)\nurlpatterns = router.urls The following mappings would be generated... \n URL HTTP Method Action URL Name \n /users GET list user-list \n /users/{username} GET retrieve user-detail \n /users/{username}/group-names GET group_names user-group-names For another example of setting the .routes attribute, see the source code for the SimpleRouter class.",
+ "text": "The following example will only route to the list and retrieve actions, and does not use the trailing slash convention. from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter\n\nclass CustomReadOnlyRouter(SimpleRouter):\n \"\"\"\n A router for read-only APIs, which doesn't use trailing slashes.\n \"\"\"\n routes = [\n Route(\n url=r'^{prefix}$',\n mapping={'get': 'list'},\n name='{basename}-list',\n initkwargs={'suffix': 'List'}\n ),\n Route(\n url=r'^{prefix}/{lookup}$',\n mapping={'get': 'retrieve'},\n name='{basename}-detail',\n initkwargs={'suffix': 'Detail'}\n ),\n DynamicDetailRoute(\n url=r'^{prefix}/{lookup}/{methodnamehyphen}$',\n name='{basename}-{methodnamehyphen}',\n initkwargs={}\n )\n ] Let's take a look at the routes our CustomReadOnlyRouter would generate for a simple viewset. views.py : class UserViewSet(viewsets.ReadOnlyModelViewSet):\n \"\"\"\n A viewset that provides the standard actions\n \"\"\"\n queryset = User.objects.all()\n serializer_class = UserSerializer\n lookup_field = 'username'\n\n @detail_route()\n def group_names(self, request, pk=None):\n \"\"\"\n Returns a list of all the group names that the given\n user belongs to.\n \"\"\"\n user = self.get_object()\n groups = user.groups.all()\n return Response([group.name for group in groups]) urls.py : router = CustomReadOnlyRouter()\nrouter.register('users', UserViewSet)\nurlpatterns = router.urls The following mappings would be generated... \n URL HTTP Method Action URL Name \n /users GET list user-list \n /users/{username} GET retrieve user-detail \n /users/{username}/group-names GET group_names user-group-names For another example of setting the .routes attribute, see the source code for the SimpleRouter class.",
"title": "Example"
},
{
@@ -2317,7 +2317,7 @@
},
{
"location": "/api-guide/authentication/",
- "text": "Authentication\n\n\n\n\nAuth needs to be pluggable.\n\n\n Jacob Kaplan-Moss, \n\"REST worst practices\"\n\n\n\n\nAuthentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The \npermission\n and \nthrottling\n policies can then use those credentials to determine if the request should be permitted.\n\n\nREST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes.\n\n\nAuthentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.\n\n\nThe \nrequest.user\n property will typically be set to an instance of the \ncontrib.auth\n package's \nUser\n class.\n\n\nThe \nrequest.auth\n property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.\n\n\n\n\nNote:\n Don't forget that \nauthentication by itself won't allow or disallow an incoming request\n, it simply identifies the credentials that the request was made with.\n\n\nFor information on how to setup the permission polices for your API please see the \npermissions documentation\n.\n\n\n\n\nHow authentication is determined\n\n\nThe authentication schemes are always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set \nrequest.user\n and \nrequest.auth\n using the return value of the first class that successfully authenticates.\n\n\nIf no class authenticates, \nrequest.user\n will be set to an instance of \ndjango.contrib.auth.models.AnonymousUser\n, and \nrequest.auth\n will be set to \nNone\n.\n\n\nThe value of \nrequest.user\n and \nrequest.auth\n for unauthenticated requests can be modified using the \nUNAUTHENTICATED_USER\n and \nUNAUTHENTICATED_TOKEN\n settings.\n\n\nSetting the authentication scheme\n\n\nThe default authentication schemes may be set globally, using the \nDEFAULT_AUTHENTICATION_CLASSES\n setting. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_AUTHENTICATION_CLASSES': (\n 'rest_framework.authentication.BasicAuthentication',\n 'rest_framework.authentication.SessionAuthentication',\n )\n}\n\n\n\nYou can also set the authentication scheme on a per-view or per-viewset basis,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.authentication import SessionAuthentication, BasicAuthentication\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n authentication_classes = (SessionAuthentication, BasicAuthentication)\n permission_classes = (IsAuthenticated,)\n\n def get(self, request, format=None):\n content = {\n 'user': unicode(request.user), # `django.contrib.auth.User` instance.\n 'auth': unicode(request.auth), # None\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\n@api_view(['GET'])\n@authentication_classes((SessionAuthentication, BasicAuthentication))\n@permission_classes((IsAuthenticated,))\ndef example_view(request, format=None):\n content = {\n 'user': unicode(request.user), # `django.contrib.auth.User` instance.\n 'auth': unicode(request.auth), # None\n }\n return Response(content)\n\n\n\nUnauthorized and Forbidden responses\n\n\nWhen an unauthenticated request is denied permission there are two different error codes that may be appropriate.\n\n\n\n\nHTTP 401 Unauthorized\n\n\nHTTP 403 Permission Denied\n\n\n\n\nHTTP 401 responses must always include a \nWWW-Authenticate\n header, that instructs the client how to authenticate. HTTP 403 responses do not include the \nWWW-Authenticate\n header.\n\n\nThe kind of response that will be used depends on the authentication scheme. Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. \nThe first authentication class set on the view is used when determining the type of response\n.\n\n\nNote that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a \n403 Permission Denied\n response will always be used, regardless of the authentication scheme.\n\n\nApache mod_wsgi specific configuration\n\n\nNote that if deploying to \nApache using mod_wsgi\n, the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level.\n\n\nIf you are deploying to Apache, and using any non-session based authentication, you will need to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the \nWSGIPassAuthorization\n directive in the appropriate context and setting it to \n'On'\n.\n\n\n# this can go in either server config, virtual host, directory or .htaccess\nWSGIPassAuthorization On\n\n\n\n\n\nAPI Reference\n\n\nBasicAuthentication\n\n\nThis authentication scheme uses \nHTTP Basic Authentication\n, signed against a user's username and password. Basic authentication is generally only appropriate for testing.\n\n\nIf successfully authenticated, \nBasicAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be \nNone\n.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 401 Unauthorized\n response with an appropriate WWW-Authenticate header. For example:\n\n\nWWW-Authenticate: Basic realm=\"api\"\n\n\n\nNote:\n If you use \nBasicAuthentication\n in production you must ensure that your API is only available over \nhttps\n. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.\n\n\nTokenAuthentication\n\n\nThis authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.\n\n\nTo use the \nTokenAuthentication\n scheme you'll need to \nconfigure the authentication classes\n to include \nTokenAuthentication\n, and additionally include \nrest_framework.authtoken\n in your \nINSTALLED_APPS\n setting:\n\n\nINSTALLED_APPS = (\n ...\n 'rest_framework.authtoken'\n)\n\n\n\n\n\nNote:\n Make sure to run \nmanage.py migrate\n after changing your settings. The \nrest_framework.authtoken\n app provides Django database migrations.\n\n\n\n\nYou'll also need to create tokens for your users.\n\n\nfrom rest_framework.authtoken.models import Token\n\ntoken = Token.objects.create(user=...)\nprint token.key\n\n\n\nFor clients to authenticate, the token key should be included in the \nAuthorization\n HTTP header. The key should be prefixed by the string literal \"Token\", with whitespace separating the two strings. For example:\n\n\nAuthorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b\n\n\n\nNote:\n If you want to use a different keyword in the header, such as \nBearer\n, simply subclass \nTokenAuthentication\n and set the \nkeyword\n class variable.\n\n\nIf successfully authenticated, \nTokenAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be a \nrest_framework.authtoken.models.Token\n instance.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 401 Unauthorized\n response with an appropriate WWW-Authenticate header. For example:\n\n\nWWW-Authenticate: Token\n\n\n\nThe \ncurl\n command line tool may be useful for testing token authenticated APIs. For example:\n\n\ncurl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'\n\n\n\n\n\nNote:\n If you use \nTokenAuthentication\n in production you must ensure that your API is only available over \nhttps\n.\n\n\n\n\nGenerating Tokens\n\n\nBy using signals\n\n\nIf you want every user to have an automatically generated Token, you can simply catch the User's \npost_save\n signal.\n\n\nfrom django.conf import settings\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\nfrom rest_framework.authtoken.models import Token\n\n@receiver(post_save, sender=settings.AUTH_USER_MODEL)\ndef create_auth_token(sender, instance=None, created=False, **kwargs):\n if created:\n Token.objects.create(user=instance)\n\n\n\nNote that you'll want to ensure you place this code snippet in an installed \nmodels.py\n module, or some other location that will be imported by Django on startup.\n\n\nIf you've already created some users, you can generate tokens for all existing users like this:\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework.authtoken.models import Token\n\nfor user in User.objects.all():\n Token.objects.get_or_create(user=user)\n\n\n\nBy exposing an api endpoint\n\n\nWhen using \nTokenAuthentication\n, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the \nobtain_auth_token\n view to your URLconf:\n\n\nfrom rest_framework.authtoken import views\nurlpatterns += [\n url(r'^api-token-auth/', views.obtain_auth_token)\n]\n\n\n\nNote that the URL part of the pattern can be whatever you want to use.\n\n\nThe \nobtain_auth_token\n view will return a JSON response when valid \nusername\n and \npassword\n fields are POSTed to the view using form data or JSON:\n\n\n{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }\n\n\n\nNote that the default \nobtain_auth_token\n view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the \nobtain_auth_token\n view, you can do so by overriding the \nObtainAuthToken\n view class, and using that in your url conf instead.\n\n\nBy default there are no permissions or throttling applied to the \nobtain_auth_token\n view. If you do wish to apply throttling you'll need to override the view class,\nand include them using the \nthrottle_classes\n attribute.\n\n\nWith Django admin\n\n\nIt is also possible to create Tokens manually through admin interface. In case you are using a large user base, we recommend that you monkey patch the \nTokenAdmin\n class to customize it to your needs, more specifically by declaring the \nuser\n field as \nraw_field\n.\n\n\nyour_app/admin.py\n:\n\n\nfrom rest_framework.authtoken.admin import TokenAdmin\n\nTokenAdmin.raw_id_fields = ('user',)\n\n\n\nSessionAuthentication\n\n\nThis authentication scheme uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website.\n\n\nIf successfully authenticated, \nSessionAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be \nNone\n.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 403 Forbidden\n response.\n\n\nIf you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any \"unsafe\" HTTP method calls, such as \nPUT\n, \nPATCH\n, \nPOST\n or \nDELETE\n requests. See the \nDjango CSRF documentation\n for more details.\n\n\nWarning\n: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.\n\n\nCSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.\n\n\nCustom authentication\n\n\nTo implement a custom authentication scheme, subclass \nBaseAuthentication\n and override the \n.authenticate(self, request)\n method. The method should return a two-tuple of \n(user, auth)\n if authentication succeeds, or \nNone\n otherwise.\n\n\nIn some circumstances instead of returning \nNone\n, you may want to raise an \nAuthenticationFailed\n exception from the \n.authenticate()\n method.\n\n\nTypically the approach you should take is:\n\n\n\n\nIf authentication is not attempted, return \nNone\n. Any other authentication schemes also in use will still be checked.\n\n\nIf authentication is attempted but fails, raise a \nAuthenticationFailed\n exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes.\n\n\n\n\nYou \nmay\n also override the \n.authenticate_header(self, request)\n method. If implemented, it should return a string that will be used as the value of the \nWWW-Authenticate\n header in a \nHTTP 401 Unauthorized\n response.\n\n\nIf the \n.authenticate_header()\n method is not overridden, the authentication scheme will return \nHTTP 403 Forbidden\n responses when an unauthenticated request is denied access.\n\n\nExample\n\n\nThe following example will authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'.\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework import authentication\nfrom rest_framework import exceptions\n\nclass ExampleAuthentication(authentication.BaseAuthentication):\n def authenticate(self, request):\n username = request.META.get('X_USERNAME')\n if not username:\n return None\n\n try:\n user = User.objects.get(username=username)\n except User.DoesNotExist:\n raise exceptions.AuthenticationFailed('No such user')\n\n return (user, None)\n\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nDjango OAuth Toolkit\n\n\nThe \nDjango OAuth Toolkit\n package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by \nEvonove\n and uses the excellent \nOAuthLib\n. The package is well documented, and well supported and is currently our \nrecommended package for OAuth 2.0 support\n.\n\n\nInstallation \n configuration\n\n\nInstall using \npip\n.\n\n\npip install django-oauth-toolkit\n\n\n\nAdd the package to your \nINSTALLED_APPS\n and modify your REST framework settings.\n\n\nINSTALLED_APPS = (\n ...\n 'oauth2_provider',\n)\n\nREST_FRAMEWORK = {\n 'DEFAULT_AUTHENTICATION_CLASSES': (\n 'oauth2_provider.ext.rest_framework.OAuth2Authentication',\n )\n}\n\n\n\nFor more details see the \nDjango REST framework - Getting started\n documentation.\n\n\nDjango REST framework OAuth\n\n\nThe \nDjango REST framework OAuth\n package provides both OAuth1 and OAuth2 support for REST framework.\n\n\nThis package was previously included directly in REST framework but is now supported and maintained as a third party package.\n\n\nInstallation \n configuration\n\n\nInstall the package using \npip\n.\n\n\npip install djangorestframework-oauth\n\n\n\nFor details on configuration and usage see the Django REST framework OAuth documentation for \nauthentication\n and \npermissions\n.\n\n\nDigest Authentication\n\n\nHTTP digest authentication is a widely implemented scheme that was intended to replace HTTP basic authentication, and which provides a simple encrypted authentication mechanism. \nJuan Riaza\n maintains the \ndjangorestframework-digestauth\n package which provides HTTP digest authentication support for REST framework.\n\n\nDjango OAuth2 Consumer\n\n\nThe \nDjango OAuth2 Consumer\n library from \nRediker Software\n is another package that provides \nOAuth 2.0 support for REST framework\n. The package includes token scoping permissions on tokens, which allows finer-grained access to your API.\n\n\nJSON Web Token Authentication\n\n\nJSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. \nBlimp\n maintains the \ndjangorestframework-jwt\n package which provides a JWT Authentication class as well as a mechanism for clients to obtain a JWT given the username and password.\n\n\nHawk HTTP Authentication\n\n\nThe \nHawkREST\n library builds on the \nMohawk\n library to let you work with \nHawk\n signed requests and responses in your API. \nHawk\n lets two parties securely communicate with each other using messages signed by a shared key. It is based on \nHTTP MAC access authentication\n (which was based on parts of \nOAuth 1.0\n).\n\n\nHTTP Signature Authentication\n\n\nHTTP Signature (currently a \nIETF draft\n) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to \nAmazon's HTTP Signature scheme\n, used by many of its services, it permits stateless, per-request authentication. \nElvio Toccalino\n maintains the \ndjangorestframework-httpsignature\n package which provides an easy to use HTTP Signature Authentication mechanism.\n\n\nDjoser\n\n\nDjoser\n library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and it uses token based authentication. This is a ready to use REST implementation of Django authentication system.\n\n\ndjango-rest-auth\n\n\nDjango-rest-auth\n library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.\n\n\ndjango-rest-framework-social-oauth2\n\n\nDjango-rest-framework-social-oauth2\n library provides an easy way to integrate social plugins (facebook, twitter, google, etc.) to your authentication system and an easy oauth2 setup. With this library, you will be able to authenticate users based on external tokens (e.g. facebook access token), convert these tokens to \"in-house\" oauth2 tokens and use and generate oauth2 tokens to authenticate your users.\n\n\ndjango-rest-knox\n\n\nDjango-rest-knox\n library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).",
+ "text": "Authentication\n\n\n\n\nAuth needs to be pluggable.\n\n\n Jacob Kaplan-Moss, \n\"REST worst practices\"\n\n\n\n\nAuthentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The \npermission\n and \nthrottling\n policies can then use those credentials to determine if the request should be permitted.\n\n\nREST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes.\n\n\nAuthentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.\n\n\nThe \nrequest.user\n property will typically be set to an instance of the \ncontrib.auth\n package's \nUser\n class.\n\n\nThe \nrequest.auth\n property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.\n\n\n\n\nNote:\n Don't forget that \nauthentication by itself won't allow or disallow an incoming request\n, it simply identifies the credentials that the request was made with.\n\n\nFor information on how to setup the permission polices for your API please see the \npermissions documentation\n.\n\n\n\n\nHow authentication is determined\n\n\nThe authentication schemes are always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set \nrequest.user\n and \nrequest.auth\n using the return value of the first class that successfully authenticates.\n\n\nIf no class authenticates, \nrequest.user\n will be set to an instance of \ndjango.contrib.auth.models.AnonymousUser\n, and \nrequest.auth\n will be set to \nNone\n.\n\n\nThe value of \nrequest.user\n and \nrequest.auth\n for unauthenticated requests can be modified using the \nUNAUTHENTICATED_USER\n and \nUNAUTHENTICATED_TOKEN\n settings.\n\n\nSetting the authentication scheme\n\n\nThe default authentication schemes may be set globally, using the \nDEFAULT_AUTHENTICATION_CLASSES\n setting. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_AUTHENTICATION_CLASSES': (\n 'rest_framework.authentication.BasicAuthentication',\n 'rest_framework.authentication.SessionAuthentication',\n )\n}\n\n\n\nYou can also set the authentication scheme on a per-view or per-viewset basis,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.authentication import SessionAuthentication, BasicAuthentication\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n authentication_classes = (SessionAuthentication, BasicAuthentication)\n permission_classes = (IsAuthenticated,)\n\n def get(self, request, format=None):\n content = {\n 'user': unicode(request.user), # `django.contrib.auth.User` instance.\n 'auth': unicode(request.auth), # None\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\n@api_view(['GET'])\n@authentication_classes((SessionAuthentication, BasicAuthentication))\n@permission_classes((IsAuthenticated,))\ndef example_view(request, format=None):\n content = {\n 'user': unicode(request.user), # `django.contrib.auth.User` instance.\n 'auth': unicode(request.auth), # None\n }\n return Response(content)\n\n\n\nUnauthorized and Forbidden responses\n\n\nWhen an unauthenticated request is denied permission there are two different error codes that may be appropriate.\n\n\n\n\nHTTP 401 Unauthorized\n\n\nHTTP 403 Permission Denied\n\n\n\n\nHTTP 401 responses must always include a \nWWW-Authenticate\n header, that instructs the client how to authenticate. HTTP 403 responses do not include the \nWWW-Authenticate\n header.\n\n\nThe kind of response that will be used depends on the authentication scheme. Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. \nThe first authentication class set on the view is used when determining the type of response\n.\n\n\nNote that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a \n403 Permission Denied\n response will always be used, regardless of the authentication scheme.\n\n\nApache mod_wsgi specific configuration\n\n\nNote that if deploying to \nApache using mod_wsgi\n, the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level.\n\n\nIf you are deploying to Apache, and using any non-session based authentication, you will need to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the \nWSGIPassAuthorization\n directive in the appropriate context and setting it to \n'On'\n.\n\n\n# this can go in either server config, virtual host, directory or .htaccess\nWSGIPassAuthorization On\n\n\n\n\n\nAPI Reference\n\n\nBasicAuthentication\n\n\nThis authentication scheme uses \nHTTP Basic Authentication\n, signed against a user's username and password. Basic authentication is generally only appropriate for testing.\n\n\nIf successfully authenticated, \nBasicAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be \nNone\n.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 401 Unauthorized\n response with an appropriate WWW-Authenticate header. For example:\n\n\nWWW-Authenticate: Basic realm=\"api\"\n\n\n\nNote:\n If you use \nBasicAuthentication\n in production you must ensure that your API is only available over \nhttps\n. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.\n\n\nTokenAuthentication\n\n\nThis authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.\n\n\nTo use the \nTokenAuthentication\n scheme you'll need to \nconfigure the authentication classes\n to include \nTokenAuthentication\n, and additionally include \nrest_framework.authtoken\n in your \nINSTALLED_APPS\n setting:\n\n\nINSTALLED_APPS = (\n ...\n 'rest_framework.authtoken'\n)\n\n\n\n\n\nNote:\n Make sure to run \nmanage.py migrate\n after changing your settings. The \nrest_framework.authtoken\n app provides Django database migrations.\n\n\n\n\nYou'll also need to create tokens for your users.\n\n\nfrom rest_framework.authtoken.models import Token\n\ntoken = Token.objects.create(user=...)\nprint token.key\n\n\n\nFor clients to authenticate, the token key should be included in the \nAuthorization\n HTTP header. The key should be prefixed by the string literal \"Token\", with whitespace separating the two strings. For example:\n\n\nAuthorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b\n\n\n\nNote:\n If you want to use a different keyword in the header, such as \nBearer\n, simply subclass \nTokenAuthentication\n and set the \nkeyword\n class variable.\n\n\nIf successfully authenticated, \nTokenAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be a \nrest_framework.authtoken.models.Token\n instance.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 401 Unauthorized\n response with an appropriate WWW-Authenticate header. For example:\n\n\nWWW-Authenticate: Token\n\n\n\nThe \ncurl\n command line tool may be useful for testing token authenticated APIs. For example:\n\n\ncurl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'\n\n\n\n\n\nNote:\n If you use \nTokenAuthentication\n in production you must ensure that your API is only available over \nhttps\n.\n\n\n\n\nGenerating Tokens\n\n\nBy using signals\n\n\nIf you want every user to have an automatically generated Token, you can simply catch the User's \npost_save\n signal.\n\n\nfrom django.conf import settings\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\nfrom rest_framework.authtoken.models import Token\n\n@receiver(post_save, sender=settings.AUTH_USER_MODEL)\ndef create_auth_token(sender, instance=None, created=False, **kwargs):\n if created:\n Token.objects.create(user=instance)\n\n\n\nNote that you'll want to ensure you place this code snippet in an installed \nmodels.py\n module, or some other location that will be imported by Django on startup.\n\n\nIf you've already created some users, you can generate tokens for all existing users like this:\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework.authtoken.models import Token\n\nfor user in User.objects.all():\n Token.objects.get_or_create(user=user)\n\n\n\nBy exposing an api endpoint\n\n\nWhen using \nTokenAuthentication\n, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the \nobtain_auth_token\n view to your URLconf:\n\n\nfrom rest_framework.authtoken import views\nurlpatterns += [\n url(r'^api-token-auth/', views.obtain_auth_token)\n]\n\n\n\nNote that the URL part of the pattern can be whatever you want to use.\n\n\nThe \nobtain_auth_token\n view will return a JSON response when valid \nusername\n and \npassword\n fields are POSTed to the view using form data or JSON:\n\n\n{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }\n\n\n\nNote that the default \nobtain_auth_token\n view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the \nobtain_auth_token\n view, you can do so by overriding the \nObtainAuthToken\n view class, and using that in your url conf instead.\n\n\nBy default there are no permissions or throttling applied to the \nobtain_auth_token\n view. If you do wish to apply throttling you'll need to override the view class,\nand include them using the \nthrottle_classes\n attribute.\n\n\nWith Django admin\n\n\nIt is also possible to create Tokens manually through admin interface. In case you are using a large user base, we recommend that you monkey patch the \nTokenAdmin\n class to customize it to your needs, more specifically by declaring the \nuser\n field as \nraw_field\n.\n\n\nyour_app/admin.py\n:\n\n\nfrom rest_framework.authtoken.admin import TokenAdmin\n\nTokenAdmin.raw_id_fields = ('user',)\n\n\n\nSessionAuthentication\n\n\nThis authentication scheme uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website.\n\n\nIf successfully authenticated, \nSessionAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be \nNone\n.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 403 Forbidden\n response.\n\n\nIf you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any \"unsafe\" HTTP method calls, such as \nPUT\n, \nPATCH\n, \nPOST\n or \nDELETE\n requests. See the \nDjango CSRF documentation\n for more details.\n\n\nWarning\n: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.\n\n\nCSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.\n\n\nCustom authentication\n\n\nTo implement a custom authentication scheme, subclass \nBaseAuthentication\n and override the \n.authenticate(self, request)\n method. The method should return a two-tuple of \n(user, auth)\n if authentication succeeds, or \nNone\n otherwise.\n\n\nIn some circumstances instead of returning \nNone\n, you may want to raise an \nAuthenticationFailed\n exception from the \n.authenticate()\n method.\n\n\nTypically the approach you should take is:\n\n\n\n\nIf authentication is not attempted, return \nNone\n. Any other authentication schemes also in use will still be checked.\n\n\nIf authentication is attempted but fails, raise a \nAuthenticationFailed\n exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes.\n\n\n\n\nYou \nmay\n also override the \n.authenticate_header(self, request)\n method. If implemented, it should return a string that will be used as the value of the \nWWW-Authenticate\n header in a \nHTTP 401 Unauthorized\n response.\n\n\nIf the \n.authenticate_header()\n method is not overridden, the authentication scheme will return \nHTTP 403 Forbidden\n responses when an unauthenticated request is denied access.\n\n\nExample\n\n\nThe following example will authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'.\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework import authentication\nfrom rest_framework import exceptions\n\nclass ExampleAuthentication(authentication.BaseAuthentication):\n def authenticate(self, request):\n username = request.META.get('X_USERNAME')\n if not username:\n return None\n\n try:\n user = User.objects.get(username=username)\n except User.DoesNotExist:\n raise exceptions.AuthenticationFailed('No such user')\n\n return (user, None)\n\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nDjango OAuth Toolkit\n\n\nThe \nDjango OAuth Toolkit\n package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by \nEvonove\n and uses the excellent \nOAuthLib\n. The package is well documented, and well supported and is currently our \nrecommended package for OAuth 2.0 support\n.\n\n\nInstallation \n configuration\n\n\nInstall using \npip\n.\n\n\npip install django-oauth-toolkit\n\n\n\nAdd the package to your \nINSTALLED_APPS\n and modify your REST framework settings.\n\n\nINSTALLED_APPS = (\n ...\n 'oauth2_provider',\n)\n\nREST_FRAMEWORK = {\n 'DEFAULT_AUTHENTICATION_CLASSES': (\n 'oauth2_provider.ext.rest_framework.OAuth2Authentication',\n )\n}\n\n\n\nFor more details see the \nDjango REST framework - Getting started\n documentation.\n\n\nDjango REST framework OAuth\n\n\nThe \nDjango REST framework OAuth\n package provides both OAuth1 and OAuth2 support for REST framework.\n\n\nThis package was previously included directly in REST framework but is now supported and maintained as a third party package.\n\n\nInstallation \n configuration\n\n\nInstall the package using \npip\n.\n\n\npip install djangorestframework-oauth\n\n\n\nFor details on configuration and usage see the Django REST framework OAuth documentation for \nauthentication\n and \npermissions\n.\n\n\nDigest Authentication\n\n\nHTTP digest authentication is a widely implemented scheme that was intended to replace HTTP basic authentication, and which provides a simple encrypted authentication mechanism. \nJuan Riaza\n maintains the \ndjangorestframework-digestauth\n package which provides HTTP digest authentication support for REST framework.\n\n\nDjango OAuth2 Consumer\n\n\nThe \nDjango OAuth2 Consumer\n library from \nRediker Software\n is another package that provides \nOAuth 2.0 support for REST framework\n. The package includes token scoping permissions on tokens, which allows finer-grained access to your API.\n\n\nJSON Web Token Authentication\n\n\nJSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. \nBlimp\n maintains the \ndjangorestframework-jwt\n package which provides a JWT Authentication class as well as a mechanism for clients to obtain a JWT given the username and password.\n\n\nHawk HTTP Authentication\n\n\nThe \nHawkREST\n library builds on the \nMohawk\n library to let you work with \nHawk\n signed requests and responses in your API. \nHawk\n lets two parties securely communicate with each other using messages signed by a shared key. It is based on \nHTTP MAC access authentication\n (which was based on parts of \nOAuth 1.0\n).\n\n\nHTTP Signature Authentication\n\n\nHTTP Signature (currently a \nIETF draft\n) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to \nAmazon's HTTP Signature scheme\n, used by many of its services, it permits stateless, per-request authentication. \nElvio Toccalino\n maintains the \ndjangorestframework-httpsignature\n package which provides an easy to use HTTP Signature Authentication mechanism.\n\n\nDjoser\n\n\nDjoser\n library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and it uses token based authentication. This is a ready to use REST implementation of Django authentication system.\n\n\ndjango-rest-auth\n\n\nDjango-rest-auth\n library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.\n\n\ndjango-rest-framework-social-oauth2\n\n\nDjango-rest-framework-social-oauth2\n library provides an easy way to integrate social plugins (facebook, twitter, google, etc.) to your authentication system and an easy oauth2 setup. With this library, you will be able to authenticate users based on external tokens (e.g. facebook access token), convert these tokens to \"in-house\" oauth2 tokens and use and generate oauth2 tokens to authenticate your users.\n\n\ndjango-rest-knox\n\n\nDjango-rest-knox\n library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).\n\n\ndrfpasswordless\n\n\ndrfpasswordless\n adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's own TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number.",
"title": "Authentication"
},
{
@@ -2465,6 +2465,11 @@
"text": "Django-rest-knox library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).",
"title": "django-rest-knox"
},
+ {
+ "location": "/api-guide/authentication/#drfpasswordless",
+ "text": "drfpasswordless adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's own TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number.",
+ "title": "drfpasswordless"
+ },
{
"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 \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 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 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 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())\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\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, you'll want to consider also adding the \nDjangoObjectPermissionsFilter\n class to ensure that list endpoints only return results including objects for which the user has appropriate view permissions.\n\n\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.\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.",
@@ -2642,7 +2647,7 @@
},
{
"location": "/api-guide/filtering/",
- "text": "Filtering\n\n\n\n\nThe root QuerySet provided by the Manager describes all objects in the database table. Usually, though, you'll need to select only a subset of the complete set of objects.\n\n\n \nDjango documentation\n\n\n\n\nThe default behavior of REST framework's generic list views is to return the entire queryset for a model manager. Often you will want your API to restrict the items that are returned by the queryset.\n\n\nThe simplest way to filter the queryset of any view that subclasses \nGenericAPIView\n is to override the \n.get_queryset()\n method.\n\n\nOverriding this method allows you to customize the queryset returned by the view in a number of different ways.\n\n\nFiltering against the current user\n\n\nYou might want to filter the queryset to ensure that only results relevant to the currently authenticated user making the request are returned.\n\n\nYou can do so by filtering based on the value of \nrequest.user\n.\n\n\nFor example:\n\n\nfrom myapp.models import Purchase\nfrom myapp.serializers import PurchaseSerializer\nfrom rest_framework import generics\n\nclass PurchaseList(generics.ListAPIView):\n serializer_class = PurchaseSerializer\n\n def get_queryset(self):\n \"\"\"\n This view should return a list of all the purchases\n for the currently authenticated user.\n \"\"\"\n user = self.request.user\n return Purchase.objects.filter(purchaser=user)\n\n\n\nFiltering against the URL\n\n\nAnother style of filtering might involve restricting the queryset based on some part of the URL.\n\n\nFor example if your URL config contained an entry like this:\n\n\nurl('^purchases/(?P\nusername\n.+)/$', PurchaseList.as_view()),\n\n\n\nYou could then write a view that returned a purchase queryset filtered by the username portion of the URL:\n\n\nclass PurchaseList(generics.ListAPIView):\n serializer_class = PurchaseSerializer\n\n def get_queryset(self):\n \"\"\"\n This view should return a list of all the purchases for\n the user as determined by the username portion of the URL.\n \"\"\"\n username = self.kwargs['username']\n return Purchase.objects.filter(purchaser__username=username)\n\n\n\nFiltering against query parameters\n\n\nA final example of filtering the initial queryset would be to determine the initial queryset based on query parameters in the url.\n\n\nWe can override \n.get_queryset()\n to deal with URLs such as \nhttp://example.com/api/purchases?username=denvercoder9\n, and filter the queryset only if the \nusername\n parameter is included in the URL:\n\n\nclass PurchaseList(generics.ListAPIView):\n serializer_class = PurchaseSerializer\n\n def get_queryset(self):\n \"\"\"\n Optionally restricts the returned purchases to a given user,\n by filtering against a `username` query parameter in the URL.\n \"\"\"\n queryset = Purchase.objects.all()\n username = self.request.query_params.get('username', None)\n if username is not None:\n queryset = queryset.filter(purchaser__username=username)\n return queryset\n\n\n\n\n\nGeneric Filtering\n\n\nAs well as being able to override the default queryset, REST framework also includes support for generic filtering backends that allow you to easily construct complex searches and filters.\n\n\nGeneric filters can also present themselves as HTML controls in the browsable API and admin API.\n\n\n\n\nSetting filter backends\n\n\nThe default filter backends may be set globally, using the \nDEFAULT_FILTER_BACKENDS\n setting. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)\n}\n\n\n\nYou can also set the filter backends on a per-view, or per-viewset basis,\nusing the \nGenericAPIView\n class-based views.\n\n\nimport django_filters.rest_framework\nfrom django.contrib.auth.models import User\nfrom myapp.serializers import UserSerializer\nfrom rest_framework import generics\n\nclass UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)\n\n\n\nFiltering and object lookups\n\n\nNote that if a filter backend is configured for a view, then as well as being used to filter list views, it will also be used to filter the querysets used for returning a single object.\n\n\nFor instance, given the previous example, and a product with an id of \n4675\n, the following URL would either return the corresponding object, or return a 404 response, depending on if the filtering conditions were met by the given product instance:\n\n\nhttp://example.com/api/products/4675/?category=clothing\nmax_price=10.00\n\n\n\nOverriding the initial queryset\n\n\nNote that you can use both an overridden \n.get_queryset()\n and generic filtering together, and everything will work as expected. For example, if \nProduct\n had a many-to-many relationship with \nUser\n, named \npurchase\n, you might want to write a view like this:\n\n\nclass PurchasedProductsList(generics.ListAPIView):\n \"\"\"\n Return a list of all the products that the authenticated\n user has ever purchased, with optional filtering.\n \"\"\"\n model = Product\n serializer_class = ProductSerializer\n filter_class = ProductFilter\n\n def get_queryset(self):\n user = self.request.user\n return user.purchase_set.all()\n\n\n\n\n\nAPI Guide\n\n\nDjangoFilterBackend\n\n\nThe \ndjango-filter\n library includes a \nDjangoFilterBackend\n class which\nsupports highly customizable field filtering for REST framework.\n\n\nTo use \nDjangoFilterBackend\n, first install \ndjango-filter\n.\n\n\npip install django-filter\n\n\n\nYou should now either add the filter backend to your settings:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)\n}\n\n\n\nOr add the filter backend to an individual View or ViewSet.\n\n\nfrom django_filters.rest_framework import DjangoFilterBackend\n\nclass UserListView(generics.ListAPIView):\n ...\n filter_backends = (DjangoFilterBackend,)\n\n\n\nIf you are using the browsable API or admin API you may also want to install \ndjango-crispy-forms\n, which will enhance the presentation of the filter forms in HTML views, by allowing them to render Bootstrap 3 HTML.\n\n\npip install django-crispy-forms\n\n\n\nWith crispy forms installed and added to Django's \nINSTALLED_APPS\n, the browsable API will present a filtering control for \nDjangoFilterBackend\n, like so:\n\n\n\n\nSpecifying filter fields\n\n\nIf all you need is simple equality-based filtering, you can set a \nfilter_fields\n attribute on the view, or viewset, listing the set of fields you wish to filter against.\n\n\nclass ProductList(generics.ListAPIView):\n queryset = Product.objects.all()\n serializer_class = ProductSerializer\n filter_backends = (filters.DjangoFilterBackend,)\n filter_fields = ('category', 'in_stock')\n\n\n\nThis will automatically create a \nFilterSet\n class for the given fields, and will allow you to make requests such as:\n\n\nhttp://example.com/api/products?category=clothing\nin_stock=True\n\n\n\nSpecifying a FilterSet\n\n\nFor more advanced filtering requirements you can specify a \nFilterSet\n class that should be used by the view. For example:\n\n\nimport django_filters\nfrom myapp.models import Product\nfrom myapp.serializers import ProductSerializer\nfrom rest_framework import generics\n\nclass ProductFilter(django_filters.rest_framework.FilterSet):\n min_price = django_filters.NumberFilter(name=\"price\", lookup_expr='gte')\n max_price = django_filters.NumberFilter(name=\"price\", lookup_expr='lte')\n class Meta:\n model = Product\n fields = ['category', 'in_stock', 'min_price', 'max_price']\n\nclass ProductList(generics.ListAPIView):\n queryset = Product.objects.all()\n serializer_class = ProductSerializer\n filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)\n filter_class = ProductFilter\n\n\n\nWhich will allow you to make requests such as:\n\n\nhttp://example.com/api/products?category=clothing\nmax_price=10.00\n\n\n\nYou can also span relationships using \ndjango-filter\n, let's assume that each\nproduct has foreign key to \nManufacturer\n model, so we create filter that\nfilters using \nManufacturer\n name. For example:\n\n\nimport django_filters\nfrom myapp.models import Product\nfrom myapp.serializers import ProductSerializer\nfrom rest_framework import generics\n\nclass ProductFilter(django_filters.rest_framework.FilterSet):\n class Meta:\n model = Product\n fields = ['category', 'in_stock', 'manufacturer__name']\n\n\n\nThis enables us to make queries like:\n\n\nhttp://example.com/api/products?manufacturer__name=foo\n\n\n\nThis is nice, but it exposes the Django's double underscore convention as part of the API. If you instead want to explicitly name the filter argument you can instead explicitly include it on the \nFilterSet\n class:\n\n\nimport django_filters\nfrom myapp.models import Product\nfrom myapp.serializers import ProductSerializer\nfrom rest_framework import generics\n\nclass ProductFilter(django_filters.rest_framework.FilterSet):\n manufacturer = django_filters.CharFilter(name=\"manufacturer__name\")\n\n class Meta:\n model = Product\n fields = ['category', 'in_stock', 'manufacturer']\n\n\n\nAnd now you can execute:\n\n\nhttp://example.com/api/products?manufacturer=foo\n\n\n\nFor more details on using filter sets see the \ndjango-filter documentation\n.\n\n\n\n\nHints \n Tips\n\n\n\n\nBy default filtering is not enabled. If you want to use \nDjangoFilterBackend\n remember to make sure it is installed by using the \n'DEFAULT_FILTER_BACKENDS'\n setting.\n\n\nWhen using boolean fields, you should use the values \nTrue\n and \nFalse\n in the URL query parameters, rather than \n0\n, \n1\n, \ntrue\n or \nfalse\n. (The allowed boolean values are currently hardwired in Django's \nNullBooleanSelect implementation\n.)\n\n\ndjango-filter\n supports filtering across relationships, using Django's double-underscore syntax.\n\n\n\n\n\n\nSearchFilter\n\n\nThe \nSearchFilter\n class supports simple single query parameter based searching, and is based on the \nDjango admin's search functionality\n.\n\n\nWhen in use, the browsable API will include a \nSearchFilter\n control:\n\n\n\n\nThe \nSearchFilter\n class will only be applied if the view has a \nsearch_fields\n attribute set. The \nsearch_fields\n attribute should be a list of names of text type fields on the model, such as \nCharField\n or \nTextField\n.\n\n\nclass UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (filters.SearchFilter,)\n search_fields = ('username', 'email')\n\n\n\nThis will allow the client to filter the items in the list by making queries such as:\n\n\nhttp://example.com/api/users?search=russell\n\n\n\nYou can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation:\n\n\nsearch_fields = ('username', 'email', 'profile__profession')\n\n\n\nBy default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched.\n\n\nThe search behavior may be restricted by prepending various characters to the \nsearch_fields\n.\n\n\n\n\n'^' Starts-with search.\n\n\n'=' Exact matches.\n\n\n'@' Full-text search. (Currently only supported Django's MySQL backend.)\n\n\n'$' Regex search.\n\n\n\n\nFor example:\n\n\nsearch_fields = ('=username', '=email')\n\n\n\nBy default, the search parameter is named \n'search\n', but this may be overridden with the \nSEARCH_PARAM\n setting.\n\n\nFor more details, see the \nDjango documentation\n.\n\n\n\n\nOrderingFilter\n\n\nThe \nOrderingFilter\n class supports simple query parameter controlled ordering of results.\n\n\n\n\nBy default, the query parameter is named \n'ordering'\n, but this may by overridden with the \nORDERING_PARAM\n setting.\n\n\nFor example, to order users by username:\n\n\nhttp://example.com/api/users?ordering=username\n\n\n\nThe client may also specify reverse orderings by prefixing the field name with '-', like so:\n\n\nhttp://example.com/api/users?ordering=-username\n\n\n\nMultiple orderings may also be specified:\n\n\nhttp://example.com/api/users?ordering=account,username\n\n\n\nSpecifying which fields may be ordered against\n\n\nIt's recommended that you explicitly specify which fields the API should allowing in the ordering filter. You can do this by setting an \nordering_fields\n attribute on the view, like so:\n\n\nclass UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (filters.OrderingFilter,)\n ordering_fields = ('username', 'email')\n\n\n\nThis helps prevent unexpected data leakage, such as allowing users to order against a password hash field or other sensitive data.\n\n\nIf you \ndon't\n specify an \nordering_fields\n attribute on the view, the filter class will default to allowing the user to filter on any readable fields on the serializer specified by the \nserializer_class\n attribute.\n\n\nIf you are confident that the queryset being used by the view doesn't contain any sensitive data, you can also explicitly specify that a view should allow ordering on \nany\n model field or queryset aggregate, by using the special value \n'__all__'\n.\n\n\nclass BookingsListView(generics.ListAPIView):\n queryset = Booking.objects.all()\n serializer_class = BookingSerializer\n filter_backends = (filters.OrderingFilter,)\n ordering_fields = '__all__'\n\n\n\nSpecifying a default ordering\n\n\nIf an \nordering\n attribute is set on the view, this will be used as the default ordering.\n\n\nTypically you'd instead control this by setting \norder_by\n on the initial queryset, but using the \nordering\n parameter on the view allows you to specify the ordering in a way that it can then be passed automatically as context to a rendered template. This makes it possible to automatically render column headers differently if they are being used to order the results.\n\n\nclass UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (filters.OrderingFilter,)\n ordering_fields = ('username', 'email')\n ordering = ('username',)\n\n\n\nThe \nordering\n attribute may be either a string or a list/tuple of strings.\n\n\n\n\nDjangoObjectPermissionsFilter\n\n\nThe \nDjangoObjectPermissionsFilter\n is intended to be used together with the \ndjango-guardian\n package, with custom \n'view'\n permissions added. The filter will ensure that querysets only returns objects for which the user has the appropriate view permission.\n\n\nIf you're using \nDjangoObjectPermissionsFilter\n, you'll probably also want to add an appropriate object permissions class, to ensure that users can only operate on instances if they have the appropriate object permissions. The easiest way to do this is to subclass \nDjangoObjectPermissions\n and add \n'view'\n permissions to the \nperms_map\n attribute.\n\n\nA complete example using both \nDjangoObjectPermissionsFilter\n and \nDjangoObjectPermissions\n might look something like this.\n\n\npermissions.py\n:\n\n\nclass CustomObjectPermissions(permissions.DjangoObjectPermissions):\n \"\"\"\n Similar to `DjangoObjectPermissions`, but adding 'view' permissions.\n \"\"\"\n perms_map = {\n 'GET': ['%(app_label)s.view_%(model_name)s'],\n 'OPTIONS': ['%(app_label)s.view_%(model_name)s'],\n 'HEAD': ['%(app_label)s.view_%(model_name)s'],\n 'POST': ['%(app_label)s.add_%(model_name)s'],\n 'PUT': ['%(app_label)s.change_%(model_name)s'],\n 'PATCH': ['%(app_label)s.change_%(model_name)s'],\n 'DELETE': ['%(app_label)s.delete_%(model_name)s'],\n }\n\n\n\nviews.py\n:\n\n\nclass EventViewSet(viewsets.ModelViewSet):\n \"\"\"\n Viewset that only lists events if user has 'view' permissions, and only\n allows operations on individual events if user has appropriate 'view', 'add',\n 'change' or 'delete' permissions.\n \"\"\"\n queryset = Event.objects.all()\n serializer_class = EventSerializer\n filter_backends = (filters.DjangoObjectPermissionsFilter,)\n permission_classes = (myapp.permissions.CustomObjectPermissions,)\n\n\n\nFor more information on adding \n'view'\n permissions for models, see the \nrelevant section\n of the \ndjango-guardian\n documentation, and \nthis blogpost\n.\n\n\n\n\nCustom generic filtering\n\n\nYou can also provide your own generic filtering backend, or write an installable app for other developers to use.\n\n\nTo do so override \nBaseFilterBackend\n, and override the \n.filter_queryset(self, request, queryset, view)\n method. The method should return a new, filtered queryset.\n\n\nAs well as allowing clients to perform searches and filtering, generic filter backends can be useful for restricting which objects should be visible to any given request or user.\n\n\nExample\n\n\nFor example, you might need to restrict users to only being able to see objects they created.\n\n\nclass IsOwnerFilterBackend(filters.BaseFilterBackend):\n \"\"\"\n Filter that only allows users to see their own objects.\n \"\"\"\n def filter_queryset(self, request, queryset, view):\n return queryset.filter(owner=request.user)\n\n\n\nWe could achieve the same behavior by overriding \nget_queryset()\n on the views, but using a filter backend allows you to more easily add this restriction to multiple views, or to apply it across the entire API.\n\n\nCustomizing the interface\n\n\nGeneric filters may also present an interface in the browsable API. To do so you should implement a \nto_html()\n method which returns a rendered HTML representation of the filter. This method should have the following signature:\n\n\nto_html(self, request, queryset, view)\n\n\nThe method should return a rendered HTML string.\n\n\nPagination \n schemas\n\n\nYou can also make the filter controls available to the schema autogeneration\nthat REST framework provides, by implementing a \nget_schema_fields()\n method,\nwhich should return a list of \ncoreapi.Field\n instances.\n\n\nThird party packages\n\n\nThe following third party packages provide additional filter implementations.\n\n\nDjango REST framework filters package\n\n\nThe \ndjango-rest-framework-filters package\n works together with the \nDjangoFilterBackend\n class, and allows you to easily create filters across relationships, or create multiple filter lookup types for a given field.\n\n\nDjango REST framework full word search filter\n\n\nThe \ndjangorestframework-word-filter\n developed as alternative to \nfilters.SearchFilter\n which will search full word in text, or exact match.\n\n\nDjango URL Filter\n\n\ndjango-url-filter\n provides a safe way to filter data via human-friendly URLs. It works very similar to DRF serializers and fields in a sense that they can be nested except they are called filtersets and filters. That provides easy way to filter related data. Also this library is generic-purpose so it can be used to filter other sources of data and not only Django \nQuerySet\ns.\n\n\ndrf-url-filters\n\n\ndrf-url-filter\n is a simple Django app to apply filters on drf \nModelViewSet\n's \nQueryset\n in a clean, simple and configurable way. It also supports validations on incoming query params and their values. A beautiful python package \nVoluptuous\n is being used for validations on the incoming query parameters. The best part about voluptuous is you can define your own validations as per your query params requirements.",
+ "text": "Filtering\n\n\n\n\nThe root QuerySet provided by the Manager describes all objects in the database table. Usually, though, you'll need to select only a subset of the complete set of objects.\n\n\n \nDjango documentation\n\n\n\n\nThe default behavior of REST framework's generic list views is to return the entire queryset for a model manager. Often you will want your API to restrict the items that are returned by the queryset.\n\n\nThe simplest way to filter the queryset of any view that subclasses \nGenericAPIView\n is to override the \n.get_queryset()\n method.\n\n\nOverriding this method allows you to customize the queryset returned by the view in a number of different ways.\n\n\nFiltering against the current user\n\n\nYou might want to filter the queryset to ensure that only results relevant to the currently authenticated user making the request are returned.\n\n\nYou can do so by filtering based on the value of \nrequest.user\n.\n\n\nFor example:\n\n\nfrom myapp.models import Purchase\nfrom myapp.serializers import PurchaseSerializer\nfrom rest_framework import generics\n\nclass PurchaseList(generics.ListAPIView):\n serializer_class = PurchaseSerializer\n\n def get_queryset(self):\n \"\"\"\n This view should return a list of all the purchases\n for the currently authenticated user.\n \"\"\"\n user = self.request.user\n return Purchase.objects.filter(purchaser=user)\n\n\n\nFiltering against the URL\n\n\nAnother style of filtering might involve restricting the queryset based on some part of the URL.\n\n\nFor example if your URL config contained an entry like this:\n\n\nurl('^purchases/(?P\nusername\n.+)/$', PurchaseList.as_view()),\n\n\n\nYou could then write a view that returned a purchase queryset filtered by the username portion of the URL:\n\n\nclass PurchaseList(generics.ListAPIView):\n serializer_class = PurchaseSerializer\n\n def get_queryset(self):\n \"\"\"\n This view should return a list of all the purchases for\n the user as determined by the username portion of the URL.\n \"\"\"\n username = self.kwargs['username']\n return Purchase.objects.filter(purchaser__username=username)\n\n\n\nFiltering against query parameters\n\n\nA final example of filtering the initial queryset would be to determine the initial queryset based on query parameters in the url.\n\n\nWe can override \n.get_queryset()\n to deal with URLs such as \nhttp://example.com/api/purchases?username=denvercoder9\n, and filter the queryset only if the \nusername\n parameter is included in the URL:\n\n\nclass PurchaseList(generics.ListAPIView):\n serializer_class = PurchaseSerializer\n\n def get_queryset(self):\n \"\"\"\n Optionally restricts the returned purchases to a given user,\n by filtering against a `username` query parameter in the URL.\n \"\"\"\n queryset = Purchase.objects.all()\n username = self.request.query_params.get('username', None)\n if username is not None:\n queryset = queryset.filter(purchaser__username=username)\n return queryset\n\n\n\n\n\nGeneric Filtering\n\n\nAs well as being able to override the default queryset, REST framework also includes support for generic filtering backends that allow you to easily construct complex searches and filters.\n\n\nGeneric filters can also present themselves as HTML controls in the browsable API and admin API.\n\n\n\n\nSetting filter backends\n\n\nThe default filter backends may be set globally, using the \nDEFAULT_FILTER_BACKENDS\n setting. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)\n}\n\n\n\nYou can also set the filter backends on a per-view, or per-viewset basis,\nusing the \nGenericAPIView\n class-based views.\n\n\nimport django_filters.rest_framework\nfrom django.contrib.auth.models import User\nfrom myapp.serializers import UserSerializer\nfrom rest_framework import generics\n\nclass UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)\n\n\n\nFiltering and object lookups\n\n\nNote that if a filter backend is configured for a view, then as well as being used to filter list views, it will also be used to filter the querysets used for returning a single object.\n\n\nFor instance, given the previous example, and a product with an id of \n4675\n, the following URL would either return the corresponding object, or return a 404 response, depending on if the filtering conditions were met by the given product instance:\n\n\nhttp://example.com/api/products/4675/?category=clothing\nmax_price=10.00\n\n\n\nOverriding the initial queryset\n\n\nNote that you can use both an overridden \n.get_queryset()\n and generic filtering together, and everything will work as expected. For example, if \nProduct\n had a many-to-many relationship with \nUser\n, named \npurchase\n, you might want to write a view like this:\n\n\nclass PurchasedProductsList(generics.ListAPIView):\n \"\"\"\n Return a list of all the products that the authenticated\n user has ever purchased, with optional filtering.\n \"\"\"\n model = Product\n serializer_class = ProductSerializer\n filter_class = ProductFilter\n\n def get_queryset(self):\n user = self.request.user\n return user.purchase_set.all()\n\n\n\n\n\nAPI Guide\n\n\nDjangoFilterBackend\n\n\nThe \ndjango-filter\n library includes a \nDjangoFilterBackend\n class which\nsupports highly customizable field filtering for REST framework.\n\n\nTo use \nDjangoFilterBackend\n, first install \ndjango-filter\n. Then add \ndjango_filters\n to Django's \nINSTALLED_APPS\n\n\npip install django-filter\n\n\n\nYou should now either add the filter backend to your settings:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)\n}\n\n\n\nOr add the filter backend to an individual View or ViewSet.\n\n\nfrom django_filters.rest_framework import DjangoFilterBackend\n\nclass UserListView(generics.ListAPIView):\n ...\n filter_backends = (DjangoFilterBackend,)\n\n\n\nIf all you need is simple equality-based filtering, you can set a \nfilter_fields\n attribute on the view, or viewset, listing the set of fields you wish to filter against.\n\n\nclass ProductList(generics.ListAPIView):\n queryset = Product.objects.all()\n serializer_class = ProductSerializer\n filter_backends = (filters.DjangoFilterBackend,)\n filter_fields = ('category', 'in_stock')\n\n\n\nThis will automatically create a \nFilterSet\n class for the given fields, and will allow you to make requests such as:\n\n\nhttp://example.com/api/products?category=clothing\nin_stock=True\n\n\n\nFor more advanced filtering requirements you can specify a \nFilterSet\n class that should be used by the view.\nYou can read more about \nFilterSet\ns in the \ndjango-filter documentation\n.\nIt's also recommended that you read the section on \nDRF integration\n.\n\n\nSearchFilter\n\n\nThe \nSearchFilter\n class supports simple single query parameter based searching, and is based on the \nDjango admin's search functionality\n.\n\n\nWhen in use, the browsable API will include a \nSearchFilter\n control:\n\n\n\n\nThe \nSearchFilter\n class will only be applied if the view has a \nsearch_fields\n attribute set. The \nsearch_fields\n attribute should be a list of names of text type fields on the model, such as \nCharField\n or \nTextField\n.\n\n\nclass UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (filters.SearchFilter,)\n search_fields = ('username', 'email')\n\n\n\nThis will allow the client to filter the items in the list by making queries such as:\n\n\nhttp://example.com/api/users?search=russell\n\n\n\nYou can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation:\n\n\nsearch_fields = ('username', 'email', 'profile__profession')\n\n\n\nBy default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched.\n\n\nThe search behavior may be restricted by prepending various characters to the \nsearch_fields\n.\n\n\n\n\n'^' Starts-with search.\n\n\n'=' Exact matches.\n\n\n'@' Full-text search. (Currently only supported Django's MySQL backend.)\n\n\n'$' Regex search.\n\n\n\n\nFor example:\n\n\nsearch_fields = ('=username', '=email')\n\n\n\nBy default, the search parameter is named \n'search\n', but this may be overridden with the \nSEARCH_PARAM\n setting.\n\n\nFor more details, see the \nDjango documentation\n.\n\n\n\n\nOrderingFilter\n\n\nThe \nOrderingFilter\n class supports simple query parameter controlled ordering of results.\n\n\n\n\nBy default, the query parameter is named \n'ordering'\n, but this may by overridden with the \nORDERING_PARAM\n setting.\n\n\nFor example, to order users by username:\n\n\nhttp://example.com/api/users?ordering=username\n\n\n\nThe client may also specify reverse orderings by prefixing the field name with '-', like so:\n\n\nhttp://example.com/api/users?ordering=-username\n\n\n\nMultiple orderings may also be specified:\n\n\nhttp://example.com/api/users?ordering=account,username\n\n\n\nSpecifying which fields may be ordered against\n\n\nIt's recommended that you explicitly specify which fields the API should allowing in the ordering filter. You can do this by setting an \nordering_fields\n attribute on the view, like so:\n\n\nclass UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (filters.OrderingFilter,)\n ordering_fields = ('username', 'email')\n\n\n\nThis helps prevent unexpected data leakage, such as allowing users to order against a password hash field or other sensitive data.\n\n\nIf you \ndon't\n specify an \nordering_fields\n attribute on the view, the filter class will default to allowing the user to filter on any readable fields on the serializer specified by the \nserializer_class\n attribute.\n\n\nIf you are confident that the queryset being used by the view doesn't contain any sensitive data, you can also explicitly specify that a view should allow ordering on \nany\n model field or queryset aggregate, by using the special value \n'__all__'\n.\n\n\nclass BookingsListView(generics.ListAPIView):\n queryset = Booking.objects.all()\n serializer_class = BookingSerializer\n filter_backends = (filters.OrderingFilter,)\n ordering_fields = '__all__'\n\n\n\nSpecifying a default ordering\n\n\nIf an \nordering\n attribute is set on the view, this will be used as the default ordering.\n\n\nTypically you'd instead control this by setting \norder_by\n on the initial queryset, but using the \nordering\n parameter on the view allows you to specify the ordering in a way that it can then be passed automatically as context to a rendered template. This makes it possible to automatically render column headers differently if they are being used to order the results.\n\n\nclass UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (filters.OrderingFilter,)\n ordering_fields = ('username', 'email')\n ordering = ('username',)\n\n\n\nThe \nordering\n attribute may be either a string or a list/tuple of strings.\n\n\n\n\nDjangoObjectPermissionsFilter\n\n\nThe \nDjangoObjectPermissionsFilter\n is intended to be used together with the \ndjango-guardian\n package, with custom \n'view'\n permissions added. The filter will ensure that querysets only returns objects for which the user has the appropriate view permission.\n\n\nIf you're using \nDjangoObjectPermissionsFilter\n, you'll probably also want to add an appropriate object permissions class, to ensure that users can only operate on instances if they have the appropriate object permissions. The easiest way to do this is to subclass \nDjangoObjectPermissions\n and add \n'view'\n permissions to the \nperms_map\n attribute.\n\n\nA complete example using both \nDjangoObjectPermissionsFilter\n and \nDjangoObjectPermissions\n might look something like this.\n\n\npermissions.py\n:\n\n\nclass CustomObjectPermissions(permissions.DjangoObjectPermissions):\n \"\"\"\n Similar to `DjangoObjectPermissions`, but adding 'view' permissions.\n \"\"\"\n perms_map = {\n 'GET': ['%(app_label)s.view_%(model_name)s'],\n 'OPTIONS': ['%(app_label)s.view_%(model_name)s'],\n 'HEAD': ['%(app_label)s.view_%(model_name)s'],\n 'POST': ['%(app_label)s.add_%(model_name)s'],\n 'PUT': ['%(app_label)s.change_%(model_name)s'],\n 'PATCH': ['%(app_label)s.change_%(model_name)s'],\n 'DELETE': ['%(app_label)s.delete_%(model_name)s'],\n }\n\n\n\nviews.py\n:\n\n\nclass EventViewSet(viewsets.ModelViewSet):\n \"\"\"\n Viewset that only lists events if user has 'view' permissions, and only\n allows operations on individual events if user has appropriate 'view', 'add',\n 'change' or 'delete' permissions.\n \"\"\"\n queryset = Event.objects.all()\n serializer_class = EventSerializer\n filter_backends = (filters.DjangoObjectPermissionsFilter,)\n permission_classes = (myapp.permissions.CustomObjectPermissions,)\n\n\n\nFor more information on adding \n'view'\n permissions for models, see the \nrelevant section\n of the \ndjango-guardian\n documentation, and \nthis blogpost\n.\n\n\n\n\nCustom generic filtering\n\n\nYou can also provide your own generic filtering backend, or write an installable app for other developers to use.\n\n\nTo do so override \nBaseFilterBackend\n, and override the \n.filter_queryset(self, request, queryset, view)\n method. The method should return a new, filtered queryset.\n\n\nAs well as allowing clients to perform searches and filtering, generic filter backends can be useful for restricting which objects should be visible to any given request or user.\n\n\nExample\n\n\nFor example, you might need to restrict users to only being able to see objects they created.\n\n\nclass IsOwnerFilterBackend(filters.BaseFilterBackend):\n \"\"\"\n Filter that only allows users to see their own objects.\n \"\"\"\n def filter_queryset(self, request, queryset, view):\n return queryset.filter(owner=request.user)\n\n\n\nWe could achieve the same behavior by overriding \nget_queryset()\n on the views, but using a filter backend allows you to more easily add this restriction to multiple views, or to apply it across the entire API.\n\n\nCustomizing the interface\n\n\nGeneric filters may also present an interface in the browsable API. To do so you should implement a \nto_html()\n method which returns a rendered HTML representation of the filter. This method should have the following signature:\n\n\nto_html(self, request, queryset, view)\n\n\nThe method should return a rendered HTML string.\n\n\nPagination \n schemas\n\n\nYou can also make the filter controls available to the schema autogeneration\nthat REST framework provides, by implementing a \nget_schema_fields()\n method. This method should have the following signature:\n\n\nget_schema_fields(self, view)\n\n\nThe method should return a list of \ncoreapi.Field\n instances.\n\n\nThird party packages\n\n\nThe following third party packages provide additional filter implementations.\n\n\nDjango REST framework filters package\n\n\nThe \ndjango-rest-framework-filters package\n works together with the \nDjangoFilterBackend\n class, and allows you to easily create filters across relationships, or create multiple filter lookup types for a given field.\n\n\nDjango REST framework full word search filter\n\n\nThe \ndjangorestframework-word-filter\n developed as alternative to \nfilters.SearchFilter\n which will search full word in text, or exact match.\n\n\nDjango URL Filter\n\n\ndjango-url-filter\n provides a safe way to filter data via human-friendly URLs. It works very similar to DRF serializers and fields in a sense that they can be nested except they are called filtersets and filters. That provides easy way to filter related data. Also this library is generic-purpose so it can be used to filter other sources of data and not only Django \nQuerySet\ns.\n\n\ndrf-url-filters\n\n\ndrf-url-filter\n is a simple Django app to apply filters on drf \nModelViewSet\n's \nQueryset\n in a clean, simple and configurable way. It also supports validations on incoming query params and their values. A beautiful python package \nVoluptuous\n is being used for validations on the incoming query parameters. The best part about voluptuous is you can define your own validations as per your query params requirements.",
"title": "Filtering"
},
{
@@ -2692,19 +2697,9 @@
},
{
"location": "/api-guide/filtering/#djangofilterbackend",
- "text": "The django-filter library includes a DjangoFilterBackend class which\nsupports highly customizable field filtering for REST framework. To use DjangoFilterBackend , first install django-filter . pip install django-filter You should now either add the filter backend to your settings: REST_FRAMEWORK = {\n 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)\n} Or add the filter backend to an individual View or ViewSet. from django_filters.rest_framework import DjangoFilterBackend\n\nclass UserListView(generics.ListAPIView):\n ...\n filter_backends = (DjangoFilterBackend,) If you are using the browsable API or admin API you may also want to install django-crispy-forms , which will enhance the presentation of the filter forms in HTML views, by allowing them to render Bootstrap 3 HTML. pip install django-crispy-forms With crispy forms installed and added to Django's INSTALLED_APPS , the browsable API will present a filtering control for DjangoFilterBackend , like so:",
+ "text": "The django-filter library includes a DjangoFilterBackend class which\nsupports highly customizable field filtering for REST framework. To use DjangoFilterBackend , first install django-filter . Then add django_filters to Django's INSTALLED_APPS pip install django-filter You should now either add the filter backend to your settings: REST_FRAMEWORK = {\n 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)\n} Or add the filter backend to an individual View or ViewSet. from django_filters.rest_framework import DjangoFilterBackend\n\nclass UserListView(generics.ListAPIView):\n ...\n filter_backends = (DjangoFilterBackend,) If all you need is simple equality-based filtering, you can set a filter_fields attribute on the view, or viewset, listing the set of fields you wish to filter against. class ProductList(generics.ListAPIView):\n queryset = Product.objects.all()\n serializer_class = ProductSerializer\n filter_backends = (filters.DjangoFilterBackend,)\n filter_fields = ('category', 'in_stock') This will automatically create a FilterSet class for the given fields, and will allow you to make requests such as: http://example.com/api/products?category=clothing in_stock=True For more advanced filtering requirements you can specify a FilterSet class that should be used by the view.\nYou can read more about FilterSet s in the django-filter documentation .\nIt's also recommended that you read the section on DRF integration .",
"title": "DjangoFilterBackend"
},
- {
- "location": "/api-guide/filtering/#specifying-filter-fields",
- "text": "If all you need is simple equality-based filtering, you can set a filter_fields attribute on the view, or viewset, listing the set of fields you wish to filter against. class ProductList(generics.ListAPIView):\n queryset = Product.objects.all()\n serializer_class = ProductSerializer\n filter_backends = (filters.DjangoFilterBackend,)\n filter_fields = ('category', 'in_stock') This will automatically create a FilterSet class for the given fields, and will allow you to make requests such as: http://example.com/api/products?category=clothing in_stock=True",
- "title": "Specifying filter fields"
- },
- {
- "location": "/api-guide/filtering/#specifying-a-filterset",
- "text": "For more advanced filtering requirements you can specify a FilterSet class that should be used by the view. For example: import django_filters\nfrom myapp.models import Product\nfrom myapp.serializers import ProductSerializer\nfrom rest_framework import generics\n\nclass ProductFilter(django_filters.rest_framework.FilterSet):\n min_price = django_filters.NumberFilter(name=\"price\", lookup_expr='gte')\n max_price = django_filters.NumberFilter(name=\"price\", lookup_expr='lte')\n class Meta:\n model = Product\n fields = ['category', 'in_stock', 'min_price', 'max_price']\n\nclass ProductList(generics.ListAPIView):\n queryset = Product.objects.all()\n serializer_class = ProductSerializer\n filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)\n filter_class = ProductFilter Which will allow you to make requests such as: http://example.com/api/products?category=clothing max_price=10.00 You can also span relationships using django-filter , let's assume that each\nproduct has foreign key to Manufacturer model, so we create filter that\nfilters using Manufacturer name. For example: import django_filters\nfrom myapp.models import Product\nfrom myapp.serializers import ProductSerializer\nfrom rest_framework import generics\n\nclass ProductFilter(django_filters.rest_framework.FilterSet):\n class Meta:\n model = Product\n fields = ['category', 'in_stock', 'manufacturer__name'] This enables us to make queries like: http://example.com/api/products?manufacturer__name=foo This is nice, but it exposes the Django's double underscore convention as part of the API. If you instead want to explicitly name the filter argument you can instead explicitly include it on the FilterSet class: import django_filters\nfrom myapp.models import Product\nfrom myapp.serializers import ProductSerializer\nfrom rest_framework import generics\n\nclass ProductFilter(django_filters.rest_framework.FilterSet):\n manufacturer = django_filters.CharFilter(name=\"manufacturer__name\")\n\n class Meta:\n model = Product\n fields = ['category', 'in_stock', 'manufacturer'] And now you can execute: http://example.com/api/products?manufacturer=foo For more details on using filter sets see the django-filter documentation . Hints Tips By default filtering is not enabled. If you want to use DjangoFilterBackend remember to make sure it is installed by using the 'DEFAULT_FILTER_BACKENDS' setting. When using boolean fields, you should use the values True and False in the URL query parameters, rather than 0 , 1 , true or false . (The allowed boolean values are currently hardwired in Django's NullBooleanSelect implementation .) django-filter supports filtering across relationships, using Django's double-underscore syntax.",
- "title": "Specifying a FilterSet"
- },
{
"location": "/api-guide/filtering/#searchfilter",
"text": "The SearchFilter class supports simple single query parameter based searching, and is based on the Django admin's search functionality . When in use, the browsable API will include a SearchFilter control: The SearchFilter class will only be applied if the view has a search_fields attribute set. The search_fields attribute should be a list of names of text type fields on the model, such as CharField or TextField . class UserListView(generics.ListAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n filter_backends = (filters.SearchFilter,)\n search_fields = ('username', 'email') This will allow the client to filter the items in the list by making queries such as: http://example.com/api/users?search=russell You can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation: search_fields = ('username', 'email', 'profile__profession') By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched. The search behavior may be restricted by prepending various characters to the search_fields . '^' Starts-with search. '=' Exact matches. '@' Full-text search. (Currently only supported Django's MySQL backend.) '$' Regex search. For example: search_fields = ('=username', '=email') By default, the search parameter is named 'search ', but this may be overridden with the SEARCH_PARAM setting. For more details, see the Django documentation .",
@@ -2747,7 +2742,7 @@
},
{
"location": "/api-guide/filtering/#pagination-schemas",
- "text": "You can also make the filter controls available to the schema autogeneration\nthat REST framework provides, by implementing a get_schema_fields() method,\nwhich should return a list of coreapi.Field instances.",
+ "text": "You can also make the filter controls available to the schema autogeneration\nthat REST framework provides, by implementing a get_schema_fields() method. This method should have the following signature: get_schema_fields(self, view) The method should return a list of coreapi.Field instances.",
"title": "Pagination & schemas"
},
{
@@ -2777,7 +2772,7 @@
},
{
"location": "/api-guide/pagination/",
- "text": "Pagination\n\n\n\n\nDjango provides a few classes that help you manage paginated data \u2013 that is, data that\u2019s split across several pages, with \u201cPrevious/Next\u201d links.\n\n\n \nDjango documentation\n\n\n\n\nREST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.\n\n\nThe pagination API can support either:\n\n\n\n\nPagination links that are provided as part of the content of the response.\n\n\nPagination links that are included in response headers, such as \nContent-Range\n or \nLink\n.\n\n\n\n\nThe built-in styles currently all use links included as part of the content of the response. This style is more accessible when using the browsable API.\n\n\nPagination is only performed automatically if you're using the generic views or viewsets. If you're using a regular \nAPIView\n, you'll need to call into the pagination API yourself to ensure you return a paginated response. See the source code for the \nmixins.ListModelMixin\n and \ngenerics.GenericAPIView\n classes for an example.\n\n\nPagination can be turned off by setting the pagination class to \nNone\n.\n\n\nSetting the pagination style\n\n\nThe default pagination style may be set globally, using the \nDEFAULT_PAGINATION_CLASS\n and \nPAGE_SIZE\n setting keys. For example, to use the built-in limit/offset pagination, you would do something like this:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nNote that you need to set both the pagination class, and the page size that should be used.\n\n\nYou can also set the pagination class on an individual view by using the \npagination_class\n attribute. Typically you'll want to use the same pagination style throughout your API, although you might want to vary individual aspects of the pagination, such as default or maximum page size, on a per-view basis.\n\n\nModifying the pagination style\n\n\nIf you want to modify particular aspects of the pagination style, you'll want to override one of the pagination classes, and set the attributes that you want to change.\n\n\nclass LargeResultsSetPagination(PageNumberPagination):\n page_size = 1000\n page_size_query_param = 'page_size'\n max_page_size = 10000\n\nclass StandardResultsSetPagination(PageNumberPagination):\n page_size = 100\n page_size_query_param = 'page_size'\n max_page_size = 1000\n\n\n\nYou can then apply your new style to a view using the \n.pagination_class\n attribute:\n\n\nclass BillingRecordsView(generics.ListAPIView):\n queryset = Billing.objects.all()\n serializer_class = BillingRecordsSerializer\n pagination_class = LargeResultsSetPagination\n\n\n\nOr apply the style globally, using the \nDEFAULT_PAGINATION_CLASS\n settings key. For example:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'\n}\n\n\n\n\n\nAPI Reference\n\n\nPageNumberPagination\n\n\nThis pagination style accepts a single number page number in the request query parameters.\n\n\nRequest\n:\n\n\nGET https://api.example.org/accounts/?page=4\n\n\n\nResponse\n:\n\n\nHTTP 200 OK\n{\n \"count\": 1023\n \"next\": \"https://api.example.org/accounts/?page=5\",\n \"previous\": \"https://api.example.org/accounts/?page=3\",\n \"results\": [\n \u2026\n ]\n}\n\n\n\nSetup\n\n\nTo enable the \nPageNumberPagination\n style globally, use the following configuration, modifying the \nPAGE_SIZE\n as desired:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nOn \nGenericAPIView\n subclasses you may also set the \npagination_class\n attribute to select \nPageNumberPagination\n on a per-view basis.\n\n\nConfiguration\n\n\nThe \nPageNumberPagination\n class includes a number of attributes that may be overridden to modify the pagination style.\n\n\nTo set these attributes you should override the \nPageNumberPagination\n class, and then enable your custom pagination class as above.\n\n\n\n\ndjango_paginator_class\n - The Django Paginator class to use. Default is \ndjango.core.paginator.Paginator\n, which should be fine for most use cases.\n\n\npage_size\n - A numeric value indicating the page size. If set, this overrides the \nPAGE_SIZE\n setting. Defaults to the same value as the \nPAGE_SIZE\n settings key.\n\n\npage_query_param\n - A string value indicating the name of the query parameter to use for the pagination control.\n\n\npage_size_query_param\n - If set, this is a string value indicating the name of a query parameter that allows the client to set the page size on a per-request basis. Defaults to \nNone\n, indicating that the client may not control the requested page size.\n\n\nmax_page_size\n - If set, this is a numeric value indicating the maximum allowable requested page size. This attribute is only valid if \npage_size_query_param\n is also set.\n\n\nlast_page_strings\n - A list or tuple of string values indicating values that may be used with the \npage_query_param\n to request the final page in the set. Defaults to \n('last',)\n\n\ntemplate\n - The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to \nNone\n to disable HTML pagination controls completely. Defaults to \n\"rest_framework/pagination/numbers.html\"\n.\n\n\n\n\n\n\nLimitOffsetPagination\n\n\nThis pagination style mirrors the syntax used when looking up multiple database records. The client includes both a \"limit\" and an\n\"offset\" query parameter. The limit indicates the maximum number of items to return, and is equivalent to the \npage_size\n in other styles. The offset indicates the starting position of the query in relation to the complete set of unpaginated items.\n\n\nRequest\n:\n\n\nGET https://api.example.org/accounts/?limit=100\noffset=400\n\n\n\nResponse\n:\n\n\nHTTP 200 OK\n{\n \"count\": 1023\n \"next\": \"https://api.example.org/accounts/?limit=100\noffset=500\",\n \"previous\": \"https://api.example.org/accounts/?limit=100\noffset=300\",\n \"results\": [\n \u2026\n ]\n}\n\n\n\nSetup\n\n\nTo enable the \nLimitOffsetPagination\n style globally, use the following configuration:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'\n}\n\n\n\nOptionally, you may also set a \nPAGE_SIZE\n key. If the \nPAGE_SIZE\n parameter is also used then the \nlimit\n query parameter will be optional, and may be omitted by the client.\n\n\nOn \nGenericAPIView\n subclasses you may also set the \npagination_class\n attribute to select \nLimitOffsetPagination\n on a per-view basis.\n\n\nConfiguration\n\n\nThe \nLimitOffsetPagination\n class includes a number of attributes that may be overridden to modify the pagination style.\n\n\nTo set these attributes you should override the \nLimitOffsetPagination\n class, and then enable your custom pagination class as above.\n\n\n\n\ndefault_limit\n - A numeric value indicating the limit to use if one is not provided by the client in a query parameter. Defaults to the same value as the \nPAGE_SIZE\n settings key.\n\n\nlimit_query_param\n - A string value indicating the name of the \"limit\" query parameter. Defaults to \n'limit'\n.\n\n\noffset_query_param\n - A string value indicating the name of the \"offset\" query parameter. Defaults to \n'offset'\n.\n\n\nmax_limit\n - If set this is a numeric value indicating the maximum allowable limit that may be requested by the client. Defaults to \nNone\n.\n\n\ntemplate\n - The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to \nNone\n to disable HTML pagination controls completely. Defaults to \n\"rest_framework/pagination/numbers.html\"\n.\n\n\n\n\n\n\nCursorPagination\n\n\nThe cursor-based pagination presents an opaque \"cursor\" indicator that the client may use to page through the result set. This pagination style only presents forward and reverse controls, and does not allow the client to navigate to arbitrary positions.\n\n\nCursor based pagination requires that there is a unique, unchanging ordering of items in the result set. This ordering might typically be a creation timestamp on the records, as this presents a consistent ordering to paginate against.\n\n\nCursor based pagination is more complex than other schemes. It also requires that the result set presents a fixed ordering, and does not allow the client to arbitrarily index into the result set. However it does provide the following benefits:\n\n\n\n\nProvides a consistent pagination view. When used properly \nCursorPagination\n ensures that the client will never see the same item twice when paging through records, even when new items are being inserted by other clients during the pagination process.\n\n\nSupports usage with very large datasets. With extremely large datasets pagination using offset-based pagination styles may become inefficient or unusable. Cursor based pagination schemes instead have fixed-time properties, and do not slow down as the dataset size increases.\n\n\n\n\nDetails and limitations\n\n\nProper use of cursor based pagination requires a little attention to detail. You'll need to think about what ordering you want the scheme to be applied against. The default is to order by \n\"-created\"\n. This assumes that \nthere must be a 'created' timestamp field\n on the model instances, and will present a \"timeline\" style paginated view, with the most recently added items first.\n\n\nYou can modify the ordering by overriding the \n'ordering'\n attribute on the pagination class, or by using the \nOrderingFilter\n filter class together with \nCursorPagination\n. When used with \nOrderingFilter\n you should strongly consider restricting the fields that the user may order by.\n\n\nProper usage of cursor pagination should have an ordering field that satisfies the following:\n\n\n\n\nShould be an unchanging value, such as a timestamp, slug, or other field that is only set once, on creation.\n\n\nShould be unique, or nearly unique. Millisecond precision timestamps are a good example. This implementation of cursor pagination uses a smart \"position plus offset\" style that allows it to properly support not-strictly-unique values as the ordering.\n\n\nShould be a non-nullable value that can be coerced to a string.\n\n\nThe field should have a database index.\n\n\n\n\nUsing an ordering field that does not satisfy these constraints will generally still work, but you'll be losing some of the benefits of cursor pagination.\n\n\nFor more technical details on the implementation we use for cursor pagination, the \n\"Building cursors for the Disqus API\"\n blog post gives a good overview of the basic approach.\n\n\nSetup\n\n\nTo enable the \nCursorPagination\n style globally, use the following configuration, modifying the \nPAGE_SIZE\n as desired:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nOn \nGenericAPIView\n subclasses you may also set the \npagination_class\n attribute to select \nCursorPagination\n on a per-view basis.\n\n\nConfiguration\n\n\nThe \nCursorPagination\n class includes a number of attributes that may be overridden to modify the pagination style.\n\n\nTo set these attributes you should override the \nCursorPagination\n class, and then enable your custom pagination class as above.\n\n\n\n\npage_size\n = A numeric value indicating the page size. If set, this overrides the \nPAGE_SIZE\n setting. Defaults to the same value as the \nPAGE_SIZE\n settings key.\n\n\ncursor_query_param\n = A string value indicating the name of the \"cursor\" query parameter. Defaults to \n'cursor'\n.\n\n\nordering\n = This should be a string, or list of strings, indicating the field against which the cursor based pagination will be applied. For example: \nordering = 'slug'\n. Defaults to \n-created\n. This value may also be overridden by using \nOrderingFilter\n on the view.\n\n\ntemplate\n = The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to \nNone\n to disable HTML pagination controls completely. Defaults to \n\"rest_framework/pagination/previous_and_next.html\"\n.\n\n\n\n\n\n\nCustom pagination styles\n\n\nTo create a custom pagination serializer class you should subclass \npagination.BasePagination\n and override the \npaginate_queryset(self, queryset, request, view=None)\n and \nget_paginated_response(self, data)\n methods:\n\n\n\n\nThe \npaginate_queryset\n method is passed the initial queryset and should return an iterable object that contains only the data in the requested page.\n\n\nThe \nget_paginated_response\n method is passed the serialized page data and should return a \nResponse\n instance.\n\n\n\n\nNote that the \npaginate_queryset\n method may set state on the pagination instance, that may later be used by the \nget_paginated_response\n method.\n\n\nExample\n\n\nSuppose we want to replace the default pagination output style with a modified format that includes the next and previous links under in a nested 'links' key. We could specify a custom pagination class like so:\n\n\nclass CustomPagination(pagination.PageNumberPagination):\n def get_paginated_response(self, data):\n return Response({\n 'links': {\n 'next': self.get_next_link(),\n 'previous': self.get_previous_link()\n },\n 'count': self.page.paginator.count,\n 'results': data\n })\n\n\n\nWe'd then need to setup the custom class in our configuration:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nNote that if you care about how the ordering of keys is displayed in responses in the browsable API you might choose to use an \nOrderedDict\n when constructing the body of paginated responses, but this is optional.\n\n\nHeader based pagination\n\n\nLet's modify the built-in \nPageNumberPagination\n style, so that instead of include the pagination links in the body of the response, we'll instead include a \nLink\n header, in a \nsimilar style to the GitHub API\n.\n\n\nclass LinkHeaderPagination(pagination.PageNumberPagination):\n def get_paginated_response(self, data):\n next_url = self.get_next_link()\n previous_url = self.get_previous_link()\n\n if next_url is not None and previous_url is not None:\n link = '\n{next_url}\n; rel=\"next\", \n{previous_url}\n; rel=\"prev\"'\n elif next_url is not None:\n link = '\n{next_url}\n; rel=\"next\"'\n elif previous_url is not None:\n link = '\n{previous_url}\n; rel=\"prev\"'\n else:\n link = ''\n\n link = link.format(next_url=next_url, previous_url=previous_url)\n headers = {'Link': link} if link else {}\n\n return Response(data, headers=headers)\n\n\n\nUsing your custom pagination class\n\n\nTo have your custom pagination class be used by default, use the \nDEFAULT_PAGINATION_CLASS\n setting:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.LinkHeaderPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nAPI responses for list endpoints will now include a \nLink\n header, instead of including the pagination links as part of the body of the response, for example:\n\n\nPagination \n schemas\n\n\nYou can also make the pagination controls available to the schema autogeneration\nthat REST framework provides, by implementing a \nget_schema_fields()\n method,\nwhich should return a list of \ncoreapi.Field\n instances.\n\n\n\n\n\n\nA custom pagination style, using the 'Link' header'\n\n\n\n\nHTML pagination controls\n\n\nBy default using the pagination classes will cause HTML pagination controls to be displayed in the browsable API. There are two built-in display styles. The \nPageNumberPagination\n and \nLimitOffsetPagination\n classes display a list of page numbers with previous and next controls. The \nCursorPagination\n class displays a simpler style that only displays a previous and next control.\n\n\nCustomizing the controls\n\n\nYou can override the templates that render the HTML pagination controls. The two built-in styles are:\n\n\n\n\nrest_framework/pagination/numbers.html\n\n\nrest_framework/pagination/previous_and_next.html\n\n\n\n\nProviding a template with either of these paths in a global template directory will override the default rendering for the relevant pagination classes.\n\n\nAlternatively you can disable HTML pagination controls completely by subclassing on of the existing classes, setting \ntemplate = None\n as an attribute on the class. You'll then need to configure your \nDEFAULT_PAGINATION_CLASS\n settings key to use your custom class as the default pagination style.\n\n\nLow-level API\n\n\nThe low-level API for determining if a pagination class should display the controls or not is exposed as a \ndisplay_page_controls\n attribute on the pagination instance. Custom pagination classes should be set to \nTrue\n in the \npaginate_queryset\n method if they require the HTML pagination controls to be displayed.\n\n\nThe \n.to_html()\n and \n.get_html_context()\n methods may also be overridden in a custom pagination class in order to further customize how the controls are rendered.\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nDRF-extensions\n\n\nThe \nDRF-extensions\n package\n includes a \nPaginateByMaxMixin\n mixin class\n that allows your API clients to specify \n?page_size=max\n to obtain the maximum allowed page size.\n\n\ndrf-proxy-pagination\n\n\nThe \ndrf-proxy-pagination\n package\n includes a \nProxyPagination\n class which allows to choose pagination class with a query parameter.",
+ "text": "Pagination\n\n\n\n\nDjango provides a few classes that help you manage paginated data \u2013 that is, data that\u2019s split across several pages, with \u201cPrevious/Next\u201d links.\n\n\n \nDjango documentation\n\n\n\n\nREST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.\n\n\nThe pagination API can support either:\n\n\n\n\nPagination links that are provided as part of the content of the response.\n\n\nPagination links that are included in response headers, such as \nContent-Range\n or \nLink\n.\n\n\n\n\nThe built-in styles currently all use links included as part of the content of the response. This style is more accessible when using the browsable API.\n\n\nPagination is only performed automatically if you're using the generic views or viewsets. If you're using a regular \nAPIView\n, you'll need to call into the pagination API yourself to ensure you return a paginated response. See the source code for the \nmixins.ListModelMixin\n and \ngenerics.GenericAPIView\n classes for an example.\n\n\nPagination can be turned off by setting the pagination class to \nNone\n.\n\n\nSetting the pagination style\n\n\nThe default pagination style may be set globally, using the \nDEFAULT_PAGINATION_CLASS\n and \nPAGE_SIZE\n setting keys. For example, to use the built-in limit/offset pagination, you would do something like this:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nNote that you need to set both the pagination class, and the page size that should be used.\n\n\nYou can also set the pagination class on an individual view by using the \npagination_class\n attribute. Typically you'll want to use the same pagination style throughout your API, although you might want to vary individual aspects of the pagination, such as default or maximum page size, on a per-view basis.\n\n\nModifying the pagination style\n\n\nIf you want to modify particular aspects of the pagination style, you'll want to override one of the pagination classes, and set the attributes that you want to change.\n\n\nclass LargeResultsSetPagination(PageNumberPagination):\n page_size = 1000\n page_size_query_param = 'page_size'\n max_page_size = 10000\n\nclass StandardResultsSetPagination(PageNumberPagination):\n page_size = 100\n page_size_query_param = 'page_size'\n max_page_size = 1000\n\n\n\nYou can then apply your new style to a view using the \n.pagination_class\n attribute:\n\n\nclass BillingRecordsView(generics.ListAPIView):\n queryset = Billing.objects.all()\n serializer_class = BillingRecordsSerializer\n pagination_class = LargeResultsSetPagination\n\n\n\nOr apply the style globally, using the \nDEFAULT_PAGINATION_CLASS\n settings key. For example:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'\n}\n\n\n\n\n\nAPI Reference\n\n\nPageNumberPagination\n\n\nThis pagination style accepts a single number page number in the request query parameters.\n\n\nRequest\n:\n\n\nGET https://api.example.org/accounts/?page=4\n\n\n\nResponse\n:\n\n\nHTTP 200 OK\n{\n \"count\": 1023\n \"next\": \"https://api.example.org/accounts/?page=5\",\n \"previous\": \"https://api.example.org/accounts/?page=3\",\n \"results\": [\n \u2026\n ]\n}\n\n\n\nSetup\n\n\nTo enable the \nPageNumberPagination\n style globally, use the following configuration, modifying the \nPAGE_SIZE\n as desired:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nOn \nGenericAPIView\n subclasses you may also set the \npagination_class\n attribute to select \nPageNumberPagination\n on a per-view basis.\n\n\nConfiguration\n\n\nThe \nPageNumberPagination\n class includes a number of attributes that may be overridden to modify the pagination style.\n\n\nTo set these attributes you should override the \nPageNumberPagination\n class, and then enable your custom pagination class as above.\n\n\n\n\ndjango_paginator_class\n - The Django Paginator class to use. Default is \ndjango.core.paginator.Paginator\n, which should be fine for most use cases.\n\n\npage_size\n - A numeric value indicating the page size. If set, this overrides the \nPAGE_SIZE\n setting. Defaults to the same value as the \nPAGE_SIZE\n settings key.\n\n\npage_query_param\n - A string value indicating the name of the query parameter to use for the pagination control.\n\n\npage_size_query_param\n - If set, this is a string value indicating the name of a query parameter that allows the client to set the page size on a per-request basis. Defaults to \nNone\n, indicating that the client may not control the requested page size.\n\n\nmax_page_size\n - If set, this is a numeric value indicating the maximum allowable requested page size. This attribute is only valid if \npage_size_query_param\n is also set.\n\n\nlast_page_strings\n - A list or tuple of string values indicating values that may be used with the \npage_query_param\n to request the final page in the set. Defaults to \n('last',)\n\n\ntemplate\n - The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to \nNone\n to disable HTML pagination controls completely. Defaults to \n\"rest_framework/pagination/numbers.html\"\n.\n\n\n\n\n\n\nLimitOffsetPagination\n\n\nThis pagination style mirrors the syntax used when looking up multiple database records. The client includes both a \"limit\" and an\n\"offset\" query parameter. The limit indicates the maximum number of items to return, and is equivalent to the \npage_size\n in other styles. The offset indicates the starting position of the query in relation to the complete set of unpaginated items.\n\n\nRequest\n:\n\n\nGET https://api.example.org/accounts/?limit=100\noffset=400\n\n\n\nResponse\n:\n\n\nHTTP 200 OK\n{\n \"count\": 1023\n \"next\": \"https://api.example.org/accounts/?limit=100\noffset=500\",\n \"previous\": \"https://api.example.org/accounts/?limit=100\noffset=300\",\n \"results\": [\n \u2026\n ]\n}\n\n\n\nSetup\n\n\nTo enable the \nLimitOffsetPagination\n style globally, use the following configuration:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'\n}\n\n\n\nOptionally, you may also set a \nPAGE_SIZE\n key. If the \nPAGE_SIZE\n parameter is also used then the \nlimit\n query parameter will be optional, and may be omitted by the client.\n\n\nOn \nGenericAPIView\n subclasses you may also set the \npagination_class\n attribute to select \nLimitOffsetPagination\n on a per-view basis.\n\n\nConfiguration\n\n\nThe \nLimitOffsetPagination\n class includes a number of attributes that may be overridden to modify the pagination style.\n\n\nTo set these attributes you should override the \nLimitOffsetPagination\n class, and then enable your custom pagination class as above.\n\n\n\n\ndefault_limit\n - A numeric value indicating the limit to use if one is not provided by the client in a query parameter. Defaults to the same value as the \nPAGE_SIZE\n settings key.\n\n\nlimit_query_param\n - A string value indicating the name of the \"limit\" query parameter. Defaults to \n'limit'\n.\n\n\noffset_query_param\n - A string value indicating the name of the \"offset\" query parameter. Defaults to \n'offset'\n.\n\n\nmax_limit\n - If set this is a numeric value indicating the maximum allowable limit that may be requested by the client. Defaults to \nNone\n.\n\n\ntemplate\n - The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to \nNone\n to disable HTML pagination controls completely. Defaults to \n\"rest_framework/pagination/numbers.html\"\n.\n\n\n\n\n\n\nCursorPagination\n\n\nThe cursor-based pagination presents an opaque \"cursor\" indicator that the client may use to page through the result set. This pagination style only presents forward and reverse controls, and does not allow the client to navigate to arbitrary positions.\n\n\nCursor based pagination requires that there is a unique, unchanging ordering of items in the result set. This ordering might typically be a creation timestamp on the records, as this presents a consistent ordering to paginate against.\n\n\nCursor based pagination is more complex than other schemes. It also requires that the result set presents a fixed ordering, and does not allow the client to arbitrarily index into the result set. However it does provide the following benefits:\n\n\n\n\nProvides a consistent pagination view. When used properly \nCursorPagination\n ensures that the client will never see the same item twice when paging through records, even when new items are being inserted by other clients during the pagination process.\n\n\nSupports usage with very large datasets. With extremely large datasets pagination using offset-based pagination styles may become inefficient or unusable. Cursor based pagination schemes instead have fixed-time properties, and do not slow down as the dataset size increases.\n\n\n\n\nDetails and limitations\n\n\nProper use of cursor based pagination requires a little attention to detail. You'll need to think about what ordering you want the scheme to be applied against. The default is to order by \n\"-created\"\n. This assumes that \nthere must be a 'created' timestamp field\n on the model instances, and will present a \"timeline\" style paginated view, with the most recently added items first.\n\n\nYou can modify the ordering by overriding the \n'ordering'\n attribute on the pagination class, or by using the \nOrderingFilter\n filter class together with \nCursorPagination\n. When used with \nOrderingFilter\n you should strongly consider restricting the fields that the user may order by.\n\n\nProper usage of cursor pagination should have an ordering field that satisfies the following:\n\n\n\n\nShould be an unchanging value, such as a timestamp, slug, or other field that is only set once, on creation.\n\n\nShould be unique, or nearly unique. Millisecond precision timestamps are a good example. This implementation of cursor pagination uses a smart \"position plus offset\" style that allows it to properly support not-strictly-unique values as the ordering.\n\n\nShould be a non-nullable value that can be coerced to a string.\n\n\nThe field should have a database index.\n\n\n\n\nUsing an ordering field that does not satisfy these constraints will generally still work, but you'll be losing some of the benefits of cursor pagination.\n\n\nFor more technical details on the implementation we use for cursor pagination, the \n\"Building cursors for the Disqus API\"\n blog post gives a good overview of the basic approach.\n\n\nSetup\n\n\nTo enable the \nCursorPagination\n style globally, use the following configuration, modifying the \nPAGE_SIZE\n as desired:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nOn \nGenericAPIView\n subclasses you may also set the \npagination_class\n attribute to select \nCursorPagination\n on a per-view basis.\n\n\nConfiguration\n\n\nThe \nCursorPagination\n class includes a number of attributes that may be overridden to modify the pagination style.\n\n\nTo set these attributes you should override the \nCursorPagination\n class, and then enable your custom pagination class as above.\n\n\n\n\npage_size\n = A numeric value indicating the page size. If set, this overrides the \nPAGE_SIZE\n setting. Defaults to the same value as the \nPAGE_SIZE\n settings key.\n\n\ncursor_query_param\n = A string value indicating the name of the \"cursor\" query parameter. Defaults to \n'cursor'\n.\n\n\nordering\n = This should be a string, or list of strings, indicating the field against which the cursor based pagination will be applied. For example: \nordering = 'slug'\n. Defaults to \n-created\n. This value may also be overridden by using \nOrderingFilter\n on the view.\n\n\ntemplate\n = The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to \nNone\n to disable HTML pagination controls completely. Defaults to \n\"rest_framework/pagination/previous_and_next.html\"\n.\n\n\n\n\n\n\nCustom pagination styles\n\n\nTo create a custom pagination serializer class you should subclass \npagination.BasePagination\n and override the \npaginate_queryset(self, queryset, request, view=None)\n and \nget_paginated_response(self, data)\n methods:\n\n\n\n\nThe \npaginate_queryset\n method is passed the initial queryset and should return an iterable object that contains only the data in the requested page.\n\n\nThe \nget_paginated_response\n method is passed the serialized page data and should return a \nResponse\n instance.\n\n\n\n\nNote that the \npaginate_queryset\n method may set state on the pagination instance, that may later be used by the \nget_paginated_response\n method.\n\n\nExample\n\n\nSuppose we want to replace the default pagination output style with a modified format that includes the next and previous links under in a nested 'links' key. We could specify a custom pagination class like so:\n\n\nclass CustomPagination(pagination.PageNumberPagination):\n def get_paginated_response(self, data):\n return Response({\n 'links': {\n 'next': self.get_next_link(),\n 'previous': self.get_previous_link()\n },\n 'count': self.page.paginator.count,\n 'results': data\n })\n\n\n\nWe'd then need to setup the custom class in our configuration:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nNote that if you care about how the ordering of keys is displayed in responses in the browsable API you might choose to use an \nOrderedDict\n when constructing the body of paginated responses, but this is optional.\n\n\nHeader based pagination\n\n\nLet's modify the built-in \nPageNumberPagination\n style, so that instead of include the pagination links in the body of the response, we'll instead include a \nLink\n header, in a \nsimilar style to the GitHub API\n.\n\n\nclass LinkHeaderPagination(pagination.PageNumberPagination):\n def get_paginated_response(self, data):\n next_url = self.get_next_link()\n previous_url = self.get_previous_link()\n\n if next_url is not None and previous_url is not None:\n link = '\n{next_url}\n; rel=\"next\", \n{previous_url}\n; rel=\"prev\"'\n elif next_url is not None:\n link = '\n{next_url}\n; rel=\"next\"'\n elif previous_url is not None:\n link = '\n{previous_url}\n; rel=\"prev\"'\n else:\n link = ''\n\n link = link.format(next_url=next_url, previous_url=previous_url)\n headers = {'Link': link} if link else {}\n\n return Response(data, headers=headers)\n\n\n\nUsing your custom pagination class\n\n\nTo have your custom pagination class be used by default, use the \nDEFAULT_PAGINATION_CLASS\n setting:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.LinkHeaderPagination',\n 'PAGE_SIZE': 100\n}\n\n\n\nAPI responses for list endpoints will now include a \nLink\n header, instead of including the pagination links as part of the body of the response, for example:\n\n\nPagination \n schemas\n\n\nYou can also make the pagination controls available to the schema autogeneration\nthat REST framework provides, by implementing a \nget_schema_fields()\n method. This method should have the following signature:\n\n\nget_schema_fields(self, view)\n\n\nThe method should return a list of \ncoreapi.Field\n instances.\n\n\n\n\n\n\nA custom pagination style, using the 'Link' header'\n\n\n\n\nHTML pagination controls\n\n\nBy default using the pagination classes will cause HTML pagination controls to be displayed in the browsable API. There are two built-in display styles. The \nPageNumberPagination\n and \nLimitOffsetPagination\n classes display a list of page numbers with previous and next controls. The \nCursorPagination\n class displays a simpler style that only displays a previous and next control.\n\n\nCustomizing the controls\n\n\nYou can override the templates that render the HTML pagination controls. The two built-in styles are:\n\n\n\n\nrest_framework/pagination/numbers.html\n\n\nrest_framework/pagination/previous_and_next.html\n\n\n\n\nProviding a template with either of these paths in a global template directory will override the default rendering for the relevant pagination classes.\n\n\nAlternatively you can disable HTML pagination controls completely by subclassing on of the existing classes, setting \ntemplate = None\n as an attribute on the class. You'll then need to configure your \nDEFAULT_PAGINATION_CLASS\n settings key to use your custom class as the default pagination style.\n\n\nLow-level API\n\n\nThe low-level API for determining if a pagination class should display the controls or not is exposed as a \ndisplay_page_controls\n attribute on the pagination instance. Custom pagination classes should be set to \nTrue\n in the \npaginate_queryset\n method if they require the HTML pagination controls to be displayed.\n\n\nThe \n.to_html()\n and \n.get_html_context()\n methods may also be overridden in a custom pagination class in order to further customize how the controls are rendered.\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nDRF-extensions\n\n\nThe \nDRF-extensions\n package\n includes a \nPaginateByMaxMixin\n mixin class\n that allows your API clients to specify \n?page_size=max\n to obtain the maximum allowed page size.\n\n\ndrf-proxy-pagination\n\n\nThe \ndrf-proxy-pagination\n package\n includes a \nProxyPagination\n class which allows to choose pagination class with a query parameter.",
"title": "Pagination"
},
{
@@ -2872,7 +2867,7 @@
},
{
"location": "/api-guide/pagination/#pagination-schemas",
- "text": "You can also make the pagination controls available to the schema autogeneration\nthat REST framework provides, by implementing a get_schema_fields() method,\nwhich should return a list of coreapi.Field instances. A custom pagination style, using the 'Link' header'",
+ "text": "You can also make the pagination controls available to the schema autogeneration\nthat REST framework provides, by implementing a get_schema_fields() method. This method should have the following signature: get_schema_fields(self, view) The method should return a list of coreapi.Field instances. A custom pagination style, using the 'Link' header'",
"title": "Pagination & schemas"
},
{
@@ -3062,7 +3057,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 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\nRepresenting schemas internally\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\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\nOther schema formats such as \nOpen API\n (\"Swagger\"),\n\nJSON HyperSchema\n, or \nAPI Blueprint\n can\nalso be supported by implementing a custom renderer class.\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\nAdding a schema\n\n\nYou'll need to install the \ncoreapi\n package in order to add schema support\nfor REST framework.\n\n\npip install coreapi\n\n\n\nREST framework includes functionality for auto-generating a schema,\nor allows you to specify one explicitly. There are a few different ways to\nadd a schema to your API, depending on exactly 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\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/vnd.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.renderers import CoreJSONRenderer\nfrom my_custom_package import APIBlueprintRenderer\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n renderer_classes=[CoreJSONRenderer, APIBlueprintRenderer]\n)\n\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.CoreJSONRenderer])\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.CoreJSONRenderer])\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.CoreJSONRenderer])\ndef schema_view(request):\n return response.Response(schema)\n\n\n\nStatic schema file\n\n\nA final option is to write your API schema as a static file, using one\nof the available formats, such as Core JSON or Open API.\n\n\nYou could then either:\n\n\n\n\nWrite a schema definition as a static file, and \nserve the static file directly\n.\n\n\nWrite a schema definition that is loaded using \nCore API\n, and then\n rendered to one of many available formats, depending on the client request.\n\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\nAlternate schema formats\n\n\nIn order to support an alternate schema format, you need to implement a custom renderer\nclass that handles converting a \nDocument\n instance into a bytestring representation.\n\n\nIf there is a Core API codec package that supports encoding into the format you\nwant to use then implementing the renderer class can be done by using the codec.\n\n\nExample\n\n\nFor example, the \nopenapi_codec\n package provides support for encoding or decoding\nto the Open API (\"Swagger\") format:\n\n\nfrom rest_framework import renderers\nfrom openapi_codec import OpenAPICodec\n\nclass SwaggerRenderer(renderers.BaseRenderer):\n media_type = 'application/openapi+json'\n format = 'swagger'\n\n def render(self, data, media_type=None, renderer_context=None):\n codec = OpenAPICodec()\n return codec.dump(data)\n\n\n\n\n\nAPI Reference\n\n\nSchemaGenerator\n\n\nA class that deals with introspecting your API views, which can be used to\ngenerate a schema.\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.CoreJSONRenderer])\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\nget_link(self, path, method, view)\n\n\nReturns a \ncoreapi.Link\n instance corresponding to the given view.\n\n\nYou can override this if you need to provide custom behaviors for particular views.\n\n\nget_description(self, path, method, view)\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, view)\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, view):\n\n\nReturn a list of \ncoreapi.Link()\n instances. One for each path parameter in the URL.\n\n\nget_serializer_fields(self, path, method, view)\n\n\nReturn a list of \ncoreapi.Link()\n instances. One for each field in the serializer class used by the view.\n\n\nget_pagination_fields(self, path, method, view\n\n\nReturn a list of \ncoreapi.Link()\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, view)\n\n\nReturn a list of \ncoreapi.Link()\n instances, as returned by the \nget_schema_fields()\n method of any filter classes used by the view.\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.",
+ "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 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\nRepresenting schemas internally\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\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\nOther schema formats such as \nOpen API\n (\"Swagger\"),\n\nJSON HyperSchema\n, or \nAPI Blueprint\n can\nalso be supported by implementing a custom renderer class.\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\nAdding a schema\n\n\nYou'll need to install the \ncoreapi\n package in order to add schema support\nfor REST framework.\n\n\npip install coreapi\n\n\n\nREST framework includes functionality for auto-generating a schema,\nor allows you to specify one explicitly. There are a few different ways to\nadd a schema to your API, depending on exactly 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\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.renderers import CoreJSONRenderer\nfrom my_custom_package import APIBlueprintRenderer\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n renderer_classes=[CoreJSONRenderer, APIBlueprintRenderer]\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\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.CoreJSONRenderer])\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.CoreJSONRenderer])\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.CoreJSONRenderer])\ndef schema_view(request):\n return response.Response(schema)\n\n\n\nStatic schema file\n\n\nA final option is to write your API schema as a static file, using one\nof the available formats, such as Core JSON or Open API.\n\n\nYou could then either:\n\n\n\n\nWrite a schema definition as a static file, and \nserve the static file directly\n.\n\n\nWrite a schema definition that is loaded using \nCore API\n, and then\n rendered to one of many available formats, depending on the client request.\n\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\nAlternate schema formats\n\n\nIn order to support an alternate schema format, you need to implement a custom renderer\nclass that handles converting a \nDocument\n instance into a bytestring representation.\n\n\nIf there is a Core API codec package that supports encoding into the format you\nwant to use then implementing the renderer class can be done by using the codec.\n\n\nExample\n\n\nFor example, the \nopenapi_codec\n package provides support for encoding or decoding\nto the Open API (\"Swagger\") format:\n\n\nfrom rest_framework import renderers\nfrom openapi_codec import OpenAPICodec\n\nclass SwaggerRenderer(renderers.BaseRenderer):\n media_type = 'application/openapi+json'\n format = 'swagger'\n\n def render(self, data, media_type=None, renderer_context=None):\n codec = OpenAPICodec()\n return codec.dump(data)\n\n\n\n\n\nAPI Reference\n\n\nSchemaGenerator\n\n\nA class that deals with introspecting your API views, which can be used to\ngenerate a schema.\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.CoreJSONRenderer])\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\nget_link(self, path, method, view)\n\n\nReturns a \ncoreapi.Link\n instance corresponding to the given view.\n\n\nYou can override this if you need to provide custom behaviors for particular views.\n\n\nget_description(self, path, method, view)\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, view)\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, view):\n\n\nReturn a list of \ncoreapi.Link()\n instances. One for each path parameter in the URL.\n\n\nget_serializer_fields(self, path, method, view)\n\n\nReturn a list of \ncoreapi.Link()\n instances. One for each field in the serializer class used by the view.\n\n\nget_pagination_fields(self, path, method, view\n\n\nReturn a list of \ncoreapi.Link()\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, view)\n\n\nReturn a list of \ncoreapi.Link()\n instances, as returned by the \nget_schema_fields()\n method of any filter classes used by the view.\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.",
"title": "Schemas"
},
{
@@ -3092,7 +3087,7 @@
},
{
"location": "/api-guide/schemas/#the-get_schema_view-shortcut",
- "text": "The simplest way to include a schema in your project is to use the get_schema_view() function. schema_view = get_schema_view(title=\"Server Monitoring API\")\n\nurlpatterns = [\n url('^$', schema_view),\n ...\n] Once the view has been added, you'll be able to make API requests to retrieve\nthe auto-generated schema definition. $ http http://127.0.0.1:8000/ Accept:application/vnd.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} The arguments to get_schema_view() are:",
+ "text": "The simplest way to include a schema in your project is to use the get_schema_view() function. schema_view = get_schema_view(title=\"Server Monitoring API\")\n\nurlpatterns = [\n url('^$', schema_view),\n ...\n] Once the view has been added, you'll be able to make API requests to retrieve\nthe auto-generated schema definition. $ 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} The arguments to get_schema_view() are:",
"title": "The get_schema_view shortcut"
},
{
@@ -3115,6 +3110,11 @@
"text": "May be used to pass the set of renderer classes that can be used to render the API root endpoint. from rest_framework.renderers import CoreJSONRenderer\nfrom my_custom_package import APIBlueprintRenderer\n\nschema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n renderer_classes=[CoreJSONRenderer, APIBlueprintRenderer]\n)",
"title": "renderer_classes"
},
+ {
+ "location": "/api-guide/schemas/#patterns",
+ "text": "List of url patterns to limit the schema introspection to. If you only want the myproject.api urls\nto be exposed in the schema: schema_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)",
+ "title": "patterns"
+ },
{
"location": "/api-guide/schemas/#using-an-explicit-schema-view",
"text": "If you need a little more control than the get_schema_view() shortcut gives you,\nthen you can use the SchemaGenerator class directly to auto-generate the Document instance, and to return that from a view. This 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. Here's an example of using SchemaGenerator together with a view to\nreturn the schema. views.py: from 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.CoreJSONRenderer])\ndef schema_view(request):\n schema = generator.get_schema(request)\n return response.Response(schema) urls.py: urlpatterns = [\n url('/', schema_view),\n ...\n] You 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. In order to present a schema with endpoints filtered by user permissions,\nyou need to pass the request argument to the get_schema() method, like so: @api_view()\n@renderer_classes([renderers.CoreJSONRenderer])\ndef schema_view(request):\n generator = schemas.SchemaGenerator(title='Bookings API')\n return response.Response(generator.get_schema(request=request))",
@@ -3462,7 +3462,7 @@
},
{
"location": "/api-guide/testing/",
- "text": "Testing\n\n\n\n\nCode without tests is broken as designed.\n\n\n \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.token)\n\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 the that 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, and simple 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\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 \n 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('/homepage/')\nassert response.status_code == 200\ncsrftoken = response.cookies['csrftoken']\n\n# Interact with the API.\nresponse = client.post('/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 \n 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\nTest 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\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 \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.token)\n\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 the that 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\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 \n 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('/homepage/')\nassert response.status_code == 200\ncsrftoken = response.cookies['csrftoken']\n\n# Interact with the API.\nresponse = client.post('/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 \n 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\nTest 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\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"
},
{
@@ -3532,7 +3532,7 @@
},
{
"location": "/api-guide/testing/#force_authenticateusernone-tokennone",
- "text": "Sometimes you may want to bypass authentication, and simple force all requests by the test client to be automatically treated as authenticated. This 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. user = User.objects.get(username='lauren')\nclient = APIClient()\nclient.force_authenticate(user=user) To unauthenticate subsequent requests, call force_authenticate setting the user and/or token to None . client.force_authenticate(user=None)",
+ "text": "Sometimes you may want to bypass authentication entirely and force all requests by the test client to be automatically treated as authenticated. This 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. user = User.objects.get(username='lauren')\nclient = APIClient()\nclient.force_authenticate(user=user) To unauthenticate subsequent requests, call force_authenticate setting the user and/or token to None . client.force_authenticate(user=None)",
"title": ".force_authenticate(user=None, token=None)"
},
{
@@ -4137,7 +4137,7 @@
},
{
"location": "/topics/internationalization/",
- "text": "Internationalization\n\n\n\n\nSupporting internationalization is not optional. It must be a core feature.\n\n\n \nJannis Leidel, speaking at Django Under the Hood, 2015\n.\n\n\n\n\nREST framework ships with translatable error messages. You can make these appear in your language enabling \nDjango's standard translation mechanisms\n.\n\n\nDoing so will allow you to:\n\n\n\n\nSelect a language other than English as the default, using the standard \nLANGUAGE_CODE\n Django setting.\n\n\nAllow clients to choose a language themselves, using the \nLocaleMiddleware\n included with Django. A typical usage for API clients would be to include an \nAccept-Language\n request header.\n\n\n\n\nEnabling internationalized APIs\n\n\nYou can change the default language by using the standard Django \nLANGUAGE_CODE\n setting:\n\n\nLANGUAGE_CODE = \"es-es\"\n\n\n\nYou can turn on per-request language requests by adding \nLocalMiddleware\n to your \nMIDDLEWARE_CLASSES\n setting:\n\n\nMIDDLEWARE_CLASSES = [\n ...\n 'django.middleware.locale.LocaleMiddleware'\n]\n\n\n\nWhen per-request internationalization is enabled, client requests will respect the \nAccept-Language\n header where possible. For example, let's make a request for an unsupported media type:\n\n\nRequest\n\n\nGET /api/users HTTP/1.1\nAccept: application/xml\nAccept-Language: es-es\nHost: example.org\n\n\n\nResponse\n\n\nHTTP/1.0 406 NOT ACCEPTABLE\n\n{\"detail\": \"No se ha podido satisfacer la solicitud de cabecera de Accept.\"}\n\n\n\nREST framework includes these built-in translations both for standard exception cases, and for serializer validation errors.\n\n\nNote that the translations only apply to the error strings themselves. The format of error messages, and the keys of field names will remain the same. An example \n400 Bad Request\n response body might look like this:\n\n\n{\"detail\": {\"username\": [\"Esse campo deve ser unico.\"]}}\n\n\n\nIf you want to use different string for parts of the response such as \ndetail\n and \nnon_field_errors\n then you can modify this behavior by using a \ncustom exception handler\n.\n\n\nSpecifying the set of supported languages.\n\n\nBy default all available languages will be supported.\n\n\nIf you only wish to support a subset of the available languages, use Django's standard \nLANGUAGES\n setting:\n\n\nLANGUAGES = [\n ('de', _('German')),\n ('en', _('English')),\n]\n\n\n\nAdding new translations\n\n\nREST framework translations are managed online using \nTransifex\n. You can use the Transifex service to add new translation languages. The maintenance team will then ensure that these translation strings are included in the REST framework package.\n\n\nSometimes you may need to add translation strings to your project locally. You may need to do this if:\n\n\n\n\nYou want to use REST Framework in a language which has not been translated yet on Transifex.\n\n\nYour project includes custom error messages, which are not part of REST framework's default translation strings.\n\n\n\n\nTranslating a new language locally\n\n\nThis guide assumes you are already familiar with how to translate a Django app. If you're not, start by reading \nDjango's translation docs\n.\n\n\nIf you're translating a new language you'll need to translate the existing REST framework error messages:\n\n\n\n\n\n\nMake a new folder where you want to store the internationalization resources. Add this path to your \nLOCALE_PATHS\n setting.\n\n\n\n\n\n\nNow create a subfolder for the language you want to translate. The folder should be named using \nlocale name\n notation. For example: \nde\n, \npt_BR\n, \nes_AR\n.\n\n\n\n\n\n\nNow copy the \nbase translations file\n from the REST framework source code into your translations folder.\n\n\n\n\n\n\nEdit the \ndjango.po\n file you've just copied, translating all the error messages.\n\n\n\n\n\n\nRun \nmanage.py compilemessages -l pt_BR\n to make the translations \navailable for Django to use. You should see a message like \nprocessing file django.po in \n...\n/locale/pt_BR/LC_MESSAGES\n.\n\n\n\n\n\n\nRestart your development server to see the changes take effect.\n\n\n\n\n\n\nIf you're only translating custom error messages that exist inside your project codebase you don't need to copy the REST framework source \ndjango.po\n file into a \nLOCALE_PATHS\n folder, and can instead simply run Django's standard \nmakemessages\n process.\n\n\nHow the language is determined\n\n\nIf you want to allow per-request language preferences you'll need to include \ndjango.middleware.locale.LocaleMiddleware\n in your \nMIDDLEWARE_CLASSES\n setting.\n\n\nYou can find more information on how the language preference is determined in the \nDjango documentation\n. For reference, the method is:\n\n\n\n\nFirst, it looks for the language prefix in the requested URL.\n\n\nFailing that, it looks for the \nLANGUAGE_SESSION_KEY\n key in the current user\u2019s session.\n\n\nFailing that, it looks for a cookie.\n\n\nFailing that, it looks at the \nAccept-Language\n HTTP header.\n\n\nFailing that, it uses the global \nLANGUAGE_CODE\n setting.\n\n\n\n\nFor API clients the most appropriate of these will typically be to use the \nAccept-Language\n header; Sessions and cookies will not be available unless using session authentication, and generally better practice to prefer an \nAccept-Language\n header for API clients rather than using language URL prefixes.",
+ "text": "Internationalization\n\n\n\n\nSupporting internationalization is not optional. It must be a core feature.\n\n\n \nJannis Leidel, speaking at Django Under the Hood, 2015\n.\n\n\n\n\nREST framework ships with translatable error messages. You can make these appear in your language enabling \nDjango's standard translation mechanisms\n.\n\n\nDoing so will allow you to:\n\n\n\n\nSelect a language other than English as the default, using the standard \nLANGUAGE_CODE\n Django setting.\n\n\nAllow clients to choose a language themselves, using the \nLocaleMiddleware\n included with Django. A typical usage for API clients would be to include an \nAccept-Language\n request header.\n\n\n\n\nEnabling internationalized APIs\n\n\nYou can change the default language by using the standard Django \nLANGUAGE_CODE\n setting:\n\n\nLANGUAGE_CODE = \"es-es\"\n\n\n\nYou can turn on per-request language requests by adding \nLocalMiddleware\n to your \nMIDDLEWARE_CLASSES\n setting:\n\n\nMIDDLEWARE_CLASSES = [\n ...\n 'django.middleware.locale.LocaleMiddleware'\n]\n\n\n\nWhen per-request internationalization is enabled, client requests will respect the \nAccept-Language\n header where possible. For example, let's make a request for an unsupported media type:\n\n\nRequest\n\n\nGET /api/users HTTP/1.1\nAccept: application/xml\nAccept-Language: es-es\nHost: example.org\n\n\n\nResponse\n\n\nHTTP/1.0 406 NOT ACCEPTABLE\n\n{\"detail\": \"No se ha podido satisfacer la solicitud de cabecera de Accept.\"}\n\n\n\nREST framework includes these built-in translations both for standard exception cases, and for serializer validation errors.\n\n\nNote that the translations only apply to the error strings themselves. The format of error messages, and the keys of field names will remain the same. An example \n400 Bad Request\n response body might look like this:\n\n\n{\"detail\": {\"username\": [\"Esse campo deve ser unico.\"]}}\n\n\n\nIf you want to use different string for parts of the response such as \ndetail\n and \nnon_field_errors\n then you can modify this behavior by using a \ncustom exception handler\n.\n\n\nSpecifying the set of supported languages.\n\n\nBy default all available languages will be supported.\n\n\nIf you only wish to support a subset of the available languages, use Django's standard \nLANGUAGES\n setting:\n\n\nLANGUAGES = [\n ('de', _('German')),\n ('en', _('English')),\n]\n\n\n\nAdding new translations\n\n\nREST framework translations are managed online using \nTransifex\n. You can use the Transifex service to add new translation languages. The maintenance team will then ensure that these translation strings are included in the REST framework package.\n\n\nSometimes you may need to add translation strings to your project locally. You may need to do this if:\n\n\n\n\nYou want to use REST Framework in a language which has not been translated yet on Transifex.\n\n\nYour project includes custom error messages, which are not part of REST framework's default translation strings.\n\n\n\n\nTranslating a new language locally\n\n\nThis guide assumes you are already familiar with how to translate a Django app. If you're not, start by reading \nDjango's translation docs\n.\n\n\nIf you're translating a new language you'll need to translate the existing REST framework error messages:\n\n\n\n\n\n\nMake a new folder where you want to store the internationalization resources. Add this path to your \nLOCALE_PATHS\n setting.\n\n\n\n\n\n\nNow create a subfolder for the language you want to translate. The folder should be named using \nlocale name\n notation. For example: \nde\n, \npt_BR\n, \nes_AR\n.\n\n\n\n\n\n\nNow copy the \nbase translations file\n from the REST framework source code into your translations folder.\n\n\n\n\n\n\nEdit the \ndjango.po\n file you've just copied, translating all the error messages.\n\n\n\n\n\n\nRun \nmanage.py compilemessages -l pt_BR\n to make the translations\navailable for Django to use. You should see a message like \nprocessing file django.po in \n...\n/locale/pt_BR/LC_MESSAGES\n.\n\n\n\n\n\n\nRestart your development server to see the changes take effect.\n\n\n\n\n\n\nIf you're only translating custom error messages that exist inside your project codebase you don't need to copy the REST framework source \ndjango.po\n file into a \nLOCALE_PATHS\n folder, and can instead simply run Django's standard \nmakemessages\n process.\n\n\nHow the language is determined\n\n\nIf you want to allow per-request language preferences you'll need to include \ndjango.middleware.locale.LocaleMiddleware\n in your \nMIDDLEWARE_CLASSES\n setting.\n\n\nYou can find more information on how the language preference is determined in the \nDjango documentation\n. For reference, the method is:\n\n\n\n\nFirst, it looks for the language prefix in the requested URL.\n\n\nFailing that, it looks for the \nLANGUAGE_SESSION_KEY\n key in the current user\u2019s session.\n\n\nFailing that, it looks for a cookie.\n\n\nFailing that, it looks at the \nAccept-Language\n HTTP header.\n\n\nFailing that, it uses the global \nLANGUAGE_CODE\n setting.\n\n\n\n\nFor API clients the most appropriate of these will typically be to use the \nAccept-Language\n header; Sessions and cookies will not be available unless using session authentication, and generally better practice to prefer an \nAccept-Language\n header for API clients rather than using language URL prefixes.",
"title": "Internationalization"
},
{
@@ -4162,7 +4162,7 @@
},
{
"location": "/topics/internationalization/#translating-a-new-language-locally",
- "text": "This guide assumes you are already familiar with how to translate a Django app. If you're not, start by reading Django's translation docs . If you're translating a new language you'll need to translate the existing REST framework error messages: Make a new folder where you want to store the internationalization resources. Add this path to your LOCALE_PATHS setting. Now create a subfolder for the language you want to translate. The folder should be named using locale name notation. For example: de , pt_BR , es_AR . Now copy the base translations file from the REST framework source code into your translations folder. Edit the django.po file you've just copied, translating all the error messages. Run manage.py compilemessages -l pt_BR to make the translations \navailable for Django to use. You should see a message like processing file django.po in ... /locale/pt_BR/LC_MESSAGES . Restart your development server to see the changes take effect. If you're only translating custom error messages that exist inside your project codebase you don't need to copy the REST framework source django.po file into a LOCALE_PATHS folder, and can instead simply run Django's standard makemessages process.",
+ "text": "This guide assumes you are already familiar with how to translate a Django app. If you're not, start by reading Django's translation docs . If you're translating a new language you'll need to translate the existing REST framework error messages: Make a new folder where you want to store the internationalization resources. Add this path to your LOCALE_PATHS setting. Now create a subfolder for the language you want to translate. The folder should be named using locale name notation. For example: de , pt_BR , es_AR . Now copy the base translations file from the REST framework source code into your translations folder. Edit the django.po file you've just copied, translating all the error messages. Run manage.py compilemessages -l pt_BR to make the translations\navailable for Django to use. You should see a message like processing file django.po in ... /locale/pt_BR/LC_MESSAGES . Restart your development server to see the changes take effect. If you're only translating custom error messages that exist inside your project codebase you don't need to copy the REST framework source django.po file into a LOCALE_PATHS folder, and can instead simply run Django's standard makemessages process.",
"title": "Translating a new language locally"
},
{
@@ -4282,7 +4282,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 \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 \nlink rel=\"stylesheet\" href=\"/path/to/my/bootstrap.css\" type=\"text/css\"\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 \nlink rel=\"stylesheet\" href=\"http://bootswatch.com/flatly/bootstrap.min.css\" type=\"text/css\"\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 \nbody\n.\n\n\nbodyclass\n - Class attribute for the \nbody\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 \nh3 style=\"margin: 0 0 20px;\"\nMy Site Name\n/h3\n\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.\n\n\nBetter support for autocomplete inputs is planned in future versions.",
+ "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 \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 \nlink rel=\"stylesheet\" href=\"/path/to/my/bootstrap.css\" type=\"text/css\"\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 \nlink rel=\"stylesheet\" href=\"http://bootswatch.com/flatly/bootstrap.min.css\" type=\"text/css\"\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 \nbody\n.\n\n\nbodyclass\n - Class attribute for the \nbody\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 \nh3 style=\"margin: 0 0 20px;\"\nMy Site Name\n/h3\n\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"
},
{
@@ -4352,7 +4352,7 @@
},
{
"location": "/topics/browsable-api/#autocomplete",
- "text": "An 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. There are a variety of packages for autocomplete widgets , such as django-autocomplete-light , 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 widget keyword argument since it now uses templated HTML generation. Better support for autocomplete inputs is planned in future versions.",
+ "text": "An 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. There are a variety of packages for autocomplete widgets , such as django-autocomplete-light , 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 widget keyword argument since it now uses templated HTML generation.",
"title": "Autocomplete"
},
{
@@ -4382,7 +4382,7 @@
},
{
"location": "/topics/third-party-packages/",
- "text": "Third Party Packages\n\n\n\n\nSoftware ecosystems [\u2026] establish a community that further accelerates the sharing of knowledge, content, issues, expertise and skills.\n\n\n \nJan Bosch\n.\n\n\n\n\nAbout Third Party Packages\n\n\nThird Party Packages allow developers to share code that extends the functionality of Django REST framework, in order to support additional use-cases.\n\n\nWe \nsupport\n, \nencourage\n and \nstrongly favor\n the creation of Third Party Packages to encapsulate new behavior rather than adding additional functionality directly to Django REST Framework.\n\n\nWe aim to make creating third party packages as easy as possible, whilst keeping a \nsimple\n and \nwell maintained\n core API. By promoting third party packages we ensure that the responsibility for a package remains with its author. If a package proves suitably popular it can always be considered for inclusion into the core REST framework.\n\n\nIf you have an idea for a new feature please consider how it may be packaged as a Third Party Package. We're always happy to discuss ideas on the \nMailing List\n.\n\n\nHow to create a Third Party Package\n\n\nCreating your package\n\n\nYou can use \nthis cookiecutter template\n for creating reusable Django REST Framework packages quickly. Cookiecutter creates projects from project templates. While optional, this cookiecutter template includes best practices from Django REST framework and other packages, as well as a Travis CI configuration, Tox configuration, and a sane setup.py for easy PyPI registration/distribution.\n\n\nNote: Let us know if you have an alternate cookiecuter package so we can also link to it.\n\n\nRunning the initial cookiecutter command\n\n\nTo run the initial cookiecutter command, you'll first need to install the Python \ncookiecutter\n package.\n\n\n$ pip install cookiecutter\n\n\n\nOnce \ncookiecutter\n is installed just run the following to create a new project.\n\n\n$ cookiecutter gh:jpadilla/cookiecutter-django-rest-framework\n\n\n\nYou'll be prompted for some questions, answer them, then it'll create your Python package in the current working directory based on those values.\n\n\nfull_name (default is \"Your full name here\")? Johnny Appleseed\nemail (default is \"you@example.com\")? jappleseed@example.com\ngithub_username (default is \"yourname\")? jappleseed\npypi_project_name (default is \"dj-package\")? djangorestframework-custom-auth\nrepo_name (default is \"dj-package\")? django-rest-framework-custom-auth\napp_name (default is \"djpackage\")? custom_auth\nproject_short_description (default is \"Your project description goes here\")?\nyear (default is \"2014\")?\nversion (default is \"0.1.0\")?\n\n\n\nGetting it onto GitHub\n\n\nTo put your project up on GitHub, you'll need a repository for it to live in. You can create a new repository \nhere\n. If you need help, check out the \nCreate A Repo\n article on GitHub.\n\n\nAdding to Travis CI\n\n\nWe recommend using \nTravis CI\n, a hosted continuous integration service which integrates well with GitHub and is free for public repositories.\n\n\nTo get started with Travis CI, \nsign in\n with your GitHub account. Once you're signed in, go to your \nprofile page\n and enable the service hook for the repository you want.\n\n\nIf you use the cookiecutter template, your project will already contain a \n.travis.yml\n file which Travis CI will use to build your project and run tests. By default, builds are triggered everytime you push to your repository or create Pull Request.\n\n\nUploading to PyPI\n\n\nOnce you've got at least a prototype working and tests running, you should publish it on PyPI to allow others to install it via \npip\n.\n\n\nYou must \nregister\n an account before publishing to PyPI.\n\n\nTo register your package on PyPI run the following command.\n\n\n$ python setup.py register\n\n\n\nIf this is the first time publishing to PyPI, you'll be prompted to login.\n\n\nNote: Before publishing you'll need to make sure you have the latest pip that supports \nwheel\n as well as install the \nwheel\n package.\n\n\n$ pip install --upgrade pip\n$ pip install wheel\n\n\n\nAfter this, every time you want to release a new version on PyPI just run the following command.\n\n\n$ python setup.py publish\nYou probably want to also tag the version now:\n git tag -a {0} -m 'version 0.1.0'\n git push --tags\n\n\n\nAfter releasing a new version to PyPI, it's always a good idea to tag the version and make available as a GitHub Release.\n\n\nWe recommend to follow \nSemantic Versioning\n for your package's versions.\n\n\nDevelopment\n\n\nVersion requirements\n\n\nThe cookiecutter template assumes a set of supported versions will be provided for Python and Django. Make sure you correctly update your requirements, docs, \ntox.ini\n, \n.travis.yml\n, and \nsetup.py\n to match the set of versions you wish to support.\n\n\nTests\n\n\nThe cookiecutter template includes a \nruntests.py\n which uses the \npytest\n package as a test runner.\n\n\nBefore running, you'll need to install a couple test requirements.\n\n\n$ pip install -r requirements.txt\n\n\n\nOnce requirements installed, you can run \nruntests.py\n.\n\n\n$ ./runtests.py\n\n\n\nRun using a more concise output style.\n\n\n$ ./runtests.py -q\n\n\n\nRun the tests using a more concise output style, no coverage, no flake8.\n\n\n$ ./runtests.py --fast\n\n\n\nDon't run the flake8 code linting.\n\n\n$ ./runtests.py --nolint\n\n\n\nOnly run the flake8 code linting, don't run the tests.\n\n\n$ ./runtests.py --lintonly\n\n\n\nRun the tests for a given test case.\n\n\n$ ./runtests.py MyTestCase\n\n\n\nRun the tests for a given test method.\n\n\n$ ./runtests.py MyTestCase.test_this_method\n\n\n\nShorter form to run the tests for a given test method.\n\n\n$ ./runtests.py test_this_method\n\n\n\nTo run your tests against multiple versions of Python as different versions of requirements such as Django we recommend using \ntox\n. \nTox\n is a generic virtualenv management and test command line tool.\n\n\nFirst, install \ntox\n globally.\n\n\n$ pip install tox\n\n\n\nTo run \ntox\n, just simply run:\n\n\n$ tox\n\n\n\nTo run a particular \ntox\n environment:\n\n\n$ tox -e envlist\n\n\n\nenvlist\n is a comma-separated value to that specifies the environments to run tests against. To view a list of all possible test environments, run:\n\n\n$ tox -l\n\n\n\nVersion compatibility\n\n\nSometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into a \ncompat.py\n module, and should provide a single common interface that the rest of the codebase can use.\n\n\nCheck out Django REST framework's \ncompat.py\n for an example.\n\n\nOnce your package is available\n\n\nOnce your package is decently documented and available on PyPI, you might want share it with others that might find it useful.\n\n\nAdding to the Django REST framework grid\n\n\nWe suggest adding your package to the \nREST Framework\n grid on Django Packages.\n\n\nAdding to the Django REST framework docs\n\n\nCreate a \nPull Request\n or \nIssue\n on GitHub, and we'll add a link to it from the main REST framework documentation. You can add your package under \nThird party packages\n of the API Guide section that best applies, like \nAuthentication\n or \nPermissions\n. You can also link your package under the \nThird Party Packages\n section.\n\n\nAnnounce on the discussion group.\n\n\nYou can also let others know about your package through the \ndiscussion group\n.\n\n\nExisting Third Party Packages\n\n\nDjango REST Framework has a growing community of developers, packages, and resources.\n\n\nCheck out a grid detailing all the packages and ecosystem around Django REST Framework at \nDjango Packages\n.\n\n\nTo submit new content, \nopen an issue\n or \ncreate a pull request\n.\n\n\nAuthentication\n\n\n\n\ndjangorestframework-digestauth\n - Provides Digest Access Authentication support.\n\n\ndjango-oauth-toolkit\n - Provides OAuth 2.0 support.\n\n\ndoac\n - Provides OAuth 2.0 support.\n\n\ndjangorestframework-jwt\n - Provides JSON Web Token Authentication support.\n\n\nhawkrest\n - Provides Hawk HTTP Authorization.\n\n\ndjangorestframework-httpsignature\n - Provides an easy to use HTTP Signature Authentication mechanism.\n\n\ndjoser\n - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.\n\n\ndjango-rest-auth\n - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc.\n\n\ndrf-oidc-auth\n - Implements OpenID Connect token authentication for DRF.\n\n\n\n\nPermissions\n\n\n\n\ndrf-any-permissions\n - Provides alternative permission handling.\n\n\ndjangorestframework-composed-permissions\n - Provides a simple way to define complex permissions.\n\n\nrest_condition\n - Another extension for building complex permissions in a simple and convenient way.\n\n\ndry-rest-permissions\n - Provides a simple way to define permissions for individual api actions.\n\n\n\n\nSerializers\n\n\n\n\ndjango-rest-framework-mongoengine\n - Serializer class that supports using MongoDB as the storage layer for Django REST framework.\n\n\ndjangorestframework-gis\n - Geographic add-ons\n\n\ndjangorestframework-hstore\n - Serializer class to support django-hstore DictionaryField model field and its schema-mode feature.\n\n\ndjangorestframework-jsonapi\n - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec.\n\n\nhtml-json-forms\n - Provides an algorithm and serializer to process HTML JSON Form submissions per the (inactive) spec.\n\n\ndjango-rest-framework-serializer-extensions\n -\n Enables black/whitelisting fields, and conditionally expanding child serializers on a per-view/request basis.\n\n\ndjangorestframework-queryfields\n - Serializer mixin allowing clients to control which fields will be sent in the API response.\n\n\n\n\nSerializer fields\n\n\n\n\ndrf-compound-fields\n - Provides \"compound\" serializer fields, such as lists of simple values.\n\n\ndjango-extra-fields\n - Provides extra serializer fields.\n\n\ndjango-versatileimagefield\n - Provides a drop-in replacement for Django's stock \nImageField\n that makes it easy to serve images in multiple sizes/renditions from a single field. For DRF-specific implementation docs, \nclick here\n.\n\n\n\n\nViews\n\n\n\n\ndjangorestframework-bulk\n - Implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.\n\n\ndjango-rest-multiple-models\n - Provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.\n\n\n\n\nRouters\n\n\n\n\ndrf-nested-routers\n - Provides routers and relationship fields for working with nested resources.\n\n\nwq.db.rest\n - Provides an admin-style model registration API with reasonable default URLs and viewsets.\n\n\n\n\nParsers\n\n\n\n\ndjangorestframework-msgpack\n - Provides MessagePack renderer and parser support.\n\n\ndjangorestframework-jsonapi\n - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec.\n\n\ndjangorestframework-camel-case\n - Provides camel case JSON renderers and parsers.\n\n\n\n\nRenderers\n\n\n\n\ndjangorestframework-csv\n - Provides CSV renderer support.\n\n\ndjangorestframework-jsonapi\n - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec.\n\n\ndrf_ujson\n - Implements JSON rendering using the UJSON package.\n\n\nrest-pandas\n - Pandas DataFrame-powered renderers including Excel, CSV, and SVG formats.\n\n\n\n\nFiltering\n\n\n\n\ndjangorestframework-chain\n - Allows arbitrary chaining of both relations and lookup filters.\n\n\ndjango-url-filter\n - Allows a safe way to filter data via human-friendly URLs. It is a generic library which is not tied to DRF but it provides easy integration with DRF.\n\n\ndrf-url-filter\n is a simple Django app to apply filters on drf \nModelViewSet\n's \nQueryset\n in a clean, simple and configurable way. It also supports validations on incoming query params and their values.\n\n\n\n\nMisc\n\n\n\n\ncookiecutter-django-rest\n - A cookiecutter template that takes care of the setup and configuration so you can focus on making your REST apis awesome.\n\n\ndjangorestrelationalhyperlink\n - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer.\n\n\ndjango-rest-swagger\n - An API documentation generator for Swagger UI.\n\n\ndjango-rest-framework-proxy\n - Proxy to redirect incoming request to another API server.\n\n\ngaiarestframework\n - Utils for django-rest-framework\n\n\ndrf-extensions\n - A collection of custom extensions\n\n\nember-django-adapter\n - An adapter for working with Ember.js\n\n\ndjango-versatileimagefield\n - Provides a drop-in replacement for Django's stock \nImageField\n that makes it easy to serve images in multiple sizes/renditions from a single field. For DRF-specific implementation docs, \nclick here\n.\n\n\ndrf-tracking\n - Utilities to track requests to DRF API views.\n\n\ndrf_tweaks\n - Serializers with one-step validation (and more), pagination without counts and other tweaks.\n\n\ndjango-rest-framework-braces\n - Collection of utilities for working with Django Rest Framework. The most notable ones are \nFormSerializer\n and \nSerializerForm\n, which are adapters between DRF serializers and Django forms.\n\n\ndrf-haystack\n - Haystack search for Django Rest Framework\n\n\ndjango-rest-framework-version-transforms\n - Enables the use of delta transformations for versioning of DRF resource representations.\n\n\ndjango-rest-messaging\n, \ndjango-rest-messaging-centrifugo\n and \ndjango-rest-messaging-js\n - A real-time pluggable messaging service using DRM.",
+ "text": "Third Party Packages\n\n\n\n\nSoftware ecosystems [\u2026] establish a community that further accelerates the sharing of knowledge, content, issues, expertise and skills.\n\n\n \nJan Bosch\n.\n\n\n\n\nAbout Third Party Packages\n\n\nThird Party Packages allow developers to share code that extends the functionality of Django REST framework, in order to support additional use-cases.\n\n\nWe \nsupport\n, \nencourage\n and \nstrongly favor\n the creation of Third Party Packages to encapsulate new behavior rather than adding additional functionality directly to Django REST Framework.\n\n\nWe aim to make creating third party packages as easy as possible, whilst keeping a \nsimple\n and \nwell maintained\n core API. By promoting third party packages we ensure that the responsibility for a package remains with its author. If a package proves suitably popular it can always be considered for inclusion into the core REST framework.\n\n\nIf you have an idea for a new feature please consider how it may be packaged as a Third Party Package. We're always happy to discuss ideas on the \nMailing List\n.\n\n\nHow to create a Third Party Package\n\n\nCreating your package\n\n\nYou can use \nthis cookiecutter template\n for creating reusable Django REST Framework packages quickly. Cookiecutter creates projects from project templates. While optional, this cookiecutter template includes best practices from Django REST framework and other packages, as well as a Travis CI configuration, Tox configuration, and a sane setup.py for easy PyPI registration/distribution.\n\n\nNote: Let us know if you have an alternate cookiecuter package so we can also link to it.\n\n\nRunning the initial cookiecutter command\n\n\nTo run the initial cookiecutter command, you'll first need to install the Python \ncookiecutter\n package.\n\n\n$ pip install cookiecutter\n\n\n\nOnce \ncookiecutter\n is installed just run the following to create a new project.\n\n\n$ cookiecutter gh:jpadilla/cookiecutter-django-rest-framework\n\n\n\nYou'll be prompted for some questions, answer them, then it'll create your Python package in the current working directory based on those values.\n\n\nfull_name (default is \"Your full name here\")? Johnny Appleseed\nemail (default is \"you@example.com\")? jappleseed@example.com\ngithub_username (default is \"yourname\")? jappleseed\npypi_project_name (default is \"dj-package\")? djangorestframework-custom-auth\nrepo_name (default is \"dj-package\")? django-rest-framework-custom-auth\napp_name (default is \"djpackage\")? custom_auth\nproject_short_description (default is \"Your project description goes here\")?\nyear (default is \"2014\")?\nversion (default is \"0.1.0\")?\n\n\n\nGetting it onto GitHub\n\n\nTo put your project up on GitHub, you'll need a repository for it to live in. You can create a new repository \nhere\n. If you need help, check out the \nCreate A Repo\n article on GitHub.\n\n\nAdding to Travis CI\n\n\nWe recommend using \nTravis CI\n, a hosted continuous integration service which integrates well with GitHub and is free for public repositories.\n\n\nTo get started with Travis CI, \nsign in\n with your GitHub account. Once you're signed in, go to your \nprofile page\n and enable the service hook for the repository you want.\n\n\nIf you use the cookiecutter template, your project will already contain a \n.travis.yml\n file which Travis CI will use to build your project and run tests. By default, builds are triggered everytime you push to your repository or create Pull Request.\n\n\nUploading to PyPI\n\n\nOnce you've got at least a prototype working and tests running, you should publish it on PyPI to allow others to install it via \npip\n.\n\n\nYou must \nregister\n an account before publishing to PyPI.\n\n\nTo register your package on PyPI run the following command.\n\n\n$ python setup.py register\n\n\n\nIf this is the first time publishing to PyPI, you'll be prompted to login.\n\n\nNote: Before publishing you'll need to make sure you have the latest pip that supports \nwheel\n as well as install the \nwheel\n package.\n\n\n$ pip install --upgrade pip\n$ pip install wheel\n\n\n\nAfter this, every time you want to release a new version on PyPI just run the following command.\n\n\n$ python setup.py publish\nYou probably want to also tag the version now:\n git tag -a {0} -m 'version 0.1.0'\n git push --tags\n\n\n\nAfter releasing a new version to PyPI, it's always a good idea to tag the version and make available as a GitHub Release.\n\n\nWe recommend to follow \nSemantic Versioning\n for your package's versions.\n\n\nDevelopment\n\n\nVersion requirements\n\n\nThe cookiecutter template assumes a set of supported versions will be provided for Python and Django. Make sure you correctly update your requirements, docs, \ntox.ini\n, \n.travis.yml\n, and \nsetup.py\n to match the set of versions you wish to support.\n\n\nTests\n\n\nThe cookiecutter template includes a \nruntests.py\n which uses the \npytest\n package as a test runner.\n\n\nBefore running, you'll need to install a couple test requirements.\n\n\n$ pip install -r requirements.txt\n\n\n\nOnce requirements installed, you can run \nruntests.py\n.\n\n\n$ ./runtests.py\n\n\n\nRun using a more concise output style.\n\n\n$ ./runtests.py -q\n\n\n\nRun the tests using a more concise output style, no coverage, no flake8.\n\n\n$ ./runtests.py --fast\n\n\n\nDon't run the flake8 code linting.\n\n\n$ ./runtests.py --nolint\n\n\n\nOnly run the flake8 code linting, don't run the tests.\n\n\n$ ./runtests.py --lintonly\n\n\n\nRun the tests for a given test case.\n\n\n$ ./runtests.py MyTestCase\n\n\n\nRun the tests for a given test method.\n\n\n$ ./runtests.py MyTestCase.test_this_method\n\n\n\nShorter form to run the tests for a given test method.\n\n\n$ ./runtests.py test_this_method\n\n\n\nTo run your tests against multiple versions of Python as different versions of requirements such as Django we recommend using \ntox\n. \nTox\n is a generic virtualenv management and test command line tool.\n\n\nFirst, install \ntox\n globally.\n\n\n$ pip install tox\n\n\n\nTo run \ntox\n, just simply run:\n\n\n$ tox\n\n\n\nTo run a particular \ntox\n environment:\n\n\n$ tox -e envlist\n\n\n\nenvlist\n is a comma-separated value to that specifies the environments to run tests against. To view a list of all possible test environments, run:\n\n\n$ tox -l\n\n\n\nVersion compatibility\n\n\nSometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into a \ncompat.py\n module, and should provide a single common interface that the rest of the codebase can use.\n\n\nCheck out Django REST framework's \ncompat.py\n for an example.\n\n\nOnce your package is available\n\n\nOnce your package is decently documented and available on PyPI, you might want share it with others that might find it useful.\n\n\nAdding to the Django REST framework grid\n\n\nWe suggest adding your package to the \nREST Framework\n grid on Django Packages.\n\n\nAdding to the Django REST framework docs\n\n\nCreate a \nPull Request\n or \nIssue\n on GitHub, and we'll add a link to it from the main REST framework documentation. You can add your package under \nThird party packages\n of the API Guide section that best applies, like \nAuthentication\n or \nPermissions\n. You can also link your package under the \nThird Party Packages\n section.\n\n\nAnnounce on the discussion group.\n\n\nYou can also let others know about your package through the \ndiscussion group\n.\n\n\nExisting Third Party Packages\n\n\nDjango REST Framework has a growing community of developers, packages, and resources.\n\n\nCheck out a grid detailing all the packages and ecosystem around Django REST Framework at \nDjango Packages\n.\n\n\nTo submit new content, \nopen an issue\n or \ncreate a pull request\n.\n\n\nAuthentication\n\n\n\n\ndjangorestframework-digestauth\n - Provides Digest Access Authentication support.\n\n\ndjango-oauth-toolkit\n - Provides OAuth 2.0 support.\n\n\ndoac\n - Provides OAuth 2.0 support.\n\n\ndjangorestframework-jwt\n - Provides JSON Web Token Authentication support.\n\n\nhawkrest\n - Provides Hawk HTTP Authorization.\n\n\ndjangorestframework-httpsignature\n - Provides an easy to use HTTP Signature Authentication mechanism.\n\n\ndjoser\n - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.\n\n\ndjango-rest-auth\n - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc.\n\n\ndrf-oidc-auth\n - Implements OpenID Connect token authentication for DRF.\n\n\ndrfpasswordless\n - Adds (Medium, Square Cash inspired) passwordless logins and signups via email and mobile numbers.\n\n\n\n\nPermissions\n\n\n\n\ndrf-any-permissions\n - Provides alternative permission handling.\n\n\ndjangorestframework-composed-permissions\n - Provides a simple way to define complex permissions.\n\n\nrest_condition\n - Another extension for building complex permissions in a simple and convenient way.\n\n\ndry-rest-permissions\n - Provides a simple way to define permissions for individual api actions.\n\n\n\n\nSerializers\n\n\n\n\ndjango-rest-framework-mongoengine\n - Serializer class that supports using MongoDB as the storage layer for Django REST framework.\n\n\ndjangorestframework-gis\n - Geographic add-ons\n\n\ndjangorestframework-hstore\n - Serializer class to support django-hstore DictionaryField model field and its schema-mode feature.\n\n\ndjangorestframework-jsonapi\n - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec.\n\n\nhtml-json-forms\n - Provides an algorithm and serializer to process HTML JSON Form submissions per the (inactive) spec.\n\n\ndjango-rest-framework-serializer-extensions\n -\n Enables black/whitelisting fields, and conditionally expanding child serializers on a per-view/request basis.\n\n\ndjangorestframework-queryfields\n - Serializer mixin allowing clients to control which fields will be sent in the API response.\n\n\n\n\nSerializer fields\n\n\n\n\ndrf-compound-fields\n - Provides \"compound\" serializer fields, such as lists of simple values.\n\n\ndjango-extra-fields\n - Provides extra serializer fields.\n\n\ndjango-versatileimagefield\n - Provides a drop-in replacement for Django's stock \nImageField\n that makes it easy to serve images in multiple sizes/renditions from a single field. For DRF-specific implementation docs, \nclick here\n.\n\n\n\n\nViews\n\n\n\n\ndjangorestframework-bulk\n - Implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.\n\n\ndjango-rest-multiple-models\n - Provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.\n\n\n\n\nRouters\n\n\n\n\ndrf-nested-routers\n - Provides routers and relationship fields for working with nested resources.\n\n\nwq.db.rest\n - Provides an admin-style model registration API with reasonable default URLs and viewsets.\n\n\n\n\nParsers\n\n\n\n\ndjangorestframework-msgpack\n - Provides MessagePack renderer and parser support.\n\n\ndjangorestframework-jsonapi\n - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec.\n\n\ndjangorestframework-camel-case\n - Provides camel case JSON renderers and parsers.\n\n\n\n\nRenderers\n\n\n\n\ndjangorestframework-csv\n - Provides CSV renderer support.\n\n\ndjangorestframework-jsonapi\n - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec.\n\n\ndrf_ujson\n - Implements JSON rendering using the UJSON package.\n\n\nrest-pandas\n - Pandas DataFrame-powered renderers including Excel, CSV, and SVG formats.\n\n\n\n\nFiltering\n\n\n\n\ndjangorestframework-chain\n - Allows arbitrary chaining of both relations and lookup filters.\n\n\ndjango-url-filter\n - Allows a safe way to filter data via human-friendly URLs. It is a generic library which is not tied to DRF but it provides easy integration with DRF.\n\n\ndrf-url-filter\n is a simple Django app to apply filters on drf \nModelViewSet\n's \nQueryset\n in a clean, simple and configurable way. It also supports validations on incoming query params and their values.\n\n\n\n\nMisc\n\n\n\n\ncookiecutter-django-rest\n - A cookiecutter template that takes care of the setup and configuration so you can focus on making your REST apis awesome.\n\n\ndjangorestrelationalhyperlink\n - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer.\n\n\ndjango-rest-swagger\n - An API documentation generator for Swagger UI.\n\n\ndjango-rest-framework-proxy\n - Proxy to redirect incoming request to another API server.\n\n\ngaiarestframework\n - Utils for django-rest-framework\n\n\ndrf-extensions\n - A collection of custom extensions\n\n\nember-django-adapter\n - An adapter for working with Ember.js\n\n\ndjango-versatileimagefield\n - Provides a drop-in replacement for Django's stock \nImageField\n that makes it easy to serve images in multiple sizes/renditions from a single field. For DRF-specific implementation docs, \nclick here\n.\n\n\ndrf-tracking\n - Utilities to track requests to DRF API views.\n\n\ndrf_tweaks\n - Serializers with one-step validation (and more), pagination without counts and other tweaks.\n\n\ndjango-rest-framework-braces\n - Collection of utilities for working with Django Rest Framework. The most notable ones are \nFormSerializer\n and \nSerializerForm\n, which are adapters between DRF serializers and Django forms.\n\n\ndrf-haystack\n - Haystack search for Django Rest Framework\n\n\ndjango-rest-framework-version-transforms\n - Enables the use of delta transformations for versioning of DRF resource representations.\n\n\ndjango-rest-messaging\n, \ndjango-rest-messaging-centrifugo\n and \ndjango-rest-messaging-js\n - A real-time pluggable messaging service using DRM.\n\n\ndjangorest-alchemy\n - SQLAlchemy support for REST framework.",
"title": "Third Party Packages"
},
{
@@ -4472,7 +4472,7 @@
},
{
"location": "/topics/third-party-packages/#authentication",
- "text": "djangorestframework-digestauth - Provides Digest Access Authentication support. django-oauth-toolkit - Provides OAuth 2.0 support. doac - Provides OAuth 2.0 support. djangorestframework-jwt - Provides JSON Web Token Authentication support. hawkrest - Provides Hawk HTTP Authorization. djangorestframework-httpsignature - Provides an easy to use HTTP Signature Authentication mechanism. djoser - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. django-rest-auth - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. drf-oidc-auth - Implements OpenID Connect token authentication for DRF.",
+ "text": "djangorestframework-digestauth - Provides Digest Access Authentication support. django-oauth-toolkit - Provides OAuth 2.0 support. doac - Provides OAuth 2.0 support. djangorestframework-jwt - Provides JSON Web Token Authentication support. hawkrest - Provides Hawk HTTP Authorization. djangorestframework-httpsignature - Provides an easy to use HTTP Signature Authentication mechanism. djoser - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. django-rest-auth - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. drf-oidc-auth - Implements OpenID Connect token authentication for DRF. drfpasswordless - Adds (Medium, Square Cash inspired) passwordless logins and signups via email and mobile numbers.",
"title": "Authentication"
},
{
@@ -4517,12 +4517,12 @@
},
{
"location": "/topics/third-party-packages/#misc",
- "text": "cookiecutter-django-rest - A cookiecutter template that takes care of the setup and configuration so you can focus on making your REST apis awesome. djangorestrelationalhyperlink - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer. django-rest-swagger - An API documentation generator for Swagger UI. django-rest-framework-proxy - Proxy to redirect incoming request to another API server. gaiarestframework - Utils for django-rest-framework drf-extensions - A collection of custom extensions ember-django-adapter - An adapter for working with Ember.js django-versatileimagefield - Provides a drop-in replacement for Django's stock ImageField that makes it easy to serve images in multiple sizes/renditions from a single field. For DRF-specific implementation docs, click here . drf-tracking - Utilities to track requests to DRF API views. drf_tweaks - Serializers with one-step validation (and more), pagination without counts and other tweaks. django-rest-framework-braces - Collection of utilities for working with Django Rest Framework. The most notable ones are FormSerializer and SerializerForm , which are adapters between DRF serializers and Django forms. drf-haystack - Haystack search for Django Rest Framework django-rest-framework-version-transforms - Enables the use of delta transformations for versioning of DRF resource representations. django-rest-messaging , django-rest-messaging-centrifugo and django-rest-messaging-js - A real-time pluggable messaging service using DRM.",
+ "text": "cookiecutter-django-rest - A cookiecutter template that takes care of the setup and configuration so you can focus on making your REST apis awesome. djangorestrelationalhyperlink - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer. django-rest-swagger - An API documentation generator for Swagger UI. django-rest-framework-proxy - Proxy to redirect incoming request to another API server. gaiarestframework - Utils for django-rest-framework drf-extensions - A collection of custom extensions ember-django-adapter - An adapter for working with Ember.js django-versatileimagefield - Provides a drop-in replacement for Django's stock ImageField that makes it easy to serve images in multiple sizes/renditions from a single field. For DRF-specific implementation docs, click here . drf-tracking - Utilities to track requests to DRF API views. drf_tweaks - Serializers with one-step validation (and more), pagination without counts and other tweaks. django-rest-framework-braces - Collection of utilities for working with Django Rest Framework. The most notable ones are FormSerializer and SerializerForm , which are adapters between DRF serializers and Django forms. drf-haystack - Haystack search for Django Rest Framework django-rest-framework-version-transforms - Enables the use of delta transformations for versioning of DRF resource representations. django-rest-messaging , django-rest-messaging-centrifugo and django-rest-messaging-js - A real-time pluggable messaging service using DRM. djangorest-alchemy - SQLAlchemy support for REST framework.",
"title": "Misc"
},
{
"location": "/topics/tutorials-and-resources/",
- "text": "Tutorials and Resources\n\n\nThere are a wide range of resources available for learning and using Django REST framework. We try to keep a comprehensive list available here.\n\n\nTutorials\n\n\n\n\nBeginner's Guide to the Django REST Framework\n\n\nDjango REST Framework - An Introduction\n\n\nDjango REST Framework Tutorial\n\n\nDjango REST Framework Course\n\n\nBuilding a RESTful API with Django REST Framework\n\n\nGetting Started with Django REST Framework and AngularJS\n\n\nEnd to End Web App with Django REST Framework \n AngularJS\n\n\nStart Your API - Django REST Framework Part 1\n\n\nPermissions \n Authentication - Django REST Framework Part 2\n\n\nViewSets and Routers - Django REST Framework Part 3\n\n\nDjango REST Framework User Endpoint\n\n\nCheck Credentials Using Django REST Framework\n\n\nCreating a Production Ready API with Python and Django REST Framework \u2013 Part 1\n\n\nCreating a Production Ready API with Python and Django REST Framework \u2013 Part 2\n\n\n\n\nVideos\n\n\nTalks\n\n\n\n\nHow to Make a Full Fledged REST API with Django OAuth Toolkit\n\n\nDjango REST API - So Easy You Can Learn It in 25 Minutes\n\n\nTom Christie about Django Rest Framework at Django: Under The Hood\n\n\nDjango REST Framework: Schemas, Hypermedia \n Client Libraries\n\n\n\n\nTutorials\n\n\n\n\nDjango REST Framework Part 1\n\n\nDjango REST Framework in Your PJ's!\n\n\nBuilding a REST API Using Django \n Django REST Framework\n\n\nBlog API with Django REST Framework\n\n\nEmber and Django Part 1\n\n\nDjango REST Framework Image Upload Tutorial (with AngularJS)\n\n\nDjango REST Framework Tutorials\n\n\n\n\nArticles\n\n\n\n\nWeb API performance: Profiling Django REST Framework\n\n\nAPI Development with Django and Django REST Framework\n\n\nIntegrating Pandas, Django REST Framework and Bokeh\n\n\nControlling Uncertainty on Web Applications and APIs\n\n\nFull Text Search in Django REST Framework with Database Backends\n\n\nOAuth2 Authentication with Django REST Framework and Custom Third-Party OAuth2 Backends\n\n\nNested Resources with Django REST Framework\n\n\nImage Fields with Django REST Framework\n\n\nChatbot Using Django REST Framework + api.ai + Slack\u200a\u2014\u200aPart 1/3\n\n\nNew Django Admin with DRF and EmberJS... What are the News?\n\n\nBlog posts about Django REST Framework\n\n\n\n\nBooks\n\n\n\n\nHello Web App: Intermediate Concepts, Chapter 10\n\n\n\n\nDocumentations\n\n\n\n\nClassy Django REST Framework\n\n\nDRF-schema-adapter\n\n\n\n\nWant your Django REST Framework talk/tutorial/article to be added to our website? Or know of a resource that's not yet included here? Please \nsubmit a pull request\n or \nemail us\n!",
+ "text": "Tutorials and Resources\n\n\nThere are a wide range of resources available for learning and using Django REST framework. We try to keep a comprehensive list available here.\n\n\nBooks\n\n\n\n \n\n \n\n \n\n \n\n \n\n \n\n\n\n\n\nTutorials\n\n\n\n\nBeginner's Guide to the Django REST Framework\n\n\nDjango REST Framework - An Introduction\n\n\nDjango REST Framework Tutorial\n\n\nDjango REST Framework Course\n\n\nBuilding a RESTful API with Django REST Framework\n\n\nGetting Started with Django REST Framework and AngularJS\n\n\nEnd to End Web App with Django REST Framework \n AngularJS\n\n\nStart Your API - Django REST Framework Part 1\n\n\nPermissions \n Authentication - Django REST Framework Part 2\n\n\nViewSets and Routers - Django REST Framework Part 3\n\n\nDjango REST Framework User Endpoint\n\n\nCheck Credentials Using Django REST Framework\n\n\nCreating a Production Ready API with Python and Django REST Framework \u2013 Part 1\n\n\nCreating a Production Ready API with Python and Django REST Framework \u2013 Part 2\n\n\n\n\nVideos\n\n\nTalks\n\n\n\n\nHow to Make a Full Fledged REST API with Django OAuth Toolkit\n\n\nDjango REST API - So Easy You Can Learn It in 25 Minutes\n\n\nTom Christie about Django Rest Framework at Django: Under The Hood\n\n\nDjango REST Framework: Schemas, Hypermedia \n Client Libraries\n\n\n\n\nTutorials\n\n\n\n\nDjango REST Framework Part 1\n\n\nDjango REST Framework in Your PJ's!\n\n\nBuilding a REST API Using Django \n Django REST Framework\n\n\nBlog API with Django REST Framework\n\n\nEmber and Django Part 1\n\n\nDjango REST Framework Image Upload Tutorial (with AngularJS)\n\n\nDjango REST Framework Tutorials\n\n\n\n\nArticles\n\n\n\n\nWeb API performance: Profiling Django REST Framework\n\n\nAPI Development with Django and Django REST Framework\n\n\nIntegrating Pandas, Django REST Framework and Bokeh\n\n\nControlling Uncertainty on Web Applications and APIs\n\n\nFull Text Search in Django REST Framework with Database Backends\n\n\nOAuth2 Authentication with Django REST Framework and Custom Third-Party OAuth2 Backends\n\n\nNested Resources with Django REST Framework\n\n\nImage Fields with Django REST Framework\n\n\nChatbot Using Django REST Framework + api.ai + Slack\u200a\u2014\u200aPart 1/3\n\n\nNew Django Admin with DRF and EmberJS... What are the News?\n\n\nBlog posts about Django REST Framework\n\n\n\n\nDocumentations\n\n\n\n\nClassy Django REST Framework\n\n\nDRF-schema-adapter\n\n\n\n\nWant your Django REST Framework talk/tutorial/article to be added to our website? Or know of a resource that's not yet included here? Please \nsubmit a pull request\n or \nemail us\n!",
"title": "Tutorials and Resources"
},
{
@@ -4530,6 +4530,11 @@
"text": "There are a wide range of resources available for learning and using Django REST framework. We try to keep a comprehensive list available here.",
"title": "Tutorials and Resources"
},
+ {
+ "location": "/topics/tutorials-and-resources/#books",
+ "text": "",
+ "title": "Books"
+ },
{
"location": "/topics/tutorials-and-resources/#tutorials",
"text": "Beginner's Guide to the Django REST Framework Django REST Framework - An Introduction Django REST Framework Tutorial Django REST Framework Course Building a RESTful API with Django REST Framework Getting Started with Django REST Framework and AngularJS End to End Web App with Django REST Framework AngularJS Start Your API - Django REST Framework Part 1 Permissions Authentication - Django REST Framework Part 2 ViewSets and Routers - Django REST Framework Part 3 Django REST Framework User Endpoint Check Credentials Using Django REST Framework Creating a Production Ready API with Python and Django REST Framework \u2013 Part 1 Creating a Production Ready API with Python and Django REST Framework \u2013 Part 2",
@@ -4555,11 +4560,6 @@
"text": "Web API performance: Profiling Django REST Framework API Development with Django and Django REST Framework Integrating Pandas, Django REST Framework and Bokeh Controlling Uncertainty on Web Applications and APIs Full Text Search in Django REST Framework with Database Backends OAuth2 Authentication with Django REST Framework and Custom Third-Party OAuth2 Backends Nested Resources with Django REST Framework Image Fields with Django REST Framework Chatbot Using Django REST Framework + api.ai + Slack\u200a\u2014\u200aPart 1/3 New Django Admin with DRF and EmberJS... What are the News? Blog posts about Django REST Framework",
"title": "Articles"
},
- {
- "location": "/topics/tutorials-and-resources/#books",
- "text": "Hello Web App: Intermediate Concepts, Chapter 10",
- "title": "Books"
- },
{
"location": "/topics/tutorials-and-resources/#documentations",
"text": "Classy Django REST Framework DRF-schema-adapter Want your Django REST Framework talk/tutorial/article to be added to our website? Or know of a resource that's not yet included here? Please submit a pull request or email us !",
@@ -4567,7 +4567,7 @@
},
{
"location": "/topics/contributing/",
- "text": "Contributing to REST framework\n\n\n\n\nThe world can only really be changed one piece at a time. The art is picking that piece.\n\n\n \nTim Berners-Lee\n\n\n\n\nThere are many ways you can contribute to Django REST framework. We'd like it to be a community-led project, so please get involved and help shape the future of the project.\n\n\nCommunity\n\n\nThe most important thing you can do to help push the REST framework project forward is to be actively involved wherever possible. Code contributions are often overvalued as being the primary way to get involved in a project, we don't believe that needs to be the case.\n\n\nIf you use REST framework, we'd love you to be vocal about your experiences with it - you might consider writing a blog post about using REST framework, or publishing a tutorial about building a project with a particular JavaScript framework. Experiences from beginners can be particularly helpful because you'll be in the best position to assess which bits of REST framework are more difficult to understand and work with.\n\n\nOther really great ways you can help move the community forward include helping to answer questions on the \ndiscussion group\n, or setting up an \nemail alert on StackOverflow\n so that you get notified of any new questions with the \ndjango-rest-framework\n tag.\n\n\nWhen answering questions make sure to help future contributors find their way around by hyperlinking wherever possible to related threads and tickets, and include backlinks from those items if relevant.\n\n\nCode of conduct\n\n\nPlease keep the tone polite \n professional. For some users a discussion on the REST framework mailing list or ticket tracker may be their first engagement with the open source community. First impressions count, so let's try to make everyone feel welcome.\n\n\nBe mindful in the language you choose. As an example, in an environment that is heavily male-dominated, posts that start 'Hey guys,' can come across as unintentionally exclusive. It's just as easy, and more inclusive to use gender neutral language in those situations.\n\n\nThe \nDjango code of conduct\n gives a fuller set of guidelines for participating in community forums.\n\n\nIssues\n\n\nIt's really helpful if you can make sure to address issues on the correct channel. Usage questions should be directed to the \ndiscussion group\n. Feature requests, bug reports and other issues should be raised on the GitHub \nissue tracker\n.\n\n\nSome tips on good issue reporting:\n\n\n\n\nWhen describing issues try to phrase your ticket in terms of the \nbehavior\n you think needs changing rather than the \ncode\n you think need changing.\n\n\nSearch the issue list first for related items, and make sure you're running the latest version of REST framework before reporting an issue.\n\n\nIf reporting a bug, then try to include a pull request with a failing test case. This will help us quickly identify if there is a valid issue, and make sure that it gets fixed more quickly if there is one.\n\n\nFeature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation.\n\n\nClosing an issue doesn't necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we'll consider if it needs to be reopened.\n\n\n\n\nTriaging issues\n\n\nGetting involved in triaging incoming issues is a good way to start contributing. Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be. Anyone can help out with this, you just need to be willing to\n\n\n\n\nRead through the ticket - does it make sense, is it missing any context that would help explain it better?\n\n\nIs the ticket reported in the correct place, would it be better suited as a discussion on the discussion group?\n\n\nIf the ticket is a bug report, can you reproduce it? Are you able to write a failing test case that demonstrates the issue and that can be submitted as a pull request?\n\n\nIf the ticket is a feature request, do you agree with it, and could the feature request instead be implemented as a third party package?\n\n\nIf a ticket hasn't had much activity and it addresses something you need, then comment on the ticket and try to find out what's needed to get it moving again.\n\n\n\n\nDevelopment\n\n\nTo start developing on Django REST framework, clone the repo:\n\n\ngit clone git@github.com:tomchristie/django-rest-framework.git\n\n\n\nChanges should broadly follow the \nPEP 8\n style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.\n\n\nTesting\n\n\nTo run the tests, clone the repository, and then:\n\n\n# Setup the virtual environment\nvirtualenv env\nsource env/bin/activate\npip install django\npip install -r requirements.txt\n\n# Run the tests\n./runtests.py\n\n\n\nTest options\n\n\nRun using a more concise output style.\n\n\n./runtests.py -q\n\n\n\nRun the tests using a more concise output style, no coverage, no flake8.\n\n\n./runtests.py --fast\n\n\n\nDon't run the flake8 code linting.\n\n\n./runtests.py --nolint\n\n\n\nOnly run the flake8 code linting, don't run the tests.\n\n\n./runtests.py --lintonly\n\n\n\nRun the tests for a given test case.\n\n\n./runtests.py MyTestCase\n\n\n\nRun the tests for a given test method.\n\n\n./runtests.py MyTestCase.test_this_method\n\n\n\nShorter form to run the tests for a given test method.\n\n\n./runtests.py test_this_method\n\n\n\nNote: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.\n\n\nRunning against multiple environments\n\n\nYou can also use the excellent \ntox\n testing tool to run the tests against all supported versions of Python and Django. Install \ntox\n globally, and then simply run:\n\n\ntox\n\n\n\nPull requests\n\n\nIt's a good idea to make pull requests early on. A pull request represents the start of a discussion, and doesn't necessarily need to be the final, finished submission.\n\n\nIt's also always best to make a new branch before starting work on a pull request. This means that you'll be able to later switch back to working on another separate issue without interfering with an ongoing pull requests.\n\n\nIt's also useful to remember that if you have an outstanding pull request then pushing new commits to your GitHub repo will also automatically update the pull requests.\n\n\nGitHub's documentation for working on pull requests is \navailable here\n.\n\n\nAlways run the tests before submitting pull requests, and ideally run \ntox\n in order to check that your modifications are compatible with both Python 2 and Python 3, and that they run properly on all supported versions of Django.\n\n\nOnce you've made a pull request take a look at the Travis build status in the GitHub interface and make sure the tests are running as you'd expect.\n\n\n\n\nAbove: Travis build notifications\n\n\nManaging compatibility issues\n\n\nSometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into the \ncompat.py\n module, and should provide a single common interface that the rest of the codebase can use.\n\n\nDocumentation\n\n\nThe documentation for REST framework is built from the \nMarkdown\n source files in \nthe docs directory\n.\n\n\nThere are many great Markdown editors that make working with the documentation really easy. The \nMou editor for Mac\n is one such editor that comes highly recommended.\n\n\nBuilding the documentation\n\n\nTo build the documentation, install MkDocs with \npip install mkdocs\n and then run the following command.\n\n\nmkdocs build\n\n\n\nThis will build the documentation into the \nsite\n directory.\n\n\nYou can build the documentation and open a preview in a browser window by using the \nserve\n command.\n\n\nmkdocs serve\n\n\n\nLanguage style\n\n\nDocumentation should be in American English. The tone of the documentation is very important - try to stick to a simple, plain, objective and well-balanced style where possible.\n\n\nSome other tips:\n\n\n\n\nKeep paragraphs reasonably short.\n\n\nDon't use abbreviations such as 'e.g.' but instead use the long form, such as 'For example'.\n\n\n\n\nMarkdown style\n\n\nThere are a couple of conventions you should follow when working on the documentation.\n\n\n1. Headers\n\n\nHeaders should use the hash style. For example:\n\n\n### Some important topic\n\n\n\nThe underline style should not be used. \nDon't do this:\n\n\nSome important topic\n====================\n\n\n\n2. Links\n\n\nLinks should always use the reference style, with the referenced hyperlinks kept at the end of the document.\n\n\nHere is a link to [some other thing][other-thing].\n\nMore text...\n\n[other-thing]: http://example.com/other/thing\n\n\n\nThis style helps keep the documentation source consistent and readable.\n\n\nIf you are hyperlinking to another REST framework document, you should use a relative link, and link to the \n.md\n suffix. For example:\n\n\n[authentication]: ../api-guide/authentication.md\n\n\n\nLinking in this style means you'll be able to click the hyperlink in your Markdown editor to open the referenced document. When the documentation is built, these links will be converted into regular links to HTML pages.\n\n\n3. Notes\n\n\nIf you want to draw attention to a note or warning, use a pair of enclosing lines, like so:\n\n\n---\n\n**Note:** A useful documentation note.\n\n---",
+ "text": "Contributing to REST framework\n\n\n\n\nThe world can only really be changed one piece at a time. The art is picking that piece.\n\n\n \nTim Berners-Lee\n\n\n\n\nThere are many ways you can contribute to Django REST framework. We'd like it to be a community-led project, so please get involved and help shape the future of the project.\n\n\nCommunity\n\n\nThe most important thing you can do to help push the REST framework project forward is to be actively involved wherever possible. Code contributions are often overvalued as being the primary way to get involved in a project, we don't believe that needs to be the case.\n\n\nIf you use REST framework, we'd love you to be vocal about your experiences with it - you might consider writing a blog post about using REST framework, or publishing a tutorial about building a project with a particular JavaScript framework. Experiences from beginners can be particularly helpful because you'll be in the best position to assess which bits of REST framework are more difficult to understand and work with.\n\n\nOther really great ways you can help move the community forward include helping to answer questions on the \ndiscussion group\n, or setting up an \nemail alert on StackOverflow\n so that you get notified of any new questions with the \ndjango-rest-framework\n tag.\n\n\nWhen answering questions make sure to help future contributors find their way around by hyperlinking wherever possible to related threads and tickets, and include backlinks from those items if relevant.\n\n\nCode of conduct\n\n\nPlease keep the tone polite \n professional. For some users a discussion on the REST framework mailing list or ticket tracker may be their first engagement with the open source community. First impressions count, so let's try to make everyone feel welcome.\n\n\nBe mindful in the language you choose. As an example, in an environment that is heavily male-dominated, posts that start 'Hey guys,' can come across as unintentionally exclusive. It's just as easy, and more inclusive to use gender neutral language in those situations.\n\n\nThe \nDjango code of conduct\n gives a fuller set of guidelines for participating in community forums.\n\n\nIssues\n\n\nIt's really helpful if you can make sure to address issues on the correct channel. Usage questions should be directed to the \ndiscussion group\n. Feature requests, bug reports and other issues should be raised on the GitHub \nissue tracker\n.\n\n\nSome tips on good issue reporting:\n\n\n\n\nWhen describing issues try to phrase your ticket in terms of the \nbehavior\n you think needs changing rather than the \ncode\n you think need changing.\n\n\nSearch the issue list first for related items, and make sure you're running the latest version of REST framework before reporting an issue.\n\n\nIf reporting a bug, then try to include a pull request with a failing test case. This will help us quickly identify if there is a valid issue, and make sure that it gets fixed more quickly if there is one.\n\n\nFeature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation.\n\n\nClosing an issue doesn't necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we'll consider if it needs to be reopened.\n\n\n\n\nTriaging issues\n\n\nGetting involved in triaging incoming issues is a good way to start contributing. Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be. Anyone can help out with this, you just need to be willing to\n\n\n\n\nRead through the ticket - does it make sense, is it missing any context that would help explain it better?\n\n\nIs the ticket reported in the correct place, would it be better suited as a discussion on the discussion group?\n\n\nIf the ticket is a bug report, can you reproduce it? Are you able to write a failing test case that demonstrates the issue and that can be submitted as a pull request?\n\n\nIf the ticket is a feature request, do you agree with it, and could the feature request instead be implemented as a third party package?\n\n\nIf a ticket hasn't had much activity and it addresses something you need, then comment on the ticket and try to find out what's needed to get it moving again.\n\n\n\n\nDevelopment\n\n\nTo start developing on Django REST framework, clone the repo:\n\n\ngit clone git@github.com:encode/django-rest-framework.git\n\n\n\nChanges should broadly follow the \nPEP 8\n style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.\n\n\nTesting\n\n\nTo run the tests, clone the repository, and then:\n\n\n# Setup the virtual environment\nvirtualenv env\nsource env/bin/activate\npip install django\npip install -r requirements.txt\n\n# Run the tests\n./runtests.py\n\n\n\nTest options\n\n\nRun using a more concise output style.\n\n\n./runtests.py -q\n\n\n\nRun the tests using a more concise output style, no coverage, no flake8.\n\n\n./runtests.py --fast\n\n\n\nDon't run the flake8 code linting.\n\n\n./runtests.py --nolint\n\n\n\nOnly run the flake8 code linting, don't run the tests.\n\n\n./runtests.py --lintonly\n\n\n\nRun the tests for a given test case.\n\n\n./runtests.py MyTestCase\n\n\n\nRun the tests for a given test method.\n\n\n./runtests.py MyTestCase.test_this_method\n\n\n\nShorter form to run the tests for a given test method.\n\n\n./runtests.py test_this_method\n\n\n\nNote: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.\n\n\nRunning against multiple environments\n\n\nYou can also use the excellent \ntox\n testing tool to run the tests against all supported versions of Python and Django. Install \ntox\n globally, and then simply run:\n\n\ntox\n\n\n\nPull requests\n\n\nIt's a good idea to make pull requests early on. A pull request represents the start of a discussion, and doesn't necessarily need to be the final, finished submission.\n\n\nIt's also always best to make a new branch before starting work on a pull request. This means that you'll be able to later switch back to working on another separate issue without interfering with an ongoing pull requests.\n\n\nIt's also useful to remember that if you have an outstanding pull request then pushing new commits to your GitHub repo will also automatically update the pull requests.\n\n\nGitHub's documentation for working on pull requests is \navailable here\n.\n\n\nAlways run the tests before submitting pull requests, and ideally run \ntox\n in order to check that your modifications are compatible with both Python 2 and Python 3, and that they run properly on all supported versions of Django.\n\n\nOnce you've made a pull request take a look at the Travis build status in the GitHub interface and make sure the tests are running as you'd expect.\n\n\n\n\nAbove: Travis build notifications\n\n\nManaging compatibility issues\n\n\nSometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into the \ncompat.py\n module, and should provide a single common interface that the rest of the codebase can use.\n\n\nDocumentation\n\n\nThe documentation for REST framework is built from the \nMarkdown\n source files in \nthe docs directory\n.\n\n\nThere are many great Markdown editors that make working with the documentation really easy. The \nMou editor for Mac\n is one such editor that comes highly recommended.\n\n\nBuilding the documentation\n\n\nTo build the documentation, install MkDocs with \npip install mkdocs\n and then run the following command.\n\n\nmkdocs build\n\n\n\nThis will build the documentation into the \nsite\n directory.\n\n\nYou can build the documentation and open a preview in a browser window by using the \nserve\n command.\n\n\nmkdocs serve\n\n\n\nLanguage style\n\n\nDocumentation should be in American English. The tone of the documentation is very important - try to stick to a simple, plain, objective and well-balanced style where possible.\n\n\nSome other tips:\n\n\n\n\nKeep paragraphs reasonably short.\n\n\nDon't use abbreviations such as 'e.g.' but instead use the long form, such as 'For example'.\n\n\n\n\nMarkdown style\n\n\nThere are a couple of conventions you should follow when working on the documentation.\n\n\n1. Headers\n\n\nHeaders should use the hash style. For example:\n\n\n### Some important topic\n\n\n\nThe underline style should not be used. \nDon't do this:\n\n\nSome important topic\n====================\n\n\n\n2. Links\n\n\nLinks should always use the reference style, with the referenced hyperlinks kept at the end of the document.\n\n\nHere is a link to [some other thing][other-thing].\n\nMore text...\n\n[other-thing]: http://example.com/other/thing\n\n\n\nThis style helps keep the documentation source consistent and readable.\n\n\nIf you are hyperlinking to another REST framework document, you should use a relative link, and link to the \n.md\n suffix. For example:\n\n\n[authentication]: ../api-guide/authentication.md\n\n\n\nLinking in this style means you'll be able to click the hyperlink in your Markdown editor to open the referenced document. When the documentation is built, these links will be converted into regular links to HTML pages.\n\n\n3. Notes\n\n\nIf you want to draw attention to a note or warning, use a pair of enclosing lines, like so:\n\n\n---\n\n**Note:** A useful documentation note.\n\n---",
"title": "Contributing to REST framework"
},
{
@@ -4597,7 +4597,7 @@
},
{
"location": "/topics/contributing/#development",
- "text": "To start developing on Django REST framework, clone the repo: git clone git@github.com:tomchristie/django-rest-framework.git Changes should broadly follow the PEP 8 style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.",
+ "text": "To start developing on Django REST framework, clone the repo: git clone git@github.com:encode/django-rest-framework.git Changes should broadly follow the PEP 8 style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.",
"title": "Development"
},
{
@@ -4662,7 +4662,7 @@
},
{
"location": "/topics/project-management/",
- "text": "Project management\n\n\n\n\n\"No one can whistle a symphony; it takes a whole orchestra to play it\"\n\n\n Halford E. Luccock\n\n\n\n\nThis document outlines our project management processes for REST framework.\n\n\nThe aim is to ensure that the project has a high\n\n\"bus factor\"\n, and can continue to remain well supported for the foreseeable future. Suggestions for improvements to our process are welcome.\n\n\n\n\nMaintenance team\n\n\nWe have a quarterly maintenance cycle where new members may join the maintenance team. We currently cap the size of the team at 5 members, and may encourage folks to step out of the team for a cycle to allow new members to participate.\n\n\nCurrent team\n\n\nThe \nmaintenance team for Q4 2015\n:\n\n\n\n\n@tomchristie\n\n\n@xordoquy\n (Release manager.)\n\n\n@carltongibson\n\n\n@kevin-brown\n\n\n@jpadilla\n\n\n\n\nMaintenance cycles\n\n\nEach maintenance cycle is initiated by an issue being opened with the \nProcess\n label.\n\n\n\n\nTo be considered for a maintainer role simply comment against the issue.\n\n\nExisting members must explicitly opt-in to the next cycle by check-marking their name.\n\n\nThe final decision on the incoming team will be made by \n@tomchristie\n.\n\n\n\n\nMembers of the maintenance team will be added as collaborators to the repository.\n\n\nThe following template should be used for the description of the issue, and serves as the formal process for selecting the team.\n\n\nThis issue is for determining the maintenance team for the *** period.\n\nPlease see the [Project management](http://www.django-rest-framework.org/topics/project-management/) section of our documentation for more details.\n\n---\n\n#### Renewing existing members.\n\nThe following people are the current maintenance team. Please checkmark your name if you wish to continue to have write permission on the repository for the *** period.\n\n- [ ] @***\n- [ ] @***\n- [ ] @***\n- [ ] @***\n- [ ] @***\n\n---\n\n#### New members.\n\nIf you wish to be considered for this or a future date, please comment against this or subsequent issues.\n\nTo modify this process for future maintenance cycles make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation.\n\n\n\nResponsibilities of team members\n\n\nTeam members have the following responsibilities.\n\n\n\n\nClose invalid or resolved tickets.\n\n\nAdd triage labels and milestones to tickets.\n\n\nMerge finalized pull requests.\n\n\nBuild and deploy the documentation, using \nmkdocs gh-deploy\n.\n\n\nBuild and update the included translation packs.\n\n\n\n\nFurther notes for maintainers:\n\n\n\n\nCode changes should come in the form of a pull request - do not push directly to master.\n\n\nMaintainers should typically not merge their own pull requests.\n\n\nEach issue/pull request should have exactly one label once triaged.\n\n\nSearch for un-triaged issues with \nis:open no:label\n.\n\n\n\n\nIt should be noted that participating actively in the REST framework project clearly \ndoes not require being part of the maintenance team\n. Almost every import part of issue triage and project improvement can be actively worked on regardless of your collaborator status on the repository.\n\n\n\n\nRelease process\n\n\nThe release manager is selected on every quarterly maintenance cycle.\n\n\n\n\nThe manager should be selected by \n@tomchristie\n.\n\n\nThe manager will then have the maintainer role added to PyPI package.\n\n\nThe previous manager will then have the maintainer role removed from the PyPI package.\n\n\n\n\nOur PyPI releases will be handled by either the current release manager, or by \n@tomchristie\n. Every release should have an open issue tagged with the \nRelease\n label and marked against the appropriate milestone.\n\n\nThe following template should be used for the description of the issue, and serves as a release checklist.\n\n\nRelease manager is @***.\nPull request is #***.\n\nDuring development cycle:\n\n- [ ] Upload the new content to be translated to [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).\n\n\nChecklist:\n\n- [ ] Create pull request for [release notes](https://github.com/tomchristie/django-rest-framework/blob/master/docs/topics/release-notes.md) based on the [*.*.* milestone](https://github.com/tomchristie/django-rest-framework/milestones/***).\n- [ ] Update the translations from [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).\n- [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/__init__.py).\n- [ ] Confirm with @tomchristie that release is finalized and ready to go.\n- [ ] Ensure that release date is included in pull request.\n- [ ] Merge the release pull request.\n- [ ] Push the package to PyPI with `./setup.py publish`.\n- [ ] Tag the release, with `git tag -a *.*.* -m 'version *.*.*'; git push --tags`.\n- [ ] Deploy the documentation with `mkdocs gh-deploy`.\n- [ ] Make a release announcement on the [discussion group](https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework).\n- [ ] Make a release announcement on twitter.\n- [ ] Close the milestone on GitHub.\n\nTo modify this process for future releases make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation.\n\n\n\nWhen pushing the release to PyPI ensure that your environment has been installed from our development \nrequirement.txt\n, so that documentation and PyPI installs are consistently being built against a pinned set of packages.\n\n\n\n\nTranslations\n\n\nThe maintenance team are responsible for managing the translation packs include in REST framework. Translating the source strings into multiple languages is managed through the \ntransifex service\n.\n\n\nManaging Transifex\n\n\nThe \nofficial Transifex client\n is used to upload and download translations to Transifex. The client is installed using pip:\n\n\npip install transifex-client\n\n\n\nTo use it you'll need a login to Transifex which has a password, and you'll need to have administrative access to the Transifex project. You'll need to create a \n~/.transifexrc\n file which contains your credentials.\n\n\n[https://www.transifex.com]\nusername = ***\ntoken = ***\npassword = ***\nhostname = https://www.transifex.com\n\n\n\nUpload new source files\n\n\nWhen any user visible strings are changed, they should be uploaded to Transifex so that the translators can start to translate them. To do this, just run:\n\n\n# 1. Update the source django.po file, which is the US English version.\ncd rest_framework\ndjango-admin.py makemessages -l en_US\n# 2. Push the source django.po file to Transifex.\ncd ..\ntx push -s\n\n\n\nWhen pushing source files, Transifex will update the source strings of a resource to match those from the new source file.\n\n\nHere's how differences between the old and new source files will be handled:\n\n\n\n\nNew strings will be added.\n\n\nModified strings will be added as well.\n\n\nStrings which do not exist in the new source file will be removed from the database, along with their translations. If that source strings gets re-added later then \nTransifex Translation Memory\n will automatically include the translation string.\n\n\n\n\nDownload translations\n\n\nWhen a translator has finished translating their work needs to be downloaded from Transifex into the REST framework repository. To do this, run:\n\n\n# 3. Pull the translated django.po files from Transifex.\ntx pull -a --minimum-perc 10\ncd rest_framework\n# 4. Compile the binary .mo files for all supported languages.\ndjango-admin.py compilemessages\n\n\n\n\n\nProject requirements\n\n\nAll our test requirements are pinned to exact versions, in order to ensure that our test runs are reproducible. We maintain the requirements in the \nrequirements\n directory. The requirements files are referenced from the \ntox.ini\n configuration file, ensuring we have a single source of truth for package versions used in testing.\n\n\nPackage upgrades should generally be treated as isolated pull requests. You can check if there are any packages available at a newer version, by using the \npip list --outdated\n.\n\n\n\n\nProject ownership\n\n\nThe PyPI package is owned by \n@tomchristie\n. As a backup \n@j4mie\n also has ownership of the package.\n\n\nIf \n@tomchristie\n ceases to participate in the project then \n@j4mie\n has responsibility for handing over ownership duties.\n\n\nOutstanding management \n ownership issues\n\n\nThe following issues still need to be addressed:\n\n\n\n\nConsider moving the repo into a proper GitHub organization\n.\n\n\nEnsure \n@jamie\n has back-up access to the \ndjango-rest-framework.org\n domain setup and admin.\n\n\nDocument ownership of the \nlive example\n API.\n\n\nDocument ownership of the \nmailing list\n and IRC channel.\n\n\nDocument ownership and management of the security mailing list.",
+ "text": "Project management\n\n\n\n\n\"No one can whistle a symphony; it takes a whole orchestra to play it\"\n\n\n Halford E. Luccock\n\n\n\n\nThis document outlines our project management processes for REST framework.\n\n\nThe aim is to ensure that the project has a high\n\n\"bus factor\"\n, and can continue to remain well supported for the foreseeable future. Suggestions for improvements to our process are welcome.\n\n\n\n\nMaintenance team\n\n\nWe have a quarterly maintenance cycle where new members may join the maintenance team. We currently cap the size of the team at 5 members, and may encourage folks to step out of the team for a cycle to allow new members to participate.\n\n\nCurrent team\n\n\nThe \nmaintenance team for Q4 2015\n:\n\n\n\n\n@tomchristie\n\n\n@xordoquy\n (Release manager.)\n\n\n@carltongibson\n\n\n@kevin-brown\n\n\n@jpadilla\n\n\n\n\nMaintenance cycles\n\n\nEach maintenance cycle is initiated by an issue being opened with the \nProcess\n label.\n\n\n\n\nTo be considered for a maintainer role simply comment against the issue.\n\n\nExisting members must explicitly opt-in to the next cycle by check-marking their name.\n\n\nThe final decision on the incoming team will be made by \n@tomchristie\n.\n\n\n\n\nMembers of the maintenance team will be added as collaborators to the repository.\n\n\nThe following template should be used for the description of the issue, and serves as the formal process for selecting the team.\n\n\nThis issue is for determining the maintenance team for the *** period.\n\nPlease see the [Project management](http://www.django-rest-framework.org/topics/project-management/) section of our documentation for more details.\n\n---\n\n#### Renewing existing members.\n\nThe following people are the current maintenance team. Please checkmark your name if you wish to continue to have write permission on the repository for the *** period.\n\n- [ ] @***\n- [ ] @***\n- [ ] @***\n- [ ] @***\n- [ ] @***\n\n---\n\n#### New members.\n\nIf you wish to be considered for this or a future date, please comment against this or subsequent issues.\n\nTo modify this process for future maintenance cycles make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation.\n\n\n\nResponsibilities of team members\n\n\nTeam members have the following responsibilities.\n\n\n\n\nClose invalid or resolved tickets.\n\n\nAdd triage labels and milestones to tickets.\n\n\nMerge finalized pull requests.\n\n\nBuild and deploy the documentation, using \nmkdocs gh-deploy\n.\n\n\nBuild and update the included translation packs.\n\n\n\n\nFurther notes for maintainers:\n\n\n\n\nCode changes should come in the form of a pull request - do not push directly to master.\n\n\nMaintainers should typically not merge their own pull requests.\n\n\nEach issue/pull request should have exactly one label once triaged.\n\n\nSearch for un-triaged issues with \nis:open no:label\n.\n\n\n\n\nIt should be noted that participating actively in the REST framework project clearly \ndoes not require being part of the maintenance team\n. Almost every import part of issue triage and project improvement can be actively worked on regardless of your collaborator status on the repository.\n\n\n\n\nRelease process\n\n\nThe release manager is selected on every quarterly maintenance cycle.\n\n\n\n\nThe manager should be selected by \n@tomchristie\n.\n\n\nThe manager will then have the maintainer role added to PyPI package.\n\n\nThe previous manager will then have the maintainer role removed from the PyPI package.\n\n\n\n\nOur PyPI releases will be handled by either the current release manager, or by \n@tomchristie\n. Every release should have an open issue tagged with the \nRelease\n label and marked against the appropriate milestone.\n\n\nThe following template should be used for the description of the issue, and serves as a release checklist.\n\n\nRelease manager is @***.\nPull request is #***.\n\nDuring development cycle:\n\n- [ ] Upload the new content to be translated to [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).\n\n\nChecklist:\n\n- [ ] Create pull request for [release notes](https://github.com/encode/django-rest-framework/blob/master/docs/topics/release-notes.md) based on the [*.*.* milestone](https://github.com/encode/django-rest-framework/milestones/***).\n- [ ] Update the translations from [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).\n- [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/encode/django-rest-framework/blob/master/rest_framework/__init__.py).\n- [ ] Confirm with @tomchristie that release is finalized and ready to go.\n- [ ] Ensure that release date is included in pull request.\n- [ ] Merge the release pull request.\n- [ ] Push the package to PyPI with `./setup.py publish`.\n- [ ] Tag the release, with `git tag -a *.*.* -m 'version *.*.*'; git push --tags`.\n- [ ] Deploy the documentation with `mkdocs gh-deploy`.\n- [ ] Make a release announcement on the [discussion group](https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework).\n- [ ] Make a release announcement on twitter.\n- [ ] Close the milestone on GitHub.\n\nTo modify this process for future releases make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation.\n\n\n\nWhen pushing the release to PyPI ensure that your environment has been installed from our development \nrequirement.txt\n, so that documentation and PyPI installs are consistently being built against a pinned set of packages.\n\n\n\n\nTranslations\n\n\nThe maintenance team are responsible for managing the translation packs include in REST framework. Translating the source strings into multiple languages is managed through the \ntransifex service\n.\n\n\nManaging Transifex\n\n\nThe \nofficial Transifex client\n is used to upload and download translations to Transifex. The client is installed using pip:\n\n\npip install transifex-client\n\n\n\nTo use it you'll need a login to Transifex which has a password, and you'll need to have administrative access to the Transifex project. You'll need to create a \n~/.transifexrc\n file which contains your credentials.\n\n\n[https://www.transifex.com]\nusername = ***\ntoken = ***\npassword = ***\nhostname = https://www.transifex.com\n\n\n\nUpload new source files\n\n\nWhen any user visible strings are changed, they should be uploaded to Transifex so that the translators can start to translate them. To do this, just run:\n\n\n# 1. Update the source django.po file, which is the US English version.\ncd rest_framework\ndjango-admin.py makemessages -l en_US\n# 2. Push the source django.po file to Transifex.\ncd ..\ntx push -s\n\n\n\nWhen pushing source files, Transifex will update the source strings of a resource to match those from the new source file.\n\n\nHere's how differences between the old and new source files will be handled:\n\n\n\n\nNew strings will be added.\n\n\nModified strings will be added as well.\n\n\nStrings which do not exist in the new source file will be removed from the database, along with their translations. If that source strings gets re-added later then \nTransifex Translation Memory\n will automatically include the translation string.\n\n\n\n\nDownload translations\n\n\nWhen a translator has finished translating their work needs to be downloaded from Transifex into the REST framework repository. To do this, run:\n\n\n# 3. Pull the translated django.po files from Transifex.\ntx pull -a --minimum-perc 10\ncd rest_framework\n# 4. Compile the binary .mo files for all supported languages.\ndjango-admin.py compilemessages\n\n\n\n\n\nProject requirements\n\n\nAll our test requirements are pinned to exact versions, in order to ensure that our test runs are reproducible. We maintain the requirements in the \nrequirements\n directory. The requirements files are referenced from the \ntox.ini\n configuration file, ensuring we have a single source of truth for package versions used in testing.\n\n\nPackage upgrades should generally be treated as isolated pull requests. You can check if there are any packages available at a newer version, by using the \npip list --outdated\n.\n\n\n\n\nProject ownership\n\n\nThe PyPI package is owned by \n@tomchristie\n. As a backup \n@j4mie\n also has ownership of the package.\n\n\nIf \n@tomchristie\n ceases to participate in the project then \n@j4mie\n has responsibility for handing over ownership duties.\n\n\nOutstanding management \n ownership issues\n\n\nThe following issues still need to be addressed:\n\n\n\n\nConsider moving the repo into a proper GitHub organization\n.\n\n\nEnsure \n@jamie\n has back-up access to the \ndjango-rest-framework.org\n domain setup and admin.\n\n\nDocument ownership of the \nlive example\n API.\n\n\nDocument ownership of the \nmailing list\n and IRC channel.\n\n\nDocument ownership and management of the security mailing list.",
"title": "Project management"
},
{
@@ -4692,7 +4692,7 @@
},
{
"location": "/topics/project-management/#release-process",
- "text": "The release manager is selected on every quarterly maintenance cycle. The manager should be selected by @tomchristie . The manager will then have the maintainer role added to PyPI package. The previous manager will then have the maintainer role removed from the PyPI package. Our PyPI releases will be handled by either the current release manager, or by @tomchristie . Every release should have an open issue tagged with the Release label and marked against the appropriate milestone. The following template should be used for the description of the issue, and serves as a release checklist. Release manager is @***.\nPull request is #***.\n\nDuring development cycle:\n\n- [ ] Upload the new content to be translated to [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).\n\n\nChecklist:\n\n- [ ] Create pull request for [release notes](https://github.com/tomchristie/django-rest-framework/blob/master/docs/topics/release-notes.md) based on the [*.*.* milestone](https://github.com/tomchristie/django-rest-framework/milestones/***).\n- [ ] Update the translations from [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).\n- [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/__init__.py).\n- [ ] Confirm with @tomchristie that release is finalized and ready to go.\n- [ ] Ensure that release date is included in pull request.\n- [ ] Merge the release pull request.\n- [ ] Push the package to PyPI with `./setup.py publish`.\n- [ ] Tag the release, with `git tag -a *.*.* -m 'version *.*.*'; git push --tags`.\n- [ ] Deploy the documentation with `mkdocs gh-deploy`.\n- [ ] Make a release announcement on the [discussion group](https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework).\n- [ ] Make a release announcement on twitter.\n- [ ] Close the milestone on GitHub.\n\nTo modify this process for future releases make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation. When pushing the release to PyPI ensure that your environment has been installed from our development requirement.txt , so that documentation and PyPI installs are consistently being built against a pinned set of packages.",
+ "text": "The release manager is selected on every quarterly maintenance cycle. The manager should be selected by @tomchristie . The manager will then have the maintainer role added to PyPI package. The previous manager will then have the maintainer role removed from the PyPI package. Our PyPI releases will be handled by either the current release manager, or by @tomchristie . Every release should have an open issue tagged with the Release label and marked against the appropriate milestone. The following template should be used for the description of the issue, and serves as a release checklist. Release manager is @***.\nPull request is #***.\n\nDuring development cycle:\n\n- [ ] Upload the new content to be translated to [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).\n\n\nChecklist:\n\n- [ ] Create pull request for [release notes](https://github.com/encode/django-rest-framework/blob/master/docs/topics/release-notes.md) based on the [*.*.* milestone](https://github.com/encode/django-rest-framework/milestones/***).\n- [ ] Update the translations from [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).\n- [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/encode/django-rest-framework/blob/master/rest_framework/__init__.py).\n- [ ] Confirm with @tomchristie that release is finalized and ready to go.\n- [ ] Ensure that release date is included in pull request.\n- [ ] Merge the release pull request.\n- [ ] Push the package to PyPI with `./setup.py publish`.\n- [ ] Tag the release, with `git tag -a *.*.* -m 'version *.*.*'; git push --tags`.\n- [ ] Deploy the documentation with `mkdocs gh-deploy`.\n- [ ] Make a release announcement on the [discussion group](https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework).\n- [ ] Make a release announcement on twitter.\n- [ ] Close the milestone on GitHub.\n\nTo modify this process for future releases make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation. When pushing the release to PyPI ensure that your environment has been installed from our development requirement.txt , so that documentation and PyPI installs are consistently being built against a pinned set of packages.",
"title": "Release process"
},
{
@@ -5472,7 +5472,7 @@
},
{
"location": "/topics/release-notes/",
- "text": "Release Notes\n\n\n\n\nRelease Early, Release Often\n\n\n 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 freeze\n:\n\n\npip freeze | grep djangorestframework\n\n\n\n\n\n3.6.x series\n\n\n3.6.2\n\n\nDate\n: \n10th March 2017\n\n\n\n\nSupport for Safari \n 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 glyicon 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 dependancy 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 fallaback 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 \n 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 \n 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 \n 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 \n 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=\nmethod\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 certains 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 \n 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\nDont 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 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 freeze\n:\n\n\npip freeze | grep djangorestframework\n\n\n\n\n\n3.6.x series\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 \n 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 \n 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 glyicon 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 dependancy 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 fallaback 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 \n 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 \n 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 \n 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 \n 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=\nmethod\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 certains 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 \n 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\nDont 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.\n\n\n HEAD\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nmaster",
"title": "Release Notes"
},
{
@@ -5500,6 +5500,11 @@
"text": "",
"title": "3.6.x series"
},
+ {
+ "location": "/topics/release-notes/#363",
+ "text": "Date : 12th May 2017 Raise 404 if a URL lookup results in ValidationError. ( #5126 ) Honor http_method_names on class based view, when generating API schemas. ( #5085 ) Allow overridden get_limit in LimitOffsetPagination to return all records. ( #4437 ) Fix partial update for the ListSerializer. ( #4222 ) Render JSONField control correctly in browsable API. ( #4999 , #5042 ) Raise validation errors for invalid datetime in given timezone. ( #4987 ) Support restricting doc schema shortcuts to a subset of urls. ( #4979 ) Resolve SchemaGenerator error with paginators that have no page_size attribute. ( #5086 , #3692 ) Resolve HyperlinkedRelatedField exception on string with %20 instead of space. ( #4748 , #5078 ) Customizable schema generator classes. ( #5082 ) Update existing vary headers in response instead of overwriting them. ( #5047 ) Support passing .as_view() to view instance. ( #5053 ) Use correct exception handler when settings overridden on a view. ( #5055 , #5054 ) Update Boolean field to support 'yes' and 'no' values. ( #5038 ) Fix unique validator for ChoiceField. ( #5004 , #5026 , #5028 ) JavaScript cleanups in API Docs. ( #5001 ) Include URL path regexs in API schemas where valid. ( #5014 ) Correctly set scheme in coreapi TokenAuthentication. ( #5000 , #4994 ) HEAD requests on ViewSets should not return 405. ( #4705 , #4973 , #4864 ) Support usage of 'source' in extra_kwargs . ( #4688 ) Fix invalid content type for schema.js ( #4968 ) Fix DjangoFilterBackend inheritance issues. ( #5089 , #5117 )",
+ "title": "3.6.3"
+ },
{
"location": "/topics/release-notes/#362",
"text": "Date : 10th March 2017 Support for Safari IE in API docs. ( #4959 , #4961 ) Add missing mark_safe in API docs template tags. ( #4952 , #4953 ) Add missing glyicon fonts. ( #4950 , #4951 ) Fix One-to-one fields in API docs. ( #4955 , #4956 ) Test clean ups. ( #4949 )",
@@ -5709,6 +5714,11 @@
"location": "/topics/release-notes/#300",
"text": "Date : 1st December 2014 For full details see the 3.0 release announcement . For older release notes, please see the version 2.x documentation .",
"title": "3.0.0"
+ },
+ {
+ "location": "/topics/release-notes/#head",
+ "text": "master",
+ "title": "<<<<<<< HEAD"
}
]
}
\ No newline at end of file
diff --git a/sitemap.xml b/sitemap.xml
index a486b5132..347be1645 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -4,7 +4,7 @@
http://www.django-rest-framework.org//
- 2017-03-27
+ 2017-05-12daily
@@ -13,49 +13,49 @@
http://www.django-rest-framework.org//tutorial/quickstart/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//tutorial/1-serialization/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//tutorial/2-requests-and-responses/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//tutorial/3-class-based-views/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//tutorial/4-authentication-and-permissions/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//tutorial/5-relationships-and-hyperlinked-apis/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//tutorial/6-viewsets-and-routers/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//tutorial/7-schemas-and-client-libraries/
- 2017-03-27
+ 2017-05-12daily
@@ -65,163 +65,163 @@
http://www.django-rest-framework.org//api-guide/requests/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/responses/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/views/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/generic-views/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/viewsets/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/routers/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/parsers/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/renderers/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/serializers/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/fields/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/relations/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/validators/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/authentication/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/permissions/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/throttling/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/filtering/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/pagination/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/versioning/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/content-negotiation/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/metadata/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/schemas/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/format-suffixes/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/reverse/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/exceptions/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/status-codes/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/testing/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//api-guide/settings/
- 2017-03-27
+ 2017-05-12daily
@@ -231,145 +231,145 @@
http://www.django-rest-framework.org//topics/documenting-your-api/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/api-clients/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/internationalization/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/ajax-csrf-cors/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/html-and-forms/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/browser-enhancements/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/browsable-api/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/rest-hypermedia-hateoas/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/third-party-packages/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/tutorials-and-resources/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/contributing/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/project-management/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/jobs/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/3.0-announcement/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/3.1-announcement/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/3.2-announcement/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/3.3-announcement/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/3.4-announcement/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/3.5-announcement/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/3.6-announcement/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/kickstarter-announcement/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/mozilla-grant/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/funding/
- 2017-03-27
+ 2017-05-12dailyhttp://www.django-rest-framework.org//topics/release-notes/
- 2017-03-27
+ 2017-05-12daily
diff --git a/topics/3.0-announcement/index.html b/topics/3.0-announcement/index.html
index bc12a8b10..0337d2d7d 100644
--- a/topics/3.0-announcement/index.html
+++ b/topics/3.0-announcement/index.html
@@ -57,7 +57,7 @@
Simple model serializers that are vastly easier to understand and debug, and that make it easy to switch between the implicit ModelSerializer class and the explicit Serializer class.
A new BaseSerializer class, making it easier to write serializers for alternative storage backends, or to completely customize your serialization and validation logic.
A cleaner fields API including new classes such as ListField and MultipleChoiceField.
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.
+
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.
The AJAX based support for the browsable API means that there are a number of internal cleanups in the request class. For the vast majority of developers this should largely remain transparent:
-
To support form based PUT and DELETE, or to support form content types such as JSON, you should now use the AJAX forms javascript library. This replaces the previous 'method and content type overloading' that required significant internal complexity to the request class.
+
To support form based PUT and DELETE, or to support form content types such as JSON, you should now use the AJAX forms javascript library. This replaces the previous 'method and content type overloading' that required significant internal complexity to the request class.
The accept query parameter is no longer supported by the default content negotiation class. If you require it then you'll need to use a custom content negotiation class.
The custom HTTP_X_HTTP_METHOD_OVERRIDE header is no longer supported by default. If you require it then you'll need to use custom middleware.
- GitHub
+ GitHub
Next
@@ -566,10 +566,10 @@ to return a list of available instances to choose from for that relational field
choices information for relational fields.
Many thanks to all our contributors who've been involved in the release, either through raising issues, giving feedback, improving the documentation, or suggesting and implementing code changes.
- GitHub
+ GitHub
Next
@@ -554,7 +554,7 @@ environment is a powerful tool. However in order to do this, you'll need to pay
close attention to how you handle setup and teardown to ensure a strict isolation
of test data from other live or staging data.
Further work on the encoding and documentation generation is planned, in order to
make features such as the 'Try it now' support available at a later date.
An 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.
There are a variety of packages for autocomplete widgets, such as django-autocomplete-light, 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 widget keyword argument since it now uses templated HTML generation.
-
Better support for autocomplete inputs is planned in future versions.
Note that prior to 3.3.0, this support was server-side rather than javascript based. The method overloading style (as used in Ruby on Rails) is no longer supported due to subtle issues that it introduces in request parsing.
Browser-based submission of content types such as JSON are supported by the AJAX form library, using form fields with data-override='content-type' and data-override='content' attributes.
+
Browser-based submission of content types such as JSON are supported by the AJAX form library, using form fields with data-override='content-type' and data-override='content' attributes.
Be mindful in the language you choose. As an example, in an environment that is heavily male-dominated, posts that start 'Hey guys,' can come across as unintentionally exclusive. It's just as easy, and more inclusive to use gender neutral language in those situations.
The Django code of conduct gives a fuller set of guidelines for participating in community forums.
It's really helpful if you can make sure to address issues on the correct channel. Usage questions should be directed to the discussion group. Feature requests, bug reports and other issues should be raised on the GitHub issue tracker.
+
It's really helpful if you can make sure to address issues on the correct channel. Usage questions should be directed to the discussion group. Feature requests, bug reports and other issues should be raised on the GitHub issue tracker.
Some tips on good issue reporting:
When describing issues try to phrase your ticket in terms of the behavior you think needs changing rather than the code you think need changing.
Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into the compat.py module, and should provide a single common interface that the rest of the codebase can use.
There are many great Markdown editors that make working with the documentation really easy. The Mou editor for Mac is one such editor that comes highly recommended.
In an effort to keep the project as transparent as possible, we are releasing monthly progress reports and regularly include financial reports and cost breakdowns.
+
In an effort to keep the project as transparent as possible, we are releasing monthly progress reports and regularly include financial reports and cost breakdowns.
Now create a subfolder for the language you want to translate. The folder should be named using locale name notation. For example: de, pt_BR, es_AR.
-
Now copy the base translations file from the REST framework source code into your translations folder.
+
Now copy the base translations file from the REST framework source code into your translations folder.
Edit the django.po file you've just copied, translating all the error messages.
-
Run manage.py compilemessages -l pt_BR to make the translations
+
Run manage.py compilemessages -l pt_BR to make the translations
available for Django to use. You should see a message like processing file django.po in <...>/locale/pt_BR/LC_MESSAGES.
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.
+
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.
We have a quarterly maintenance cycle where new members may join the maintenance team. We currently cap the size of the team at 5 members, and may encourage folks to step out of the team for a cycle to allow new members to participate.
It should be noted that participating actively in the REST framework project clearly does not require being part of the maintenance team. Almost every import part of issue triage and project improvement can be actively worked on regardless of your collaborator status on the repository.
@@ -507,9 +507,9 @@ During development cycle:
Checklist:
-- [ ] Create pull request for [release notes](https://github.com/tomchristie/django-rest-framework/blob/master/docs/topics/release-notes.md) based on the [*.*.* milestone](https://github.com/tomchristie/django-rest-framework/milestones/***).
+- [ ] Create pull request for [release notes](https://github.com/encode/django-rest-framework/blob/master/docs/topics/release-notes.md) based on the [*.*.* milestone](https://github.com/encode/django-rest-framework/milestones/***).
- [ ] Update the translations from [transifex](http://www.django-rest-framework.org/topics/project-management/#translations).
-- [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/__init__.py).
+- [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/encode/django-rest-framework/blob/master/rest_framework/__init__.py).
- [ ] Confirm with @tomchristie that release is finalized and ready to go.
- [ ] Ensure that release date is included in pull request.
- [ ] Merge the release pull request.
@@ -572,7 +572,7 @@ django-admin.py compilemessages
Remove version string from templates. Thanks to @blag for the report and fixes. (#3878, #3913, #3912)
-
Fixes vertical html layout for BooleanField. Thanks to Mikalai Radchuk for the fix. (#3910)
-
Silenced deprecation warnings on Django 1.8. Thanks to Simon Charette for the fix. (#3903)
-
Internationalization for authtoken. Thanks to Michael Nacharov for the fix. (#3887, #3968)
-
Fix Token model as abstract when the authtoken application isn't declared. Thanks to Adam Thomas for the report. (#3860, #3858)
-
Improve Markdown version compatibility. Thanks to Michael J. Schultz for the fix. (#3604, #3842)
-
QueryParameterVersioning does not use DEFAULT_VERSION setting. Thanks to Brad Montgomery for the fix. (#3833)
-
Add an explicit on_delete on the models. Thanks to Mads Jensen for the fix. (#3832)
-
Fix DateField.to_representation to work with Python 2 unicode. Thanks to Mikalai Radchuk for the fix. (#3819)
-
Fixed TimeField not handling string times. Thanks to Areski Belaid for the fix. (#3809)
-
Avoid updates of Meta.extra_kwargs. Thanks to Kevin Massey for the report and fix. (#3805, #3804)
-
Fix nested validation error being rendered incorrectly. Thanks to Craig de Stigter for the fix. (#3801)
-
Document how to avoid CSRF and missing button issues with django-crispy-forms. Thanks to Emmanuelle Delescolle, José Padilla and Luis San Pablo for the report, analysis and fix. (#3787, #3636, #3637)
-
Improve Rest Framework Settings file setup time. Thanks to Miles Hutson for the report and Mads Jensen for the fix. (#3786, #3815)
-
Improve authtoken compatibility with Django 1.9. Thanks to S. Andrew Sheppard for the fix. (#3785)
-
Fix Min/MaxValueValidator transfer from a model's DecimalField. Thanks to Kevin Brown for the fix. (#3774)
-
Improve HTML title in the Browsable API. Thanks to Mike Lissner for the report and fix. (#3769)
-
Fix AutoFilterSet to inherit from default_filter_set. Thanks to Tom Linford for the fix. (#3753)
-
Fix transifex config to handle the new Chinese language codes. Thanks to @nypisces for the report and fix. (#3739)
-
DateTimeField does not handle empty values correctly. Thanks to Mick Parker for the report and fix. (#3731, #3726)
-
Raise error when setting a removed rest_framework setting. Thanks to Luis San Pablo for the fix. (#3715)
-
Add missing csrf_token in AdminRenderer post form. Thanks to Piotr Śniegowski for the fix. (#3703)
-
Refactored _get_reverse_relationships() to use correct to_field. Thanks to Benjamin Phillips for the fix. (#3696)
-
Document the use of get_queryset for RelatedField. Thanks to Ryan Hiebert for the fix. (#3605)
-
Fix empty pk detection in HyperlinkRelatedField.get_url. Thanks to @jslang for the fix (#3962)
+
Remove version string from templates. Thanks to @blag for the report and fixes. (#3878, #3913, #3912)
+
Fixes vertical html layout for BooleanField. Thanks to Mikalai Radchuk for the fix. (#3910)
+
Silenced deprecation warnings on Django 1.8. Thanks to Simon Charette for the fix. (#3903)
+
Internationalization for authtoken. Thanks to Michael Nacharov for the fix. (#3887, #3968)
+
Fix Token model as abstract when the authtoken application isn't declared. Thanks to Adam Thomas for the report. (#3860, #3858)
+
Improve Markdown version compatibility. Thanks to Michael J. Schultz for the fix. (#3604, #3842)
+
QueryParameterVersioning does not use DEFAULT_VERSION setting. Thanks to Brad Montgomery for the fix. (#3833)
+
Add an explicit on_delete on the models. Thanks to Mads Jensen for the fix. (#3832)
+
Fix DateField.to_representation to work with Python 2 unicode. Thanks to Mikalai Radchuk for the fix. (#3819)
+
Fixed TimeField not handling string times. Thanks to Areski Belaid for the fix. (#3809)
+
Avoid updates of Meta.extra_kwargs. Thanks to Kevin Massey for the report and fix. (#3805, #3804)
+
Fix nested validation error being rendered incorrectly. Thanks to Craig de Stigter for the fix. (#3801)
+
Document how to avoid CSRF and missing button issues with django-crispy-forms. Thanks to Emmanuelle Delescolle, José Padilla and Luis San Pablo for the report, analysis and fix. (#3787, #3636, #3637)
+
Improve Rest Framework Settings file setup time. Thanks to Miles Hutson for the report and Mads Jensen for the fix. (#3786, #3815)
+
Improve authtoken compatibility with Django 1.9. Thanks to S. Andrew Sheppard for the fix. (#3785)
+
Fix Min/MaxValueValidator transfer from a model's DecimalField. Thanks to Kevin Brown for the fix. (#3774)
+
Improve HTML title in the Browsable API. Thanks to Mike Lissner for the report and fix. (#3769)
+
Fix AutoFilterSet to inherit from default_filter_set. Thanks to Tom Linford for the fix. (#3753)
+
Fix transifex config to handle the new Chinese language codes. Thanks to @nypisces for the report and fix. (#3739)
+
DateTimeField does not handle empty values correctly. Thanks to Mick Parker for the report and fix. (#3731, #3726)
+
Raise error when setting a removed rest_framework setting. Thanks to Luis San Pablo for the fix. (#3715)
+
Add missing csrf_token in AdminRenderer post form. Thanks to Piotr Śniegowski for the fix. (#3703)
+
Refactored _get_reverse_relationships() to use correct to_field. Thanks to Benjamin Phillips for the fix. (#3696)
+
Document the use of get_queryset for RelatedField. Thanks to Ryan Hiebert for the fix. (#3605)
+
Fix empty pk detection in HyperlinkRelatedField.get_url. Thanks to @jslang for the fix (#3962)
Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into a compat.py module, and should provide a single common interface that the rest of the codebase can use.
-
Check out Django REST framework's compat.py for an example.
+
Check out Django REST framework's compat.py for an example.
Create a Pull Request or Issue on GitHub, and we'll add a link to it from the main REST framework documentation. You can add your package under Third party packages of the API Guide section that best applies, like Authentication or Permissions. You can also link your package under the Third Party Packages section.
+
Create a Pull Request or Issue on GitHub, and we'll add a link to it from the main REST framework documentation. You can add your package under Third party packages of the API Guide section that best applies, like Authentication or Permissions. You can also link your package under the Third Party Packages section.
@@ -537,6 +537,7 @@ You probably want to also tag the version now:
djoser - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.
django-rest-auth - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc.
drf-oidc-auth - Implements OpenID Connect token authentication for DRF.
+
drfpasswordless - Adds (Medium, Square Cash inspired) passwordless logins and signups via email and mobile numbers.
Want your Django REST Framework talk/tutorial/article to be added to our website? Or know of a resource that's not yet included here? Please submit a pull request or email us!
+
Want your Django REST Framework talk/tutorial/article to be added to our website? Or know of a resource that's not yet included here? Please submit a pull request or email us!
This tutorial will cover creating a simple pastebin code highlighting Web API. Along the way it will introduce the various components that make up REST framework, and give you a comprehensive understanding of how everything fits together.
The tutorial is fairly in-depth, so you should probably get a cookie and a cup of your favorite brew before getting started. If you just want a quick overview, you should head over to the quickstart documentation instead.
-
Note: The code for this tutorial is available in the tomchristie/rest-framework-tutorial repository on GitHub. The completed implementation is also online as a sandbox version for testing, available here.
+
Note: The code for this tutorial is available in the tomchristie/rest-framework-tutorial repository on GitHub. The completed implementation is also online as a sandbox version for testing, available here.
Before we do anything else we'll create a new virtual environment, using virtualenv. This will make sure our package configuration is kept nicely isolated from any other projects we're working on.
@@ -696,7 +696,7 @@ urlpatterns = [
Validating models...
0 errors found
-Django version 1.8.3, using settings 'tutorial.settings'
+Django version 1.11, using settings 'tutorial.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
diff --git a/tutorial/2-requests-and-responses/index.html b/tutorial/2-requests-and-responses/index.html
index abb06c42e..ffc5d6624 100644
--- a/tutorial/2-requests-and-responses/index.html
+++ b/tutorial/2-requests-and-responses/index.html
@@ -57,7 +57,7 @@
- GitHub
+ GitHub
Next
diff --git a/tutorial/3-class-based-views/index.html b/tutorial/3-class-based-views/index.html
index 5abd75c67..aa738fd4d 100644
--- a/tutorial/3-class-based-views/index.html
+++ b/tutorial/3-class-based-views/index.html
@@ -57,7 +57,7 @@
- GitHub
+ GitHub
Next
diff --git a/tutorial/4-authentication-and-permissions/index.html b/tutorial/4-authentication-and-permissions/index.html
index 2ee627074..a1424b180 100644
--- a/tutorial/4-authentication-and-permissions/index.html
+++ b/tutorial/4-authentication-and-permissions/index.html
@@ -57,7 +57,7 @@
- GitHub
+ GitHub
Next
diff --git a/tutorial/5-relationships-and-hyperlinked-apis/index.html b/tutorial/5-relationships-and-hyperlinked-apis/index.html
index 6b6479c9a..899b842a0 100644
--- a/tutorial/5-relationships-and-hyperlinked-apis/index.html
+++ b/tutorial/5-relationships-and-hyperlinked-apis/index.html
@@ -57,7 +57,7 @@
- GitHub
+ GitHub
Next
diff --git a/tutorial/6-viewsets-and-routers/index.html b/tutorial/6-viewsets-and-routers/index.html
index afbf213d0..654d31f00 100644
--- a/tutorial/6-viewsets-and-routers/index.html
+++ b/tutorial/6-viewsets-and-routers/index.html
@@ -57,7 +57,7 @@
- GitHub
+ GitHub
Next
diff --git a/tutorial/7-schemas-and-client-libraries/index.html b/tutorial/7-schemas-and-client-libraries/index.html
index af429c6cf..c0b30bc58 100644
--- a/tutorial/7-schemas-and-client-libraries/index.html
+++ b/tutorial/7-schemas-and-client-libraries/index.html
@@ -57,7 +57,7 @@
With an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browsable, includes a schema-driven client library, and comes complete with authentication, per-object permissions, and multiple renderer formats.
We've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views.