From 74fbc7a70834399a81e37a3b99ab8f88b1796f18 Mon Sep 17 00:00:00 2001
From: Tom Christie drf-schema-adapter is a set of tools that makes it easier to provide schema information to frontend frameworks and libraries. It provides a metadata mixin as well as 2 metadata classes and several adapters suitable to generate json-schema as well as schema information readable by various libraries. You can also write your own adapter to work with your specific frontend.
-If you whish to do so, it also provides an exporter that can export those schema information to json files.DRF-schema-adapter
The REST Condition package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.
The DRY Rest Permissions package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrive per user.
+The DRY Rest Permissions package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrieve per user.
The Django Rest Framework Roles package makes it easier to parameterize your API over multiple types of users.
+The Django Rest Framework API Key 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.
^users/{pk}/change-password/$
Name: 'user-change-password'
In 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.
+For example, if you want to change the name of our custom action to 'user-change-password'
, you could write:
from myapp.permissions import IsAdminOrIsSelf
+from rest_framework.decorators import detail_route
+
+class UserViewSet(ModelViewSet):
+ ...
+
+ @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_name='change-password')
+ def set_password(self, request, pk=None):
+ ...
+
+The above example would now generate the following URL pattern:
+^users/{pk}/set_password/$
Name: 'user-change-password'
You can also use url_path and url_name parameters together to obtain extra control on URL generation for custom views.
For more information see the viewset documentation on marking extra actions for routing.
urlconf
A string representing the import path to the URL conf that you want +to generate an API schema for. This defaults to the value of Django's +ROOT_URLCONF setting.
+schema_view = get_schema_view(
+ title='Server Monitoring API',
+ url='https://www.example.org/api/',
+ urlconf='myproject.urls'
+)
+
renderer_classes
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
diff --git a/api-guide/serializers/index.html b/api-guide/serializers/index.html
index c5b64f58b..296584b74 100644
--- a/api-guide/serializers/index.html
+++ b/api-guide/serializers/index.html
@@ -4,7 +4,6 @@
-
Serializers - Django REST framework
@@ -1481,7 +1480,7 @@ blacklisted and child serializers can be optionally expanded.
DRF-Base64
DRF-Base64 provides a set of field and model serializers that handles the upload of base64-encoded files.
QueryFields
-djangorestframework-queryfields allows API clients to specify which fields will be sent in the response via inclusion or exclusion query paramaters.
+djangorestframework-queryfields allows API clients to specify which fields will be sent in the response via inclusion/exclusion query parameters.
diff --git a/api-guide/settings/index.html b/api-guide/settings/index.html
index 51be6188a..37b4f4e71 100644
--- a/api-guide/settings/index.html
+++ b/api-guide/settings/index.html
@@ -4,7 +4,6 @@
-
Settings - Django REST framework
@@ -595,7 +594,7 @@ If set to None
then generic filtering is disabled.
If set, this maps the 'pk'
identifier in the URL conf onto the actual field
name when generating a schema path parameter. Typically this will be 'id'
.
This gives a more suitable representation as "primary key" is an implementation
-detail, wheras "identifier" is a more general concept.
+detail, whereas "identifier" is a more general concept.
Default: True
SCHEMA_COERCE_METHOD_NAMES
If set, this is used to map internal viewset method names onto external action
diff --git a/api-guide/status-codes/index.html b/api-guide/status-codes/index.html
index b6ac431b2..294b4c915 100644
--- a/api-guide/status-codes/index.html
+++ b/api-guide/status-codes/index.html
@@ -4,7 +4,6 @@
-
Status codes - Django REST framework
diff --git a/api-guide/testing/index.html b/api-guide/testing/index.html
index c2274d566..c2a8bc044 100644
--- a/api-guide/testing/index.html
+++ b/api-guide/testing/index.html
@@ -4,7 +4,6 @@
-
Testing - Django REST framework
diff --git a/api-guide/throttling/index.html b/api-guide/throttling/index.html
index 2bd521124..0057e4038 100644
--- a/api-guide/throttling/index.html
+++ b/api-guide/throttling/index.html
@@ -4,7 +4,6 @@
-
Throttling - Django REST framework
diff --git a/api-guide/validators/index.html b/api-guide/validators/index.html
index c5a5efbc3..307dde9ed 100644
--- a/api-guide/validators/index.html
+++ b/api-guide/validators/index.html
@@ -4,7 +4,6 @@
-
Validators - Django REST framework
diff --git a/api-guide/versioning/index.html b/api-guide/versioning/index.html
index 754056133..b635fbced 100644
--- a/api-guide/versioning/index.html
+++ b/api-guide/versioning/index.html
@@ -4,7 +4,6 @@
-
Versioning - Django REST framework
diff --git a/api-guide/views/index.html b/api-guide/views/index.html
index 2fb730bd0..4e57a6549 100644
--- a/api-guide/views/index.html
+++ b/api-guide/views/index.html
@@ -4,7 +4,6 @@
-
Views - Django REST framework
diff --git a/api-guide/viewsets/index.html b/api-guide/viewsets/index.html
index d367ddf6c..67779867f 100644
--- a/api-guide/viewsets/index.html
+++ b/api-guide/viewsets/index.html
@@ -4,7 +4,6 @@
-
Viewsets - Django REST framework
diff --git a/base.html b/base.html
index f621ee042..6cb929d1c 100644
--- a/base.html
+++ b/base.html
@@ -4,7 +4,6 @@
-
{% if page_title %}{{ page_title }} - {% endif %}{{ site_name }}
diff --git a/index.html b/index.html
index 677a5d029..6162c1947 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,6 @@
-
Django REST framework
@@ -529,7 +528,7 @@ continued development by signing up for a paid
-Many thanks to all our wonderful sponsors, and in particular to our premium backers, Rover, Sentry, Stream, and Machinalis.
+Many thanks to all our wonderful sponsors, and in particular to our premium backers, Rover, Sentry, Stream, and Machinalis.
Requirements
REST framework requires the following:
diff --git a/mkdocs/search_index.json b/mkdocs/search_index.json
index 5b989f5a8..ced3d7d65 100644
--- a/mkdocs/search_index.json
+++ b/mkdocs/search_index.json
@@ -222,7 +222,7 @@
},
{
"location": "/tutorial/3-class-based-views/",
- "text": "Tutorial 3: Class-based Views\n\n\nWe can also write our API views using class-based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code \nDRY\n.\n\n\nRewriting our API using class-based views\n\n\nWe'll start by rewriting the root view as a class-based view. All this involves is a little bit of refactoring of \nviews.py\n.\n\n\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom django.http import Http404\nfrom rest_framework.views import APIView\nfrom rest_framework.response import Response\nfrom rest_framework import status\n\n\nclass SnippetList(APIView):\n \"\"\"\n List all snippets, or create a new snippet.\n \"\"\"\n def get(self, request, format=None):\n snippets = Snippet.objects.all()\n serializer = SnippetSerializer(snippets, many=True)\n return Response(serializer.data)\n\n def post(self, request, format=None):\n serializer = SnippetSerializer(data=request.data)\n if serializer.is_valid():\n serializer.save()\n return Response(serializer.data, status=status.HTTP_201_CREATED)\n return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\n\n\nSo far, so good. It looks pretty similar to the previous case, but we've got better separation between the different HTTP methods. We'll also need to update the instance view in \nviews.py\n.\n\n\nclass SnippetDetail(APIView):\n \"\"\"\n Retrieve, update or delete a snippet instance.\n \"\"\"\n def get_object(self, pk):\n try:\n return Snippet.objects.get(pk=pk)\n except Snippet.DoesNotExist:\n raise Http404\n\n def get(self, request, pk, format=None):\n snippet = self.get_object(pk)\n serializer = SnippetSerializer(snippet)\n return Response(serializer.data)\n\n def put(self, request, pk, format=None):\n snippet = self.get_object(pk)\n serializer = SnippetSerializer(snippet, data=request.data)\n if serializer.is_valid():\n serializer.save()\n return Response(serializer.data)\n return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\n def delete(self, request, pk, format=None):\n snippet = self.get_object(pk)\n snippet.delete()\n return Response(status=status.HTTP_204_NO_CONTENT)\n\n\n\nThat's looking good. Again, it's still pretty similar to the function based view right now.\n\n\nWe'll also need to refactor our \nurls.py\n slightly now we're using class-based views.\n\n\nfrom django.conf.urls import url\nfrom rest_framework.urlpatterns import format_suffix_patterns\nfrom snippets import views\n\nurlpatterns = [\n url(r'^snippets/$', views.SnippetList.as_view()),\n url(r'^snippets/(?P\npk\n[0-9]+)/$', views.SnippetDetail.as_view()),\n]\n\nurlpatterns = format_suffix_patterns(urlpatterns)\n\n\n\nOkay, we're done. If you run the development server everything should be working just as before.\n\n\nUsing mixins\n\n\nOne of the big wins of using class-based views is that it allows us to easily compose reusable bits of behaviour.\n\n\nThe create/retrieve/update/delete operations that we've been using so far are going to be pretty similar for any model-backed API views we create. Those bits of common behaviour are implemented in REST framework's mixin classes.\n\n\nLet's take a look at how we can compose the views by using the mixin classes. Here's our \nviews.py\n module again.\n\n\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom rest_framework import mixins\nfrom rest_framework import generics\n\nclass SnippetList(mixins.ListModelMixin,\n mixins.CreateModelMixin,\n generics.GenericAPIView):\n queryset = Snippet.objects.all()\n serializer_class = SnippetSerializer\n\n def get(self, request, *args, **kwargs):\n return self.list(request, *args, **kwargs)\n\n def post(self, request, *args, **kwargs):\n return self.create(request, *args, **kwargs)\n\n\n\nWe'll take a moment to examine exactly what's happening here. We're building our view using \nGenericAPIView\n, and adding in \nListModelMixin\n and \nCreateModelMixin\n.\n\n\nThe base class provides the core functionality, and the mixin classes provide the \n.list()\n and \n.create()\n actions. We're then explicitly binding the \nget\n and \npost\n methods to the appropriate actions. Simple enough stuff so far.\n\n\nclass SnippetDetail(mixins.RetrieveModelMixin,\n mixins.UpdateModelMixin,\n mixins.DestroyModelMixin,\n generics.GenericAPIView):\n queryset = Snippet.objects.all()\n serializer_class = SnippetSerializer\n\n def get(self, request, *args, **kwargs):\n return self.retrieve(request, *args, **kwargs)\n\n def put(self, request, *args, **kwargs):\n return self.update(request, *args, **kwargs)\n\n def delete(self, request, *args, **kwargs):\n return self.destroy(request, *args, **kwargs)\n\n\n\nPretty similar. Again we're using the \nGenericAPIView\n class to provide the core functionality, and adding in mixins to provide the \n.retrieve()\n, \n.update()\n and \n.destroy()\n actions.\n\n\nUsing generic class-based views\n\n\nUsing the mixin classes we've rewritten the views to use slightly less code than before, but we can go one step further. REST framework provides a set of already mixed-in generic views that we can use to trim down our \nviews.py\n module even more.\n\n\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom rest_framework import generics\n\n\nclass SnippetList(generics.ListCreateAPIView):\n queryset = Snippet.objects.all()\n serializer_class = SnippetSerializer\n\n\nclass SnippetDetail(generics.RetrieveUpdateDestroyAPIView):\n queryset = Snippet.objects.all()\n serializer_class = SnippetSerializer\n\n\n\nWow, that's pretty concise. We've gotten a huge amount for free, and our code looks like good, clean, idiomatic Django.\n\n\nNext we'll move onto \npart 4 of the tutorial\n, where we'll take a look at how we can deal with authentication and permissions for our API.",
+ "text": "Tutorial 3: Class-based Views\n\n\nWe can also write our API views using class-based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code \nDRY\n.\n\n\nRewriting our API using class-based views\n\n\nWe'll start by rewriting the root view as a class-based view. All this involves is a little bit of refactoring of \nviews.py\n.\n\n\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom django.http import Http404\nfrom rest_framework.views import APIView\nfrom rest_framework.response import Response\nfrom rest_framework import status\n\n\nclass SnippetList(APIView):\n \"\"\"\n List all snippets, or create a new snippet.\n \"\"\"\n def get(self, request, format=None):\n snippets = Snippet.objects.all()\n serializer = SnippetSerializer(snippets, many=True)\n return Response(serializer.data)\n\n def post(self, request, format=None):\n serializer = SnippetSerializer(data=request.data)\n if serializer.is_valid():\n serializer.save()\n return Response(serializer.data, status=status.HTTP_201_CREATED)\n return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\n\n\nSo far, so good. It looks pretty similar to the previous case, but we've got better separation between the different HTTP methods. We'll also need to update the instance view in \nviews.py\n.\n\n\nclass SnippetDetail(APIView):\n \"\"\"\n Retrieve, update or delete a snippet instance.\n \"\"\"\n def get_object(self, pk):\n try:\n return Snippet.objects.get(pk=pk)\n except Snippet.DoesNotExist:\n raise Http404\n\n def get(self, request, pk, format=None):\n snippet = self.get_object(pk)\n serializer = SnippetSerializer(snippet)\n return Response(serializer.data)\n\n def put(self, request, pk, format=None):\n snippet = self.get_object(pk)\n serializer = SnippetSerializer(snippet, data=request.data)\n if serializer.is_valid():\n serializer.save()\n return Response(serializer.data)\n return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\n def delete(self, request, pk, format=None):\n snippet = self.get_object(pk)\n snippet.delete()\n return Response(status=status.HTTP_204_NO_CONTENT)\n\n\n\nThat's looking good. Again, it's still pretty similar to the function based view right now.\n\n\nWe'll also need to refactor our \nurls.py\n slightly now that we're using class-based views.\n\n\nfrom django.conf.urls import url\nfrom rest_framework.urlpatterns import format_suffix_patterns\nfrom snippets import views\n\nurlpatterns = [\n url(r'^snippets/$', views.SnippetList.as_view()),\n url(r'^snippets/(?P\npk\n[0-9]+)/$', views.SnippetDetail.as_view()),\n]\n\nurlpatterns = format_suffix_patterns(urlpatterns)\n\n\n\nOkay, we're done. If you run the development server everything should be working just as before.\n\n\nUsing mixins\n\n\nOne of the big wins of using class-based views is that it allows us to easily compose reusable bits of behaviour.\n\n\nThe create/retrieve/update/delete operations that we've been using so far are going to be pretty similar for any model-backed API views we create. Those bits of common behaviour are implemented in REST framework's mixin classes.\n\n\nLet's take a look at how we can compose the views by using the mixin classes. Here's our \nviews.py\n module again.\n\n\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom rest_framework import mixins\nfrom rest_framework import generics\n\nclass SnippetList(mixins.ListModelMixin,\n mixins.CreateModelMixin,\n generics.GenericAPIView):\n queryset = Snippet.objects.all()\n serializer_class = SnippetSerializer\n\n def get(self, request, *args, **kwargs):\n return self.list(request, *args, **kwargs)\n\n def post(self, request, *args, **kwargs):\n return self.create(request, *args, **kwargs)\n\n\n\nWe'll take a moment to examine exactly what's happening here. We're building our view using \nGenericAPIView\n, and adding in \nListModelMixin\n and \nCreateModelMixin\n.\n\n\nThe base class provides the core functionality, and the mixin classes provide the \n.list()\n and \n.create()\n actions. We're then explicitly binding the \nget\n and \npost\n methods to the appropriate actions. Simple enough stuff so far.\n\n\nclass SnippetDetail(mixins.RetrieveModelMixin,\n mixins.UpdateModelMixin,\n mixins.DestroyModelMixin,\n generics.GenericAPIView):\n queryset = Snippet.objects.all()\n serializer_class = SnippetSerializer\n\n def get(self, request, *args, **kwargs):\n return self.retrieve(request, *args, **kwargs)\n\n def put(self, request, *args, **kwargs):\n return self.update(request, *args, **kwargs)\n\n def delete(self, request, *args, **kwargs):\n return self.destroy(request, *args, **kwargs)\n\n\n\nPretty similar. Again we're using the \nGenericAPIView\n class to provide the core functionality, and adding in mixins to provide the \n.retrieve()\n, \n.update()\n and \n.destroy()\n actions.\n\n\nUsing generic class-based views\n\n\nUsing the mixin classes we've rewritten the views to use slightly less code than before, but we can go one step further. REST framework provides a set of already mixed-in generic views that we can use to trim down our \nviews.py\n module even more.\n\n\nfrom snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom rest_framework import generics\n\n\nclass SnippetList(generics.ListCreateAPIView):\n queryset = Snippet.objects.all()\n serializer_class = SnippetSerializer\n\n\nclass SnippetDetail(generics.RetrieveUpdateDestroyAPIView):\n queryset = Snippet.objects.all()\n serializer_class = SnippetSerializer\n\n\n\nWow, that's pretty concise. We've gotten a huge amount for free, and our code looks like good, clean, idiomatic Django.\n\n\nNext we'll move onto \npart 4 of the tutorial\n, where we'll take a look at how we can deal with authentication and permissions for our API.",
"title": "3 - Class based views"
},
{
@@ -232,7 +232,7 @@
},
{
"location": "/tutorial/3-class-based-views/#rewriting-our-api-using-class-based-views",
- "text": "We'll start by rewriting the root view as a class-based view. All this involves is a little bit of refactoring of views.py . from snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom django.http import Http404\nfrom rest_framework.views import APIView\nfrom rest_framework.response import Response\nfrom rest_framework import status\n\n\nclass SnippetList(APIView):\n \"\"\"\n List all snippets, or create a new snippet.\n \"\"\"\n def get(self, request, format=None):\n snippets = Snippet.objects.all()\n serializer = SnippetSerializer(snippets, many=True)\n return Response(serializer.data)\n\n def post(self, request, format=None):\n serializer = SnippetSerializer(data=request.data)\n if serializer.is_valid():\n serializer.save()\n return Response(serializer.data, status=status.HTTP_201_CREATED)\n return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) So far, so good. It looks pretty similar to the previous case, but we've got better separation between the different HTTP methods. We'll also need to update the instance view in views.py . class SnippetDetail(APIView):\n \"\"\"\n Retrieve, update or delete a snippet instance.\n \"\"\"\n def get_object(self, pk):\n try:\n return Snippet.objects.get(pk=pk)\n except Snippet.DoesNotExist:\n raise Http404\n\n def get(self, request, pk, format=None):\n snippet = self.get_object(pk)\n serializer = SnippetSerializer(snippet)\n return Response(serializer.data)\n\n def put(self, request, pk, format=None):\n snippet = self.get_object(pk)\n serializer = SnippetSerializer(snippet, data=request.data)\n if serializer.is_valid():\n serializer.save()\n return Response(serializer.data)\n return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\n def delete(self, request, pk, format=None):\n snippet = self.get_object(pk)\n snippet.delete()\n return Response(status=status.HTTP_204_NO_CONTENT) That's looking good. Again, it's still pretty similar to the function based view right now. We'll also need to refactor our urls.py slightly now we're using class-based views. from django.conf.urls import url\nfrom rest_framework.urlpatterns import format_suffix_patterns\nfrom snippets import views\n\nurlpatterns = [\n url(r'^snippets/$', views.SnippetList.as_view()),\n url(r'^snippets/(?P pk [0-9]+)/$', views.SnippetDetail.as_view()),\n]\n\nurlpatterns = format_suffix_patterns(urlpatterns) Okay, we're done. If you run the development server everything should be working just as before.",
+ "text": "We'll start by rewriting the root view as a class-based view. All this involves is a little bit of refactoring of views.py . from snippets.models import Snippet\nfrom snippets.serializers import SnippetSerializer\nfrom django.http import Http404\nfrom rest_framework.views import APIView\nfrom rest_framework.response import Response\nfrom rest_framework import status\n\n\nclass SnippetList(APIView):\n \"\"\"\n List all snippets, or create a new snippet.\n \"\"\"\n def get(self, request, format=None):\n snippets = Snippet.objects.all()\n serializer = SnippetSerializer(snippets, many=True)\n return Response(serializer.data)\n\n def post(self, request, format=None):\n serializer = SnippetSerializer(data=request.data)\n if serializer.is_valid():\n serializer.save()\n return Response(serializer.data, status=status.HTTP_201_CREATED)\n return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) So far, so good. It looks pretty similar to the previous case, but we've got better separation between the different HTTP methods. We'll also need to update the instance view in views.py . class SnippetDetail(APIView):\n \"\"\"\n Retrieve, update or delete a snippet instance.\n \"\"\"\n def get_object(self, pk):\n try:\n return Snippet.objects.get(pk=pk)\n except Snippet.DoesNotExist:\n raise Http404\n\n def get(self, request, pk, format=None):\n snippet = self.get_object(pk)\n serializer = SnippetSerializer(snippet)\n return Response(serializer.data)\n\n def put(self, request, pk, format=None):\n snippet = self.get_object(pk)\n serializer = SnippetSerializer(snippet, data=request.data)\n if serializer.is_valid():\n serializer.save()\n return Response(serializer.data)\n return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\n def delete(self, request, pk, format=None):\n snippet = self.get_object(pk)\n snippet.delete()\n return Response(status=status.HTTP_204_NO_CONTENT) That's looking good. Again, it's still pretty similar to the function based view right now. We'll also need to refactor our urls.py slightly now that we're using class-based views. from django.conf.urls import url\nfrom rest_framework.urlpatterns import format_suffix_patterns\nfrom snippets import views\n\nurlpatterns = [\n url(r'^snippets/$', views.SnippetList.as_view()),\n url(r'^snippets/(?P pk [0-9]+)/$', views.SnippetDetail.as_view()),\n]\n\nurlpatterns = format_suffix_patterns(urlpatterns) Okay, we're done. If you run the development server everything should be working just as before.",
"title": "Rewriting our API using class-based views"
},
{
@@ -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\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):\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"
},
{
@@ -972,7 +972,7 @@
},
{
"location": "/api-guide/routers/#extra-link-and-actions",
- "text": "Any methods on the viewset decorated with @detail_route or @list_route will also be routed.\nFor example, given a method like this on the UserViewSet class: from 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 ... The following URL pattern would additionally be generated: URL pattern: ^users/{pk}/set_password/$ Name: 'user-set-password' If 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. For example, if you want to change the URL for our custom action to ^users/{pk}/change-password/$ , you could write: from 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 ... The above example would now generate the following URL pattern: URL pattern: ^users/{pk}/change-password/$ Name: 'user-change-password' For more information see the viewset documentation on marking extra actions for routing .",
+ "text": "Any methods on the viewset decorated with @detail_route or @list_route will also be routed.\nFor example, given a method like this on the UserViewSet class: from 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 ... The following URL pattern would additionally be generated: URL pattern: ^users/{pk}/set_password/$ Name: 'user-set-password' If 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. For example, if you want to change the URL for our custom action to ^users/{pk}/change-password/$ , you could write: from 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 ... The above example would now generate the following URL pattern: URL pattern: ^users/{pk}/change-password/$ Name: 'user-change-password' In 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. For example, if you want to change the name of our custom action to 'user-change-password' , you could write: from 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 ... The above example would now generate the following URL pattern: URL pattern: ^users/{pk}/set_password/$ Name: 'user-change-password' You can also use url_path and url_name parameters together to obtain extra control on URL generation for custom views. For more information see the viewset documentation on marking extra actions for routing .",
"title": "Extra link and actions"
},
{
@@ -1337,7 +1337,7 @@
},
{
"location": "/api-guide/serializers/",
- "text": "Serializers\n\n\n\n\nExpanding the usefulness of the serializers is something that we would\nlike to address. However, it's not a trivial problem, and it\nwill take some serious design work.\n\n\n Russell Keith-Magee, \nDjango users group\n\n\n\n\nSerializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into \nJSON\n, \nXML\n or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.\n\n\nThe serializers in REST framework work very similarly to Django's \nForm\n and \nModelForm\n classes. We provide a \nSerializer\n class which gives you a powerful, generic way to control the output of your responses, as well as a \nModelSerializer\n class which provides a useful shortcut for creating serializers that deal with model instances and querysets.\n\n\nDeclaring Serializers\n\n\nLet's start by creating a simple object we can use for example purposes:\n\n\nfrom datetime import datetime\n\nclass Comment(object):\n def __init__(self, email, content, created=None):\n self.email = email\n self.content = content\n self.created = created or datetime.now()\n\ncomment = Comment(email='leila@example.com', content='foo bar')\n\n\n\nWe'll declare a serializer that we can use to serialize and deserialize data that corresponds to \nComment\n objects.\n\n\nDeclaring a serializer looks very similar to declaring a form:\n\n\nfrom rest_framework import serializers\n\nclass CommentSerializer(serializers.Serializer):\n email = serializers.EmailField()\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n\n\nSerializing objects\n\n\nWe can now use \nCommentSerializer\n to serialize a comment, or list of comments. Again, using the \nSerializer\n class looks a lot like using a \nForm\n class.\n\n\nserializer = CommentSerializer(comment)\nserializer.data\n# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}\n\n\n\nAt this point we've translated the model instance into Python native datatypes. To finalise the serialization process we render the data into \njson\n.\n\n\nfrom rest_framework.renderers import JSONRenderer\n\njson = JSONRenderer().render(serializer.data)\njson\n# b'{\"email\":\"leila@example.com\",\"content\":\"foo bar\",\"created\":\"2016-01-27T15:17:10.375877\"}'\n\n\n\nDeserializing objects\n\n\nDeserialization is similar. First we parse a stream into Python native datatypes...\n\n\nfrom django.utils.six import BytesIO\nfrom rest_framework.parsers import JSONParser\n\nstream = BytesIO(json)\ndata = JSONParser().parse(stream)\n\n\n\n...then we restore those native datatypes into a dictionary of validated data.\n\n\nserializer = CommentSerializer(data=data)\nserializer.is_valid()\n# True\nserializer.validated_data\n# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}\n\n\n\nSaving instances\n\n\nIf we want to be able to return complete object instances based on the validated data we need to implement one or both of the \n.create()\n and \nupdate()\n methods. For example:\n\n\nclass CommentSerializer(serializers.Serializer):\n email = serializers.EmailField()\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n def create(self, validated_data):\n return Comment(**validated_data)\n\n def update(self, instance, validated_data):\n instance.email = validated_data.get('email', instance.email)\n instance.content = validated_data.get('content', instance.content)\n instance.created = validated_data.get('created', instance.created)\n return instance\n\n\n\nIf your object instances correspond to Django models you'll also want to ensure that these methods save the object to the database. For example, if \nComment\n was a Django model, the methods might look like this:\n\n\n def create(self, validated_data):\n return Comment.objects.create(**validated_data)\n\n def update(self, instance, validated_data):\n instance.email = validated_data.get('email', instance.email)\n instance.content = validated_data.get('content', instance.content)\n instance.created = validated_data.get('created', instance.created)\n instance.save()\n return instance\n\n\n\nNow when deserializing data, we can call \n.save()\n to return an object instance, based on the validated data.\n\n\ncomment = serializer.save()\n\n\n\nCalling \n.save()\n will either create a new instance, or update an existing instance, depending on if an existing instance was passed when instantiating the serializer class:\n\n\n# .save() will create a new instance.\nserializer = CommentSerializer(data=data)\n\n# .save() will update the existing `comment` instance.\nserializer = CommentSerializer(comment, data=data)\n\n\n\nBoth the \n.create()\n and \n.update()\n methods are optional. You can implement either neither, one, or both of them, depending on the use-case for your serializer class.\n\n\nPassing additional attributes to \n.save()\n\n\nSometimes you'll want your view code to be able to inject additional data at the point of saving the instance. This additional data might include information like the current user, the current time, or anything else that is not part of the request data.\n\n\nYou can do so by including additional keyword arguments when calling \n.save()\n. For example:\n\n\nserializer.save(owner=request.user)\n\n\n\nAny additional keyword arguments will be included in the \nvalidated_data\n argument when \n.create()\n or \n.update()\n are called.\n\n\nOverriding \n.save()\n directly.\n\n\nIn some cases the \n.create()\n and \n.update()\n method names may not be meaningful. For example, in a contact form we may not be creating new instances, but instead sending an email or other message.\n\n\nIn these cases you might instead choose to override \n.save()\n directly, as being more readable and meaningful.\n\n\nFor example:\n\n\nclass ContactForm(serializers.Serializer):\n email = serializers.EmailField()\n message = serializers.CharField()\n\n def save(self):\n email = self.validated_data['email']\n message = self.validated_data['message']\n send_email(from=email, message=message)\n\n\n\nNote that in the case above we're now having to access the serializer \n.validated_data\n property directly.\n\n\nValidation\n\n\nWhen deserializing data, you always need to call \nis_valid()\n before attempting to access the validated data, or save an object instance. If any validation errors occur, the \n.errors\n property will contain a dictionary representing the resulting error messages. For example:\n\n\nserializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})\nserializer.is_valid()\n# False\nserializer.errors\n# {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']}\n\n\n\nEach key in the dictionary will be the field name, and the values will be lists of strings of any error messages corresponding to that field. The \nnon_field_errors\n key may also be present, and will list any general validation errors. The name of the \nnon_field_errors\n key may be customized using the \nNON_FIELD_ERRORS_KEY\n REST framework setting.\n\n\nWhen deserializing a list of items, errors will be returned as a list of dictionaries representing each of the deserialized items.\n\n\nRaising an exception on invalid data\n\n\nThe \n.is_valid()\n method takes an optional \nraise_exception\n flag that will cause it to raise a \nserializers.ValidationError\n exception if there are validation errors.\n\n\nThese exceptions are automatically dealt with by the default exception handler that REST framework provides, and will return \nHTTP 400 Bad Request\n responses by default.\n\n\n# Return a 400 response if the data was invalid.\nserializer.is_valid(raise_exception=True)\n\n\n\nField-level validation\n\n\nYou can specify custom field-level validation by adding \n.validate_\nfield_name\n methods to your \nSerializer\n subclass. These are similar to the \n.clean_\nfield_name\n methods on Django forms.\n\n\nThese methods take a single argument, which is the field value that requires validation.\n\n\nYour \nvalidate_\nfield_name\n methods should return the validated value or raise a \nserializers.ValidationError\n. For example:\n\n\nfrom rest_framework import serializers\n\nclass BlogPostSerializer(serializers.Serializer):\n title = serializers.CharField(max_length=100)\n content = serializers.CharField()\n\n def validate_title(self, value):\n \"\"\"\n Check that the blog post is about Django.\n \"\"\"\n if 'django' not in value.lower():\n raise serializers.ValidationError(\"Blog post is not about Django\")\n return value\n\n\n\n\n\nNote:\n If your \nfield_name\n is declared on your serializer with the parameter \nrequired=False\n then this validation step will not take place if the field is not included.\n\n\n\n\nObject-level validation\n\n\nTo do any other validation that requires access to multiple fields, add a method called \n.validate()\n to your \nSerializer\n subclass. This method takes a single argument, which is a dictionary of field values. It should raise a \nValidationError\n if necessary, or just return the validated values. For example:\n\n\nfrom rest_framework import serializers\n\nclass EventSerializer(serializers.Serializer):\n description = serializers.CharField(max_length=100)\n start = serializers.DateTimeField()\n finish = serializers.DateTimeField()\n\n def validate(self, data):\n \"\"\"\n Check that the start is before the stop.\n \"\"\"\n if data['start'] \n data['finish']:\n raise serializers.ValidationError(\"finish must occur after start\")\n return data\n\n\n\nValidators\n\n\nIndividual fields on a serializer can include validators, by declaring them on the field instance, for example:\n\n\ndef multiple_of_ten(value):\n if value % 10 != 0:\n raise serializers.ValidationError('Not a multiple of ten')\n\nclass GameRecord(serializers.Serializer):\n score = IntegerField(validators=[multiple_of_ten])\n ...\n\n\n\nSerializer classes can also include reusable validators that are applied to the complete set of field data. These validators are included by declaring them on an inner \nMeta\n class, like so:\n\n\nclass EventSerializer(serializers.Serializer):\n name = serializers.CharField()\n room_number = serializers.IntegerField(choices=[101, 102, 103, 201])\n date = serializers.DateField()\n\n class Meta:\n # Each room only has one event per day.\n validators = UniqueTogetherValidator(\n queryset=Event.objects.all(),\n fields=['room_number', 'date']\n )\n\n\n\nFor more information see the \nvalidators documentation\n.\n\n\nAccessing the initial data and instance\n\n\nWhen passing an initial object or queryset to a serializer instance, the object will be made available as \n.instance\n. If no initial object is passed then the \n.instance\n attribute will be \nNone\n.\n\n\nWhen passing data to a serializer instance, the unmodified data will be made available as \n.initial_data\n. If the data keyword argument is not passed then the \n.initial_data\n attribute will not exist.\n\n\nPartial updates\n\n\nBy default, serializers must be passed values for all required fields or they will raise validation errors. You can use the \npartial\n argument in order to allow partial updates.\n\n\n# Update `comment` with partial data\nserializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)\n\n\n\nDealing with nested objects\n\n\nThe previous examples are fine for dealing with objects that only have simple datatypes, but sometimes we also need to be able to represent more complex objects, where some of the attributes of an object might not be simple datatypes such as strings, dates or integers.\n\n\nThe \nSerializer\n class is itself a type of \nField\n, and can be used to represent relationships where one object type is nested inside another.\n\n\nclass UserSerializer(serializers.Serializer):\n email = serializers.EmailField()\n username = serializers.CharField(max_length=100)\n\nclass CommentSerializer(serializers.Serializer):\n user = UserSerializer()\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n\n\nIf a nested representation may optionally accept the \nNone\n value you should pass the \nrequired=False\n flag to the nested serializer.\n\n\nclass CommentSerializer(serializers.Serializer):\n user = UserSerializer(required=False) # May be an anonymous user.\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n\n\nSimilarly if a nested representation should be a list of items, you should pass the \nmany=True\n flag to the nested serialized.\n\n\nclass CommentSerializer(serializers.Serializer):\n user = UserSerializer(required=False)\n edits = EditItemSerializer(many=True) # A nested list of 'edit' items.\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n\n\nWritable nested representations\n\n\nWhen dealing with nested representations that support deserializing the data, any errors with nested objects will be nested under the field name of the nested object.\n\n\nserializer = CommentSerializer(data={'user': {'email': 'foobar', 'username': 'doe'}, 'content': 'baz'})\nserializer.is_valid()\n# False\nserializer.errors\n# {'user': {'email': [u'Enter a valid e-mail address.']}, 'created': [u'This field is required.']}\n\n\n\nSimilarly, the \n.validated_data\n property will include nested data structures.\n\n\nWriting \n.create()\n methods for nested representations\n\n\nIf you're supporting writable nested representations you'll need to write \n.create()\n or \n.update()\n methods that handle saving multiple objects.\n\n\nThe following example demonstrates how you might handle creating a user with a nested profile object.\n\n\nclass UserSerializer(serializers.ModelSerializer):\n profile = ProfileSerializer()\n\n class Meta:\n model = User\n fields = ('username', 'email', 'profile')\n\n def create(self, validated_data):\n profile_data = validated_data.pop('profile')\n user = User.objects.create(**validated_data)\n Profile.objects.create(user=user, **profile_data)\n return user\n\n\n\nWriting \n.update()\n methods for nested representations\n\n\nFor updates you'll want to think carefully about how to handle updates to relationships. For example if the data for the relationship is \nNone\n, or not provided, which of the following should occur?\n\n\n\n\nSet the relationship to \nNULL\n in the database.\n\n\nDelete the associated instance.\n\n\nIgnore the data and leave the instance as it is.\n\n\nRaise a validation error.\n\n\n\n\nHere's an example for an \nupdate()\n method on our previous \nUserSerializer\n class.\n\n\n def update(self, instance, validated_data):\n profile_data = validated_data.pop('profile')\n # Unless the application properly enforces that this field is\n # always set, the follow could raise a `DoesNotExist`, which\n # would need to be handled.\n profile = instance.profile\n\n instance.username = validated_data.get('username', instance.username)\n instance.email = validated_data.get('email', instance.email)\n instance.save()\n\n profile.is_premium_member = profile_data.get(\n 'is_premium_member',\n profile.is_premium_member\n )\n profile.has_support_contract = profile_data.get(\n 'has_support_contract',\n profile.has_support_contract\n )\n profile.save()\n\n return instance\n\n\n\nBecause the behavior of nested creates and updates can be ambiguous, and may require complex dependencies between related models, REST framework 3 requires you to always write these methods explicitly. The default \nModelSerializer\n \n.create()\n and \n.update()\n methods do not include support for writable nested representations.\n\n\nIt is possible that a third party package, providing automatic support some kinds of automatic writable nested representations may be released alongside the 3.1 release.\n\n\nHandling saving related instances in model manager classes\n\n\nAn alternative to saving multiple related instances in the serializer is to write custom model manager classes that handle creating the correct instances.\n\n\nFor example, suppose we wanted to ensure that \nUser\n instances and \nProfile\n instances are always created together as a pair. We might write a custom manager class that looks something like this:\n\n\nclass UserManager(models.Manager):\n ...\n\n def create(self, username, email, is_premium_member=False, has_support_contract=False):\n user = User(username=username, email=email)\n user.save()\n profile = Profile(\n user=user,\n is_premium_member=is_premium_member,\n has_support_contract=has_support_contract\n )\n profile.save()\n return user\n\n\n\nThis manager class now more nicely encapsulates that user instances and profile instances are always created at the same time. Our \n.create()\n method on the serializer class can now be re-written to use the new manager method.\n\n\ndef create(self, validated_data):\n return User.objects.create(\n username=validated_data['username'],\n email=validated_data['email']\n is_premium_member=validated_data['profile']['is_premium_member']\n has_support_contract=validated_data['profile']['has_support_contract']\n )\n\n\n\nFor more details on this approach see the Django documentation on \nmodel managers\n, and \nthis blogpost on using model and manager classes\n.\n\n\nDealing with multiple objects\n\n\nThe \nSerializer\n class can also handle serializing or deserializing lists of objects.\n\n\nSerializing multiple objects\n\n\nTo serialize a queryset or list of objects instead of a single object instance, you should pass the \nmany=True\n flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.\n\n\nqueryset = Book.objects.all()\nserializer = BookSerializer(queryset, many=True)\nserializer.data\n# [\n# {'id': 0, 'title': 'The electric kool-aid acid test', 'author': 'Tom Wolfe'},\n# {'id': 1, 'title': 'If this is a man', 'author': 'Primo Levi'},\n# {'id': 2, 'title': 'The wind-up bird chronicle', 'author': 'Haruki Murakami'}\n# ]\n\n\n\nDeserializing multiple objects\n\n\nThe default behavior for deserializing multiple objects is to support multiple object creation, but not support multiple object updates. For more information on how to support or customize either of these cases, see the \nListSerializer\n documentation below.\n\n\nIncluding extra context\n\n\nThere are some cases where you need to provide extra context to the serializer in addition to the object being serialized. One common case is if you're using a serializer that includes hyperlinked relations, which requires the serializer to have access to the current request so that it can properly generate fully qualified URLs.\n\n\nYou can provide arbitrary additional context by passing a \ncontext\n argument when instantiating the serializer. For example:\n\n\nserializer = AccountSerializer(account, context={'request': request})\nserializer.data\n# {'id': 6, 'owner': u'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'}\n\n\n\nThe context dictionary can be used within any serializer field logic, such as a custom \n.to_representation()\n method, by accessing the \nself.context\n attribute.\n\n\n\n\nModelSerializer\n\n\nOften you'll want serializer classes that map closely to Django model definitions.\n\n\nThe \nModelSerializer\n class provides a shortcut that lets you automatically create a \nSerializer\n class with fields that correspond to the Model fields.\n\n\nThe \nModelSerializer\n class is the same as a regular \nSerializer\n class, except that\n:\n\n\n\n\nIt will automatically generate a set of fields for you, based on the model.\n\n\nIt will automatically generate validators for the serializer, such as unique_together validators.\n\n\nIt includes simple default implementations of \n.create()\n and \n.update()\n.\n\n\n\n\nDeclaring a \nModelSerializer\n looks like this:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created')\n\n\n\nBy default, all the model fields on the class will be mapped to a corresponding serializer fields.\n\n\nAny relationships such as foreign keys on the model will be mapped to \nPrimaryKeyRelatedField\n. Reverse relationships are not included by default unless explicitly included as specified in the \nserializer relations\n documentation.\n\n\nInspecting a \nModelSerializer\n\n\nSerializer classes generate helpful verbose representation strings, that allow you to fully inspect the state of their fields. This is particularly useful when working with \nModelSerializers\n where you want to determine what set of fields and validators are being automatically created for you.\n\n\nTo do so, open the Django shell, using \npython manage.py shell\n, then import the serializer class, instantiate it, and print the object representation\u2026\n\n\n from myapp.serializers import AccountSerializer\n\n serializer = AccountSerializer()\n\n print(repr(serializer))\nAccountSerializer():\n id = IntegerField(label='ID', read_only=True)\n name = CharField(allow_blank=True, max_length=100, required=False)\n owner = PrimaryKeyRelatedField(queryset=User.objects.all())\n\n\n\nSpecifying which fields to include\n\n\nIf you only want a subset of the default fields to be used in a model serializer, you can do so using \nfields\n or \nexclude\n options, just as you would with a \nModelForm\n. It is strongly recommended that you explicitly set all fields that should be serialized using the \nfields\n attribute. This will make it less likely to result in unintentionally exposing data when your models change.\n\n\nFor example:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created')\n\n\n\nYou can also set the \nfields\n attribute to the special value \n'__all__'\n to indicate that all fields in the model should be used.\n\n\nFor example:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = '__all__'\n\n\n\nYou can set the \nexclude\n attribute to a list of fields to be excluded from the serializer.\n\n\nFor example:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n exclude = ('users',)\n\n\n\nIn the example above, if the \nAccount\n model had 3 fields \naccount_name\n, \nusers\n, and \ncreated\n, this will result in the fields \naccount_name\n and \ncreated\n to be serialized.\n\n\nThe names in the \nfields\n and \nexclude\n attributes will normally map to model fields on the model class.\n\n\nAlternatively names in the \nfields\n options can map to properties or methods which take no arguments that exist on the model class.\n\n\nSpecifying nested serialization\n\n\nThe default \nModelSerializer\n uses primary keys for relationships, but you can also easily generate nested representations using the \ndepth\n option:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created')\n depth = 1\n\n\n\nThe \ndepth\n option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.\n\n\nIf you want to customize the way the serialization is done you'll need to define the field yourself.\n\n\nSpecifying fields explicitly\n\n\nYou can add extra fields to a \nModelSerializer\n or override the default fields by declaring fields on the class, just as you would for a \nSerializer\n class.\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n url = serializers.CharField(source='get_absolute_url', read_only=True)\n groups = serializers.PrimaryKeyRelatedField(many=True)\n\n class Meta:\n model = Account\n\n\n\nExtra fields can correspond to any property or callable on the model.\n\n\nSpecifying read only fields\n\n\nYou may wish to specify multiple fields as read-only. Instead of adding each field explicitly with the \nread_only=True\n attribute, you may use the shortcut Meta option, \nread_only_fields\n.\n\n\nThis option should be a list or tuple of field names, and is declared as follows:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created')\n read_only_fields = ('account_name',)\n\n\n\nModel fields which have \neditable=False\n set, and \nAutoField\n fields will be set to read-only by default, and do not need to be added to the \nread_only_fields\n option.\n\n\n\n\nNote\n: There is a special-case where a read-only field is part of a \nunique_together\n constraint at the model level. In this case the field is required by the serializer class in order to validate the constraint, but should also not be editable by the user.\n\n\nThe right way to deal with this is to specify the field explicitly on the serializer, providing both the \nread_only=True\n and \ndefault=\u2026\n keyword arguments.\n\n\nOne example of this is a read-only relation to the currently authenticated \nUser\n which is \nunique_together\n with another identifier. In this case you would declare the user field like so:\n\n\nuser = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())\n\n\n\nPlease review the \nValidators Documentation\n for details on the \nUniqueTogetherValidator\n and \nCurrentUserDefault\n classes.\n\n\n\n\nAdditional keyword arguments\n\n\nThere is also a shortcut allowing you to specify arbitrary additional keyword arguments on fields, using the \nextra_kwargs\n option. As in the case of \nread_only_fields\n, this means you do not need to explicitly declare the field on the serializer.\n\n\nThis option is a dictionary, mapping field names to a dictionary of keyword arguments. For example:\n\n\nclass CreateUserSerializer(serializers.ModelSerializer):\n class Meta:\n model = User\n fields = ('email', 'username', 'password')\n extra_kwargs = {'password': {'write_only': True}}\n\n def create(self, validated_data):\n user = User(\n email=validated_data['email'],\n username=validated_data['username']\n )\n user.set_password(validated_data['password'])\n user.save()\n return user\n\n\n\nRelational fields\n\n\nWhen serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation for \nModelSerializer\n is to use the primary keys of the related instances.\n\n\nAlternative representations include serializing using hyperlinks, serializing complete nested representations, or serializing with a custom representation.\n\n\nFor full details see the \nserializer relations\n documentation.\n\n\nCustomizing field mappings\n\n\nThe ModelSerializer class also exposes an API that you can override in order to alter how serializer fields are automatically determined when instantiating the serializer.\n\n\nNormally if a \nModelSerializer\n does not generate the fields you need by default then you should either add them to the class explicitly, or simply use a regular \nSerializer\n class instead. However in some cases you may want to create a new base class that defines how the serializer fields are created for any given model.\n\n\n.serializer_field_mapping\n\n\nA mapping of Django model classes to REST framework serializer classes. You can override this mapping to alter the default serializer classes that should be used for each model class.\n\n\n.serializer_related_field\n\n\nThis property should be the serializer field class, that is used for relational fields by default.\n\n\nFor \nModelSerializer\n this defaults to \nPrimaryKeyRelatedField\n.\n\n\nFor \nHyperlinkedModelSerializer\n this defaults to \nserializers.HyperlinkedRelatedField\n.\n\n\nserializer_url_field\n\n\nThe serializer field class that should be used for any \nurl\n field on the serializer.\n\n\nDefaults to \nserializers.HyperlinkedIdentityField\n\n\nserializer_choice_field\n\n\nThe serializer field class that should be used for any choice fields on the serializer.\n\n\nDefaults to \nserializers.ChoiceField\n\n\nThe field_class and field_kwargs API\n\n\nThe following methods are called to determine the class and keyword arguments for each field that should be automatically included on the serializer. Each of these methods should return a two tuple of \n(field_class, field_kwargs)\n.\n\n\n.build_standard_field(self, field_name, model_field)\n\n\nCalled to generate a serializer field that maps to a standard model field.\n\n\nThe default implementation returns a serializer class based on the \nserializer_field_mapping\n attribute.\n\n\n.build_relational_field(self, field_name, relation_info)\n\n\nCalled to generate a serializer field that maps to a relational model field.\n\n\nThe default implementation returns a serializer class based on the \nserializer_relational_field\n attribute.\n\n\nThe \nrelation_info\n argument is a named tuple, that contains \nmodel_field\n, \nrelated_model\n, \nto_many\n and \nhas_through_model\n properties.\n\n\n.build_nested_field(self, field_name, relation_info, nested_depth)\n\n\nCalled to generate a serializer field that maps to a relational model field, when the \ndepth\n option has been set.\n\n\nThe default implementation dynamically creates a nested serializer class based on either \nModelSerializer\n or \nHyperlinkedModelSerializer\n.\n\n\nThe \nnested_depth\n will be the value of the \ndepth\n option, minus one.\n\n\nThe \nrelation_info\n argument is a named tuple, that contains \nmodel_field\n, \nrelated_model\n, \nto_many\n and \nhas_through_model\n properties.\n\n\n.build_property_field(self, field_name, model_class)\n\n\nCalled to generate a serializer field that maps to a property or zero-argument method on the model class.\n\n\nThe default implementation returns a \nReadOnlyField\n class.\n\n\n.build_url_field(self, field_name, model_class)\n\n\nCalled to generate a serializer field for the serializer's own \nurl\n field. The default implementation returns a \nHyperlinkedIdentityField\n class.\n\n\n.build_unknown_field(self, field_name, model_class)\n\n\nCalled when the field name did not map to any model field or model property.\nThe default implementation raises an error, although subclasses may customize this behavior.\n\n\n\n\nHyperlinkedModelSerializer\n\n\nThe \nHyperlinkedModelSerializer\n class is similar to the \nModelSerializer\n class except that it uses hyperlinks to represent relationships, rather than primary keys.\n\n\nBy default the serializer will include a \nurl\n field instead of a primary key field.\n\n\nThe url field will be represented using a \nHyperlinkedIdentityField\n serializer field, and any relationships on the model will be represented using a \nHyperlinkedRelatedField\n serializer field.\n\n\nYou can explicitly include the primary key by adding it to the \nfields\n option, for example:\n\n\nclass AccountSerializer(serializers.HyperlinkedModelSerializer):\n class Meta:\n model = Account\n fields = ('url', 'id', 'account_name', 'users', 'created')\n\n\n\nAbsolute and relative URLs\n\n\nWhen instantiating a \nHyperlinkedModelSerializer\n you must include the current\n\nrequest\n in the serializer context, for example:\n\n\nserializer = AccountSerializer(queryset, context={'request': request})\n\n\n\nDoing so will ensure that the hyperlinks can include an appropriate hostname,\nso that the resulting representation uses fully qualified URLs, such as:\n\n\nhttp://api.example.com/accounts/1/\n\n\n\nRather than relative URLs, such as:\n\n\n/accounts/1/\n\n\n\nIf you \ndo\n want to use relative URLs, you should explicitly pass \n{'request': None}\n\nin the serializer context.\n\n\nHow hyperlinked views are determined\n\n\nThere needs to be a way of determining which views should be used for hyperlinking to model instances.\n\n\nBy default hyperlinks are expected to correspond to a view name that matches the style \n'{model_name}-detail'\n, and looks up the instance by a \npk\n keyword argument.\n\n\nYou can override a URL field view name and lookup field by using either, or both of, the \nview_name\n and \nlookup_field\n options in the \nextra_kwargs\n setting, like so:\n\n\nclass AccountSerializer(serializers.HyperlinkedModelSerializer):\n class Meta:\n model = Account\n fields = ('account_url', 'account_name', 'users', 'created')\n extra_kwargs = {\n 'url': {'view_name': 'accounts', 'lookup_field': 'account_name'}\n 'users': {'lookup_field': 'username'}\n }\n\n\n\nAlternatively you can set the fields on the serializer explicitly. For example:\n\n\nclass AccountSerializer(serializers.HyperlinkedModelSerializer):\n url = serializers.HyperlinkedIdentityField(\n view_name='accounts',\n lookup_field='slug'\n )\n users = serializers.HyperlinkedRelatedField(\n view_name='user-detail',\n lookup_field='username',\n many=True,\n read_only=True\n )\n\n class Meta:\n model = Account\n fields = ('url', 'account_name', 'users', 'created')\n\n\n\n\n\nTip\n: Properly matching together hyperlinked representations and your URL conf can sometimes be a bit fiddly. Printing the \nrepr\n of a \nHyperlinkedModelSerializer\n instance is a particularly useful way to inspect exactly which view names and lookup fields the relationships are expected to map too.\n\n\n\n\nChanging the URL field name\n\n\nThe name of the URL field defaults to 'url'. You can override this globally, by using the \nURL_FIELD_NAME\n setting.\n\n\n\n\nListSerializer\n\n\nThe \nListSerializer\n class provides the behavior for serializing and validating multiple objects at once. You won't \ntypically\n need to use \nListSerializer\n directly, but should instead simply pass \nmany=True\n when instantiating a serializer.\n\n\nWhen a serializer is instantiated and \nmany=True\n is passed, a \nListSerializer\n instance will be created. The serializer class then becomes a child of the parent \nListSerializer\n\n\nThe following argument can also be passed to a \nListSerializer\n field or a serializer that is passed \nmany=True\n:\n\n\nallow_empty\n\n\nThis is \nTrue\n by default, but can be set to \nFalse\n if you want to disallow empty lists as valid input.\n\n\nCustomizing \nListSerializer\n behavior\n\n\nThere \nare\n a few use cases when you might want to customize the \nListSerializer\n behavior. For example:\n\n\n\n\nYou want to provide particular validation of the lists, such as checking that one element does not conflict with another element in a list.\n\n\nYou want to customize the create or update behavior of multiple objects.\n\n\n\n\nFor these cases you can modify the class that is used when \nmany=True\n is passed, by using the \nlist_serializer_class\n option on the serializer \nMeta\n class.\n\n\nFor example:\n\n\nclass CustomListSerializer(serializers.ListSerializer):\n ...\n\nclass CustomSerializer(serializers.Serializer):\n ...\n class Meta:\n list_serializer_class = CustomListSerializer\n\n\n\nCustomizing multiple create\n\n\nThe default implementation for multiple object creation is to simply call \n.create()\n for each item in the list. If you want to customize this behavior, you'll need to customize the \n.create()\n method on \nListSerializer\n class that is used when \nmany=True\n is passed.\n\n\nFor example:\n\n\nclass BookListSerializer(serializers.ListSerializer):\n def create(self, validated_data):\n books = [Book(**item) for item in validated_data]\n return Book.objects.bulk_create(books)\n\nclass BookSerializer(serializers.Serializer):\n ...\n class Meta:\n list_serializer_class = BookListSerializer\n\n\n\nCustomizing multiple update\n\n\nBy default the \nListSerializer\n class does not support multiple updates. This is because the behavior that should be expected for insertions and deletions is ambiguous.\n\n\nTo support multiple updates you'll need to do so explicitly. When writing your multiple update code make sure to keep the following in mind:\n\n\n\n\nHow do you determine which instance should be updated for each item in the list of data?\n\n\nHow should insertions be handled? Are they invalid, or do they create new objects?\n\n\nHow should removals be handled? Do they imply object deletion, or removing a relationship? Should they be silently ignored, or are they invalid?\n\n\nHow should ordering be handled? Does changing the position of two items imply any state change or is it ignored?\n\n\n\n\nYou will need to add an explicit \nid\n field to the instance serializer. The default implicitly-generated \nid\n field is marked as \nread_only\n. This causes it to be removed on updates. Once you declare it explicitly, it will be available in the list serializer's \nupdate\n method.\n\n\nHere's an example of how you might choose to implement multiple updates:\n\n\nclass BookListSerializer(serializers.ListSerializer):\n def update(self, instance, validated_data):\n # Maps for id-\ninstance and id-\ndata item.\n book_mapping = {book.id: book for book in instance}\n data_mapping = {item['id']: item for item in validated_data}\n\n # Perform creations and updates.\n ret = []\n for book_id, data in data_mapping.items():\n book = book_mapping.get(book_id, None)\n if book is None:\n ret.append(self.child.create(data))\n else:\n ret.append(self.child.update(book, data))\n\n # Perform deletions.\n for book_id, book in book_mapping.items():\n if book_id not in data_mapping:\n book.delete()\n\n return ret\n\nclass BookSerializer(serializers.Serializer):\n # We need to identify elements in the list using their primary key,\n # so use a writable field here, rather than the default which would be read-only.\n id = serializers.IntegerField()\n\n ...\n id = serializers.IntegerField(required=False)\n\n class Meta:\n list_serializer_class = BookListSerializer\n\n\n\nIt is possible that a third party package may be included alongside the 3.1 release that provides some automatic support for multiple update operations, similar to the \nallow_add_remove\n behavior that was present in REST framework 2.\n\n\nCustomizing ListSerializer initialization\n\n\nWhen a serializer with \nmany=True\n is instantiated, we need to determine which arguments and keyword arguments should be passed to the \n.__init__()\n method for both the child \nSerializer\n class, and for the parent \nListSerializer\n class.\n\n\nThe default implementation is to pass all arguments to both classes, except for \nvalidators\n, and any custom keyword arguments, both of which are assumed to be intended for the child serializer class.\n\n\nOccasionally you might need to explicitly specify how the child and parent classes should be instantiated when \nmany=True\n is passed. You can do so by using the \nmany_init\n class method.\n\n\n @classmethod\n def many_init(cls, *args, **kwargs):\n # Instantiate the child serializer.\n kwargs['child'] = cls()\n # Instantiate the parent list serializer.\n return CustomListSerializer(*args, **kwargs)\n\n\n\n\n\nBaseSerializer\n\n\nBaseSerializer\n class that can be used to easily support alternative serialization and deserialization styles.\n\n\nThis class implements the same basic API as the \nSerializer\n class:\n\n\n\n\n.data\n - Returns the outgoing primitive representation.\n\n\n.is_valid()\n - Deserializes and validates incoming data.\n\n\n.validated_data\n - Returns the validated incoming data.\n\n\n.errors\n - Returns any errors during validation.\n\n\n.save()\n - Persists the validated data into an object instance.\n\n\n\n\nThere are four methods that can be overridden, depending on what functionality you want the serializer class to support:\n\n\n\n\n.to_representation()\n - Override this to support serialization, for read operations.\n\n\n.to_internal_value()\n - Override this to support deserialization, for write operations.\n\n\n.create()\n and \n.update()\n - Override either or both of these to support saving instances.\n\n\n\n\nBecause this class provides the same interface as the \nSerializer\n class, you can use it with the existing generic class-based views exactly as you would for a regular \nSerializer\n or \nModelSerializer\n.\n\n\nThe only difference you'll notice when doing so is the \nBaseSerializer\n classes will not generate HTML forms in the browsable API. This is because the data they return does not include all the field information that would allow each field to be rendered into a suitable HTML input.\n\n\nRead-only \nBaseSerializer\n classes\n\n\nTo implement a read-only serializer using the \nBaseSerializer\n class, we just need to override the \n.to_representation()\n method. Let's take a look at an example using a simple Django model:\n\n\nclass HighScore(models.Model):\n created = models.DateTimeField(auto_now_add=True)\n player_name = models.CharField(max_length=10)\n score = models.IntegerField()\n\n\n\nIt's simple to create a read-only serializer for converting \nHighScore\n instances into primitive data types.\n\n\nclass HighScoreSerializer(serializers.BaseSerializer):\n def to_representation(self, obj):\n return {\n 'score': obj.score,\n 'player_name': obj.player_name\n }\n\n\n\nWe can now use this class to serialize single \nHighScore\n instances:\n\n\n@api_view(['GET'])\ndef high_score(request, pk):\n instance = HighScore.objects.get(pk=pk)\n serializer = HighScoreSerializer(instance)\n return Response(serializer.data)\n\n\n\nOr use it to serialize multiple instances:\n\n\n@api_view(['GET'])\ndef all_high_scores(request):\n queryset = HighScore.objects.order_by('-score')\n serializer = HighScoreSerializer(queryset, many=True)\n return Response(serializer.data)\n\n\n\nRead-write \nBaseSerializer\n classes\n\n\nTo create a read-write serializer we first need to implement a \n.to_internal_value()\n method. This method returns the validated values that will be used to construct the object instance, and may raise a \nValidationError\n if the supplied data is in an incorrect format.\n\n\nOnce you've implemented \n.to_internal_value()\n, the basic validation API will be available on the serializer, and you will be able to use \n.is_valid()\n, \n.validated_data\n and \n.errors\n.\n\n\nIf you want to also support \n.save()\n you'll need to also implement either or both of the \n.create()\n and \n.update()\n methods.\n\n\nHere's a complete example of our previous \nHighScoreSerializer\n, that's been updated to support both read and write operations.\n\n\nclass HighScoreSerializer(serializers.BaseSerializer):\n def to_internal_value(self, data):\n score = data.get('score')\n player_name = data.get('player_name')\n\n # Perform the data validation.\n if not score:\n raise ValidationError({\n 'score': 'This field is required.'\n })\n if not player_name:\n raise ValidationError({\n 'player_name': 'This field is required.'\n })\n if len(player_name) \n 10:\n raise ValidationError({\n 'player_name': 'May not be more than 10 characters.'\n })\n\n # Return the validated values. This will be available as\n # the `.validated_data` property.\n return {\n 'score': int(score),\n 'player_name': player_name\n }\n\n def to_representation(self, obj):\n return {\n 'score': obj.score,\n 'player_name': obj.player_name\n }\n\n def create(self, validated_data):\n return HighScore.objects.create(**validated_data)\n\n\n\nCreating new base classes\n\n\nThe \nBaseSerializer\n class is also useful if you want to implement new generic serializer classes for dealing with particular serialization styles, or for integrating with alternative storage backends.\n\n\nThe following class is an example of a generic serializer that can handle coercing arbitrary objects into primitive representations.\n\n\nclass ObjectSerializer(serializers.BaseSerializer):\n \"\"\"\n A read-only serializer that coerces arbitrary complex objects\n into primitive representations.\n \"\"\"\n def to_representation(self, obj):\n for attribute_name in dir(obj):\n attribute = getattr(obj, attribute_name)\n if attribute_name('_'):\n # Ignore private attributes.\n pass\n elif hasattr(attribute, '__call__'):\n # Ignore methods and other callables.\n pass\n elif isinstance(attribute, (str, int, bool, float, type(None))):\n # Primitive types can be passed through unmodified.\n output[attribute_name] = attribute\n elif isinstance(attribute, list):\n # Recursively deal with items in lists.\n output[attribute_name] = [\n self.to_representation(item) for item in attribute\n ]\n elif isinstance(attribute, dict):\n # Recursively deal with items in dictionaries.\n output[attribute_name] = {\n str(key): self.to_representation(value)\n for key, value in attribute.items()\n }\n else:\n # Force anything else to its string representation.\n output[attribute_name] = str(attribute)\n\n\n\n\n\nAdvanced serializer usage\n\n\nOverriding serialization and deserialization behavior\n\n\nIf you need to alter the serialization, deserialization or validation of a serializer class you can do so by overriding the \n.to_representation()\n or \n.to_internal_value()\n methods.\n\n\nSome reasons this might be useful include...\n\n\n\n\nAdding new behavior for new serializer base classes.\n\n\nModifying the behavior slightly for an existing class.\n\n\nImproving serialization performance for a frequently accessed API endpoint that returns lots of data.\n\n\n\n\nThe signatures for these methods are as follows:\n\n\n.to_representation(self, obj)\n\n\nTakes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API.\n\n\n.to_internal_value(self, data)\n\n\nTakes the unvalidated incoming data as input and should return the validated data that will be made available as \nserializer.validated_data\n. The return value will also be passed to the \n.create()\n or \n.update()\n methods if \n.save()\n is called on the serializer class.\n\n\nIf any of the validation fails, then the method should raise a \nserializers.ValidationError(errors)\n. Typically the \nerrors\n argument here will be a dictionary mapping field names to error messages.\n\n\nThe \ndata\n argument passed to this method will normally be the value of \nrequest.data\n, so the datatype it provides will depend on the parser classes you have configured for your API.\n\n\nSerializer Inheritance\n\n\nSimilar to Django forms, you can extend and reuse serializers through inheritance. This allows you to declare a common set of fields or methods on a parent class that can then be used in a number of serializers. For example,\n\n\nclass MyBaseSerializer(Serializer):\n my_field = serializers.CharField()\n\n def validate_my_field(self):\n ...\n\nclass MySerializer(MyBaseSerializer):\n ...\n\n\n\nLike Django's \nModel\n and \nModelForm\n classes, the inner \nMeta\n class on serializers does not implicitly inherit from it's parents' inner \nMeta\n classes. If you want the \nMeta\n class to inherit from a parent class you must do so explicitly. For example:\n\n\nclass AccountSerializer(MyBaseSerializer):\n class Meta(MyBaseSerializer.Meta):\n model = Account\n\n\n\nTypically we would recommend \nnot\n using inheritance on inner Meta classes, but instead declaring all options explicitly.\n\n\nAdditionally, the following caveats apply to serializer inheritance:\n\n\n\n\nNormal Python name resolution rules apply. If you have multiple base classes that declare a \nMeta\n inner class, only the first one will be used. This means the child\u2019s \nMeta\n, if it exists, otherwise the \nMeta\n of the first parent, etc.\n\n\n\n\nIt\u2019s possible to declaratively remove a \nField\n inherited from a parent class by setting the name to be \nNone\n on the subclass.\n\n\nclass MyBaseSerializer(ModelSerializer):\n my_field = serializers.CharField()\n\nclass MySerializer(MyBaseSerializer):\n my_field = None\n\n\n\nHowever, you can only use this technique to opt out from a field defined declaratively by a parent class; it won\u2019t prevent the \nModelSerializer\n from generating a default field. To opt-out from default fields, see \nSpecifying which fields to include\n.\n\n\n\n\n\n\nDynamically modifying fields\n\n\nOnce a serializer has been initialized, the dictionary of fields that are set on the serializer may be accessed using the \n.fields\n attribute. Accessing and modifying this attribute allows you to dynamically modify the serializer.\n\n\nModifying the \nfields\n argument directly allows you to do interesting things such as changing the arguments on serializer fields at runtime, rather than at the point of declaring the serializer.\n\n\nExample\n\n\nFor example, if you wanted to be able to set which fields should be used by a serializer at the point of initializing it, you could create a serializer class like so:\n\n\nclass DynamicFieldsModelSerializer(serializers.ModelSerializer):\n \"\"\"\n A ModelSerializer that takes an additional `fields` argument that\n controls which fields should be displayed.\n \"\"\"\n\n def __init__(self, *args, **kwargs):\n # Don't pass the 'fields' arg up to the superclass\n fields = kwargs.pop('fields', None)\n\n # Instantiate the superclass normally\n super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)\n\n if fields is not None:\n # Drop any fields that are not specified in the `fields` argument.\n allowed = set(fields)\n existing = set(self.fields.keys())\n for field_name in existing - allowed:\n self.fields.pop(field_name)\n\n\n\nThis would then allow you to do the following:\n\n\n class UserSerializer(DynamicFieldsModelSerializer):\n\n class Meta:\n\n model = User\n\n fields = ('id', 'username', 'email')\n\n\n\n print UserSerializer(user)\n{'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'}\n\n\n\n print UserSerializer(user, fields=('id', 'email'))\n{'id': 2, 'email': 'jon@example.com'}\n\n\n\nCustomizing the default fields\n\n\nREST framework 2 provided an API to allow developers to override how a \nModelSerializer\n class would automatically generate the default set of fields.\n\n\nThis API included the \n.get_field()\n, \n.get_pk_field()\n and other methods.\n\n\nBecause the serializers have been fundamentally redesigned with 3.0 this API no longer exists. You can still modify the fields that get created but you'll need to refer to the source code, and be aware that if the changes you make are against private bits of API then they may be subject to change.\n\n\nA new interface for controlling this behavior is currently planned for REST framework 3.1.\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nDjango REST marshmallow\n\n\nThe \ndjango-rest-marshmallow\n package provides an alternative implementation for serializers, using the python \nmarshmallow\n library. It exposes the same API as the REST framework serializers, and can be used as a drop-in replacement in some use-cases.\n\n\nSerpy\n\n\nThe \nserpy\n package is an alternative implementation for serializers that is built for speed. \nSerpy\n serializes complex datatypes to simple native types. The native types can be easily converted to JSON or any other format needed.\n\n\nMongoengineModelSerializer\n\n\nThe \ndjango-rest-framework-mongoengine\n package provides a \nMongoEngineModelSerializer\n serializer class that supports using MongoDB as the storage layer for Django REST framework.\n\n\nGeoFeatureModelSerializer\n\n\nThe \ndjango-rest-framework-gis\n package provides a \nGeoFeatureModelSerializer\n serializer class that supports GeoJSON both for read and write operations.\n\n\nHStoreSerializer\n\n\nThe \ndjango-rest-framework-hstore\n package provides an \nHStoreSerializer\n to support \ndjango-hstore\n \nDictionaryField\n model field and its \nschema-mode\n feature.\n\n\nDynamic REST\n\n\nThe \ndynamic-rest\n package extends the ModelSerializer and ModelViewSet interfaces, adding API query parameters for filtering, sorting, and including / excluding all fields and relationships defined by your serializers.\n\n\nDynamic Fields Mixin\n\n\nThe \ndrf-dynamic-fields\n package provides a mixin to dynamically limit the fields per serializer to a subset specified by an URL parameter.\n\n\nDRF FlexFields\n\n\nThe \ndrf-flex-fields\n package extends the ModelSerializer and ModelViewSet to provide commonly used functionality for dynamically setting fields and expanding primitive fields to nested models, both from URL parameters and your serializer class definitions.\n\n\nSerializer Extensions\n\n\nThe \ndjango-rest-framework-serializer-extensions\n\npackage provides a collection of tools to DRY up your serializers, by allowing\nfields to be defined on a per-view/request basis. Fields can be whitelisted,\nblacklisted and child serializers can be optionally expanded.\n\n\nHTML JSON Forms\n\n\nThe \nhtml-json-forms\n package provides an algorithm and serializer for processing \nform\n submissions per the (inactive) \nHTML JSON Form specification\n. The serializer facilitates processing of arbitrarily nested JSON structures within HTML. For example, \ninput name=\"items[0][id]\" value=\"5\"\n will be interpreted as \n{\"items\": [{\"id\": \"5\"}]}\n.\n\n\nDRF-Base64\n\n\nDRF-Base64\n provides a set of field and model serializers that handles the upload of base64-encoded files.\n\n\nQueryFields\n\n\ndjangorestframework-queryfields\n allows API clients to specify which fields will be sent in the response via inclusion or exclusion query paramaters.",
+ "text": "Serializers\n\n\n\n\nExpanding the usefulness of the serializers is something that we would\nlike to address. However, it's not a trivial problem, and it\nwill take some serious design work.\n\n\n Russell Keith-Magee, \nDjango users group\n\n\n\n\nSerializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into \nJSON\n, \nXML\n or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.\n\n\nThe serializers in REST framework work very similarly to Django's \nForm\n and \nModelForm\n classes. We provide a \nSerializer\n class which gives you a powerful, generic way to control the output of your responses, as well as a \nModelSerializer\n class which provides a useful shortcut for creating serializers that deal with model instances and querysets.\n\n\nDeclaring Serializers\n\n\nLet's start by creating a simple object we can use for example purposes:\n\n\nfrom datetime import datetime\n\nclass Comment(object):\n def __init__(self, email, content, created=None):\n self.email = email\n self.content = content\n self.created = created or datetime.now()\n\ncomment = Comment(email='leila@example.com', content='foo bar')\n\n\n\nWe'll declare a serializer that we can use to serialize and deserialize data that corresponds to \nComment\n objects.\n\n\nDeclaring a serializer looks very similar to declaring a form:\n\n\nfrom rest_framework import serializers\n\nclass CommentSerializer(serializers.Serializer):\n email = serializers.EmailField()\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n\n\nSerializing objects\n\n\nWe can now use \nCommentSerializer\n to serialize a comment, or list of comments. Again, using the \nSerializer\n class looks a lot like using a \nForm\n class.\n\n\nserializer = CommentSerializer(comment)\nserializer.data\n# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}\n\n\n\nAt this point we've translated the model instance into Python native datatypes. To finalise the serialization process we render the data into \njson\n.\n\n\nfrom rest_framework.renderers import JSONRenderer\n\njson = JSONRenderer().render(serializer.data)\njson\n# b'{\"email\":\"leila@example.com\",\"content\":\"foo bar\",\"created\":\"2016-01-27T15:17:10.375877\"}'\n\n\n\nDeserializing objects\n\n\nDeserialization is similar. First we parse a stream into Python native datatypes...\n\n\nfrom django.utils.six import BytesIO\nfrom rest_framework.parsers import JSONParser\n\nstream = BytesIO(json)\ndata = JSONParser().parse(stream)\n\n\n\n...then we restore those native datatypes into a dictionary of validated data.\n\n\nserializer = CommentSerializer(data=data)\nserializer.is_valid()\n# True\nserializer.validated_data\n# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}\n\n\n\nSaving instances\n\n\nIf we want to be able to return complete object instances based on the validated data we need to implement one or both of the \n.create()\n and \nupdate()\n methods. For example:\n\n\nclass CommentSerializer(serializers.Serializer):\n email = serializers.EmailField()\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n def create(self, validated_data):\n return Comment(**validated_data)\n\n def update(self, instance, validated_data):\n instance.email = validated_data.get('email', instance.email)\n instance.content = validated_data.get('content', instance.content)\n instance.created = validated_data.get('created', instance.created)\n return instance\n\n\n\nIf your object instances correspond to Django models you'll also want to ensure that these methods save the object to the database. For example, if \nComment\n was a Django model, the methods might look like this:\n\n\n def create(self, validated_data):\n return Comment.objects.create(**validated_data)\n\n def update(self, instance, validated_data):\n instance.email = validated_data.get('email', instance.email)\n instance.content = validated_data.get('content', instance.content)\n instance.created = validated_data.get('created', instance.created)\n instance.save()\n return instance\n\n\n\nNow when deserializing data, we can call \n.save()\n to return an object instance, based on the validated data.\n\n\ncomment = serializer.save()\n\n\n\nCalling \n.save()\n will either create a new instance, or update an existing instance, depending on if an existing instance was passed when instantiating the serializer class:\n\n\n# .save() will create a new instance.\nserializer = CommentSerializer(data=data)\n\n# .save() will update the existing `comment` instance.\nserializer = CommentSerializer(comment, data=data)\n\n\n\nBoth the \n.create()\n and \n.update()\n methods are optional. You can implement either neither, one, or both of them, depending on the use-case for your serializer class.\n\n\nPassing additional attributes to \n.save()\n\n\nSometimes you'll want your view code to be able to inject additional data at the point of saving the instance. This additional data might include information like the current user, the current time, or anything else that is not part of the request data.\n\n\nYou can do so by including additional keyword arguments when calling \n.save()\n. For example:\n\n\nserializer.save(owner=request.user)\n\n\n\nAny additional keyword arguments will be included in the \nvalidated_data\n argument when \n.create()\n or \n.update()\n are called.\n\n\nOverriding \n.save()\n directly.\n\n\nIn some cases the \n.create()\n and \n.update()\n method names may not be meaningful. For example, in a contact form we may not be creating new instances, but instead sending an email or other message.\n\n\nIn these cases you might instead choose to override \n.save()\n directly, as being more readable and meaningful.\n\n\nFor example:\n\n\nclass ContactForm(serializers.Serializer):\n email = serializers.EmailField()\n message = serializers.CharField()\n\n def save(self):\n email = self.validated_data['email']\n message = self.validated_data['message']\n send_email(from=email, message=message)\n\n\n\nNote that in the case above we're now having to access the serializer \n.validated_data\n property directly.\n\n\nValidation\n\n\nWhen deserializing data, you always need to call \nis_valid()\n before attempting to access the validated data, or save an object instance. If any validation errors occur, the \n.errors\n property will contain a dictionary representing the resulting error messages. For example:\n\n\nserializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})\nserializer.is_valid()\n# False\nserializer.errors\n# {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']}\n\n\n\nEach key in the dictionary will be the field name, and the values will be lists of strings of any error messages corresponding to that field. The \nnon_field_errors\n key may also be present, and will list any general validation errors. The name of the \nnon_field_errors\n key may be customized using the \nNON_FIELD_ERRORS_KEY\n REST framework setting.\n\n\nWhen deserializing a list of items, errors will be returned as a list of dictionaries representing each of the deserialized items.\n\n\nRaising an exception on invalid data\n\n\nThe \n.is_valid()\n method takes an optional \nraise_exception\n flag that will cause it to raise a \nserializers.ValidationError\n exception if there are validation errors.\n\n\nThese exceptions are automatically dealt with by the default exception handler that REST framework provides, and will return \nHTTP 400 Bad Request\n responses by default.\n\n\n# Return a 400 response if the data was invalid.\nserializer.is_valid(raise_exception=True)\n\n\n\nField-level validation\n\n\nYou can specify custom field-level validation by adding \n.validate_\nfield_name\n methods to your \nSerializer\n subclass. These are similar to the \n.clean_\nfield_name\n methods on Django forms.\n\n\nThese methods take a single argument, which is the field value that requires validation.\n\n\nYour \nvalidate_\nfield_name\n methods should return the validated value or raise a \nserializers.ValidationError\n. For example:\n\n\nfrom rest_framework import serializers\n\nclass BlogPostSerializer(serializers.Serializer):\n title = serializers.CharField(max_length=100)\n content = serializers.CharField()\n\n def validate_title(self, value):\n \"\"\"\n Check that the blog post is about Django.\n \"\"\"\n if 'django' not in value.lower():\n raise serializers.ValidationError(\"Blog post is not about Django\")\n return value\n\n\n\n\n\nNote:\n If your \nfield_name\n is declared on your serializer with the parameter \nrequired=False\n then this validation step will not take place if the field is not included.\n\n\n\n\nObject-level validation\n\n\nTo do any other validation that requires access to multiple fields, add a method called \n.validate()\n to your \nSerializer\n subclass. This method takes a single argument, which is a dictionary of field values. It should raise a \nValidationError\n if necessary, or just return the validated values. For example:\n\n\nfrom rest_framework import serializers\n\nclass EventSerializer(serializers.Serializer):\n description = serializers.CharField(max_length=100)\n start = serializers.DateTimeField()\n finish = serializers.DateTimeField()\n\n def validate(self, data):\n \"\"\"\n Check that the start is before the stop.\n \"\"\"\n if data['start'] \n data['finish']:\n raise serializers.ValidationError(\"finish must occur after start\")\n return data\n\n\n\nValidators\n\n\nIndividual fields on a serializer can include validators, by declaring them on the field instance, for example:\n\n\ndef multiple_of_ten(value):\n if value % 10 != 0:\n raise serializers.ValidationError('Not a multiple of ten')\n\nclass GameRecord(serializers.Serializer):\n score = IntegerField(validators=[multiple_of_ten])\n ...\n\n\n\nSerializer classes can also include reusable validators that are applied to the complete set of field data. These validators are included by declaring them on an inner \nMeta\n class, like so:\n\n\nclass EventSerializer(serializers.Serializer):\n name = serializers.CharField()\n room_number = serializers.IntegerField(choices=[101, 102, 103, 201])\n date = serializers.DateField()\n\n class Meta:\n # Each room only has one event per day.\n validators = UniqueTogetherValidator(\n queryset=Event.objects.all(),\n fields=['room_number', 'date']\n )\n\n\n\nFor more information see the \nvalidators documentation\n.\n\n\nAccessing the initial data and instance\n\n\nWhen passing an initial object or queryset to a serializer instance, the object will be made available as \n.instance\n. If no initial object is passed then the \n.instance\n attribute will be \nNone\n.\n\n\nWhen passing data to a serializer instance, the unmodified data will be made available as \n.initial_data\n. If the data keyword argument is not passed then the \n.initial_data\n attribute will not exist.\n\n\nPartial updates\n\n\nBy default, serializers must be passed values for all required fields or they will raise validation errors. You can use the \npartial\n argument in order to allow partial updates.\n\n\n# Update `comment` with partial data\nserializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)\n\n\n\nDealing with nested objects\n\n\nThe previous examples are fine for dealing with objects that only have simple datatypes, but sometimes we also need to be able to represent more complex objects, where some of the attributes of an object might not be simple datatypes such as strings, dates or integers.\n\n\nThe \nSerializer\n class is itself a type of \nField\n, and can be used to represent relationships where one object type is nested inside another.\n\n\nclass UserSerializer(serializers.Serializer):\n email = serializers.EmailField()\n username = serializers.CharField(max_length=100)\n\nclass CommentSerializer(serializers.Serializer):\n user = UserSerializer()\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n\n\nIf a nested representation may optionally accept the \nNone\n value you should pass the \nrequired=False\n flag to the nested serializer.\n\n\nclass CommentSerializer(serializers.Serializer):\n user = UserSerializer(required=False) # May be an anonymous user.\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n\n\nSimilarly if a nested representation should be a list of items, you should pass the \nmany=True\n flag to the nested serialized.\n\n\nclass CommentSerializer(serializers.Serializer):\n user = UserSerializer(required=False)\n edits = EditItemSerializer(many=True) # A nested list of 'edit' items.\n content = serializers.CharField(max_length=200)\n created = serializers.DateTimeField()\n\n\n\nWritable nested representations\n\n\nWhen dealing with nested representations that support deserializing the data, any errors with nested objects will be nested under the field name of the nested object.\n\n\nserializer = CommentSerializer(data={'user': {'email': 'foobar', 'username': 'doe'}, 'content': 'baz'})\nserializer.is_valid()\n# False\nserializer.errors\n# {'user': {'email': [u'Enter a valid e-mail address.']}, 'created': [u'This field is required.']}\n\n\n\nSimilarly, the \n.validated_data\n property will include nested data structures.\n\n\nWriting \n.create()\n methods for nested representations\n\n\nIf you're supporting writable nested representations you'll need to write \n.create()\n or \n.update()\n methods that handle saving multiple objects.\n\n\nThe following example demonstrates how you might handle creating a user with a nested profile object.\n\n\nclass UserSerializer(serializers.ModelSerializer):\n profile = ProfileSerializer()\n\n class Meta:\n model = User\n fields = ('username', 'email', 'profile')\n\n def create(self, validated_data):\n profile_data = validated_data.pop('profile')\n user = User.objects.create(**validated_data)\n Profile.objects.create(user=user, **profile_data)\n return user\n\n\n\nWriting \n.update()\n methods for nested representations\n\n\nFor updates you'll want to think carefully about how to handle updates to relationships. For example if the data for the relationship is \nNone\n, or not provided, which of the following should occur?\n\n\n\n\nSet the relationship to \nNULL\n in the database.\n\n\nDelete the associated instance.\n\n\nIgnore the data and leave the instance as it is.\n\n\nRaise a validation error.\n\n\n\n\nHere's an example for an \nupdate()\n method on our previous \nUserSerializer\n class.\n\n\n def update(self, instance, validated_data):\n profile_data = validated_data.pop('profile')\n # Unless the application properly enforces that this field is\n # always set, the follow could raise a `DoesNotExist`, which\n # would need to be handled.\n profile = instance.profile\n\n instance.username = validated_data.get('username', instance.username)\n instance.email = validated_data.get('email', instance.email)\n instance.save()\n\n profile.is_premium_member = profile_data.get(\n 'is_premium_member',\n profile.is_premium_member\n )\n profile.has_support_contract = profile_data.get(\n 'has_support_contract',\n profile.has_support_contract\n )\n profile.save()\n\n return instance\n\n\n\nBecause the behavior of nested creates and updates can be ambiguous, and may require complex dependencies between related models, REST framework 3 requires you to always write these methods explicitly. The default \nModelSerializer\n \n.create()\n and \n.update()\n methods do not include support for writable nested representations.\n\n\nIt is possible that a third party package, providing automatic support some kinds of automatic writable nested representations may be released alongside the 3.1 release.\n\n\nHandling saving related instances in model manager classes\n\n\nAn alternative to saving multiple related instances in the serializer is to write custom model manager classes that handle creating the correct instances.\n\n\nFor example, suppose we wanted to ensure that \nUser\n instances and \nProfile\n instances are always created together as a pair. We might write a custom manager class that looks something like this:\n\n\nclass UserManager(models.Manager):\n ...\n\n def create(self, username, email, is_premium_member=False, has_support_contract=False):\n user = User(username=username, email=email)\n user.save()\n profile = Profile(\n user=user,\n is_premium_member=is_premium_member,\n has_support_contract=has_support_contract\n )\n profile.save()\n return user\n\n\n\nThis manager class now more nicely encapsulates that user instances and profile instances are always created at the same time. Our \n.create()\n method on the serializer class can now be re-written to use the new manager method.\n\n\ndef create(self, validated_data):\n return User.objects.create(\n username=validated_data['username'],\n email=validated_data['email']\n is_premium_member=validated_data['profile']['is_premium_member']\n has_support_contract=validated_data['profile']['has_support_contract']\n )\n\n\n\nFor more details on this approach see the Django documentation on \nmodel managers\n, and \nthis blogpost on using model and manager classes\n.\n\n\nDealing with multiple objects\n\n\nThe \nSerializer\n class can also handle serializing or deserializing lists of objects.\n\n\nSerializing multiple objects\n\n\nTo serialize a queryset or list of objects instead of a single object instance, you should pass the \nmany=True\n flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.\n\n\nqueryset = Book.objects.all()\nserializer = BookSerializer(queryset, many=True)\nserializer.data\n# [\n# {'id': 0, 'title': 'The electric kool-aid acid test', 'author': 'Tom Wolfe'},\n# {'id': 1, 'title': 'If this is a man', 'author': 'Primo Levi'},\n# {'id': 2, 'title': 'The wind-up bird chronicle', 'author': 'Haruki Murakami'}\n# ]\n\n\n\nDeserializing multiple objects\n\n\nThe default behavior for deserializing multiple objects is to support multiple object creation, but not support multiple object updates. For more information on how to support or customize either of these cases, see the \nListSerializer\n documentation below.\n\n\nIncluding extra context\n\n\nThere are some cases where you need to provide extra context to the serializer in addition to the object being serialized. One common case is if you're using a serializer that includes hyperlinked relations, which requires the serializer to have access to the current request so that it can properly generate fully qualified URLs.\n\n\nYou can provide arbitrary additional context by passing a \ncontext\n argument when instantiating the serializer. For example:\n\n\nserializer = AccountSerializer(account, context={'request': request})\nserializer.data\n# {'id': 6, 'owner': u'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'}\n\n\n\nThe context dictionary can be used within any serializer field logic, such as a custom \n.to_representation()\n method, by accessing the \nself.context\n attribute.\n\n\n\n\nModelSerializer\n\n\nOften you'll want serializer classes that map closely to Django model definitions.\n\n\nThe \nModelSerializer\n class provides a shortcut that lets you automatically create a \nSerializer\n class with fields that correspond to the Model fields.\n\n\nThe \nModelSerializer\n class is the same as a regular \nSerializer\n class, except that\n:\n\n\n\n\nIt will automatically generate a set of fields for you, based on the model.\n\n\nIt will automatically generate validators for the serializer, such as unique_together validators.\n\n\nIt includes simple default implementations of \n.create()\n and \n.update()\n.\n\n\n\n\nDeclaring a \nModelSerializer\n looks like this:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created')\n\n\n\nBy default, all the model fields on the class will be mapped to a corresponding serializer fields.\n\n\nAny relationships such as foreign keys on the model will be mapped to \nPrimaryKeyRelatedField\n. Reverse relationships are not included by default unless explicitly included as specified in the \nserializer relations\n documentation.\n\n\nInspecting a \nModelSerializer\n\n\nSerializer classes generate helpful verbose representation strings, that allow you to fully inspect the state of their fields. This is particularly useful when working with \nModelSerializers\n where you want to determine what set of fields and validators are being automatically created for you.\n\n\nTo do so, open the Django shell, using \npython manage.py shell\n, then import the serializer class, instantiate it, and print the object representation\u2026\n\n\n from myapp.serializers import AccountSerializer\n\n serializer = AccountSerializer()\n\n print(repr(serializer))\nAccountSerializer():\n id = IntegerField(label='ID', read_only=True)\n name = CharField(allow_blank=True, max_length=100, required=False)\n owner = PrimaryKeyRelatedField(queryset=User.objects.all())\n\n\n\nSpecifying which fields to include\n\n\nIf you only want a subset of the default fields to be used in a model serializer, you can do so using \nfields\n or \nexclude\n options, just as you would with a \nModelForm\n. It is strongly recommended that you explicitly set all fields that should be serialized using the \nfields\n attribute. This will make it less likely to result in unintentionally exposing data when your models change.\n\n\nFor example:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created')\n\n\n\nYou can also set the \nfields\n attribute to the special value \n'__all__'\n to indicate that all fields in the model should be used.\n\n\nFor example:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = '__all__'\n\n\n\nYou can set the \nexclude\n attribute to a list of fields to be excluded from the serializer.\n\n\nFor example:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n exclude = ('users',)\n\n\n\nIn the example above, if the \nAccount\n model had 3 fields \naccount_name\n, \nusers\n, and \ncreated\n, this will result in the fields \naccount_name\n and \ncreated\n to be serialized.\n\n\nThe names in the \nfields\n and \nexclude\n attributes will normally map to model fields on the model class.\n\n\nAlternatively names in the \nfields\n options can map to properties or methods which take no arguments that exist on the model class.\n\n\nSpecifying nested serialization\n\n\nThe default \nModelSerializer\n uses primary keys for relationships, but you can also easily generate nested representations using the \ndepth\n option:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created')\n depth = 1\n\n\n\nThe \ndepth\n option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.\n\n\nIf you want to customize the way the serialization is done you'll need to define the field yourself.\n\n\nSpecifying fields explicitly\n\n\nYou can add extra fields to a \nModelSerializer\n or override the default fields by declaring fields on the class, just as you would for a \nSerializer\n class.\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n url = serializers.CharField(source='get_absolute_url', read_only=True)\n groups = serializers.PrimaryKeyRelatedField(many=True)\n\n class Meta:\n model = Account\n\n\n\nExtra fields can correspond to any property or callable on the model.\n\n\nSpecifying read only fields\n\n\nYou may wish to specify multiple fields as read-only. Instead of adding each field explicitly with the \nread_only=True\n attribute, you may use the shortcut Meta option, \nread_only_fields\n.\n\n\nThis option should be a list or tuple of field names, and is declared as follows:\n\n\nclass AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created')\n read_only_fields = ('account_name',)\n\n\n\nModel fields which have \neditable=False\n set, and \nAutoField\n fields will be set to read-only by default, and do not need to be added to the \nread_only_fields\n option.\n\n\n\n\nNote\n: There is a special-case where a read-only field is part of a \nunique_together\n constraint at the model level. In this case the field is required by the serializer class in order to validate the constraint, but should also not be editable by the user.\n\n\nThe right way to deal with this is to specify the field explicitly on the serializer, providing both the \nread_only=True\n and \ndefault=\u2026\n keyword arguments.\n\n\nOne example of this is a read-only relation to the currently authenticated \nUser\n which is \nunique_together\n with another identifier. In this case you would declare the user field like so:\n\n\nuser = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())\n\n\n\nPlease review the \nValidators Documentation\n for details on the \nUniqueTogetherValidator\n and \nCurrentUserDefault\n classes.\n\n\n\n\nAdditional keyword arguments\n\n\nThere is also a shortcut allowing you to specify arbitrary additional keyword arguments on fields, using the \nextra_kwargs\n option. As in the case of \nread_only_fields\n, this means you do not need to explicitly declare the field on the serializer.\n\n\nThis option is a dictionary, mapping field names to a dictionary of keyword arguments. For example:\n\n\nclass CreateUserSerializer(serializers.ModelSerializer):\n class Meta:\n model = User\n fields = ('email', 'username', 'password')\n extra_kwargs = {'password': {'write_only': True}}\n\n def create(self, validated_data):\n user = User(\n email=validated_data['email'],\n username=validated_data['username']\n )\n user.set_password(validated_data['password'])\n user.save()\n return user\n\n\n\nRelational fields\n\n\nWhen serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation for \nModelSerializer\n is to use the primary keys of the related instances.\n\n\nAlternative representations include serializing using hyperlinks, serializing complete nested representations, or serializing with a custom representation.\n\n\nFor full details see the \nserializer relations\n documentation.\n\n\nCustomizing field mappings\n\n\nThe ModelSerializer class also exposes an API that you can override in order to alter how serializer fields are automatically determined when instantiating the serializer.\n\n\nNormally if a \nModelSerializer\n does not generate the fields you need by default then you should either add them to the class explicitly, or simply use a regular \nSerializer\n class instead. However in some cases you may want to create a new base class that defines how the serializer fields are created for any given model.\n\n\n.serializer_field_mapping\n\n\nA mapping of Django model classes to REST framework serializer classes. You can override this mapping to alter the default serializer classes that should be used for each model class.\n\n\n.serializer_related_field\n\n\nThis property should be the serializer field class, that is used for relational fields by default.\n\n\nFor \nModelSerializer\n this defaults to \nPrimaryKeyRelatedField\n.\n\n\nFor \nHyperlinkedModelSerializer\n this defaults to \nserializers.HyperlinkedRelatedField\n.\n\n\nserializer_url_field\n\n\nThe serializer field class that should be used for any \nurl\n field on the serializer.\n\n\nDefaults to \nserializers.HyperlinkedIdentityField\n\n\nserializer_choice_field\n\n\nThe serializer field class that should be used for any choice fields on the serializer.\n\n\nDefaults to \nserializers.ChoiceField\n\n\nThe field_class and field_kwargs API\n\n\nThe following methods are called to determine the class and keyword arguments for each field that should be automatically included on the serializer. Each of these methods should return a two tuple of \n(field_class, field_kwargs)\n.\n\n\n.build_standard_field(self, field_name, model_field)\n\n\nCalled to generate a serializer field that maps to a standard model field.\n\n\nThe default implementation returns a serializer class based on the \nserializer_field_mapping\n attribute.\n\n\n.build_relational_field(self, field_name, relation_info)\n\n\nCalled to generate a serializer field that maps to a relational model field.\n\n\nThe default implementation returns a serializer class based on the \nserializer_relational_field\n attribute.\n\n\nThe \nrelation_info\n argument is a named tuple, that contains \nmodel_field\n, \nrelated_model\n, \nto_many\n and \nhas_through_model\n properties.\n\n\n.build_nested_field(self, field_name, relation_info, nested_depth)\n\n\nCalled to generate a serializer field that maps to a relational model field, when the \ndepth\n option has been set.\n\n\nThe default implementation dynamically creates a nested serializer class based on either \nModelSerializer\n or \nHyperlinkedModelSerializer\n.\n\n\nThe \nnested_depth\n will be the value of the \ndepth\n option, minus one.\n\n\nThe \nrelation_info\n argument is a named tuple, that contains \nmodel_field\n, \nrelated_model\n, \nto_many\n and \nhas_through_model\n properties.\n\n\n.build_property_field(self, field_name, model_class)\n\n\nCalled to generate a serializer field that maps to a property or zero-argument method on the model class.\n\n\nThe default implementation returns a \nReadOnlyField\n class.\n\n\n.build_url_field(self, field_name, model_class)\n\n\nCalled to generate a serializer field for the serializer's own \nurl\n field. The default implementation returns a \nHyperlinkedIdentityField\n class.\n\n\n.build_unknown_field(self, field_name, model_class)\n\n\nCalled when the field name did not map to any model field or model property.\nThe default implementation raises an error, although subclasses may customize this behavior.\n\n\n\n\nHyperlinkedModelSerializer\n\n\nThe \nHyperlinkedModelSerializer\n class is similar to the \nModelSerializer\n class except that it uses hyperlinks to represent relationships, rather than primary keys.\n\n\nBy default the serializer will include a \nurl\n field instead of a primary key field.\n\n\nThe url field will be represented using a \nHyperlinkedIdentityField\n serializer field, and any relationships on the model will be represented using a \nHyperlinkedRelatedField\n serializer field.\n\n\nYou can explicitly include the primary key by adding it to the \nfields\n option, for example:\n\n\nclass AccountSerializer(serializers.HyperlinkedModelSerializer):\n class Meta:\n model = Account\n fields = ('url', 'id', 'account_name', 'users', 'created')\n\n\n\nAbsolute and relative URLs\n\n\nWhen instantiating a \nHyperlinkedModelSerializer\n you must include the current\n\nrequest\n in the serializer context, for example:\n\n\nserializer = AccountSerializer(queryset, context={'request': request})\n\n\n\nDoing so will ensure that the hyperlinks can include an appropriate hostname,\nso that the resulting representation uses fully qualified URLs, such as:\n\n\nhttp://api.example.com/accounts/1/\n\n\n\nRather than relative URLs, such as:\n\n\n/accounts/1/\n\n\n\nIf you \ndo\n want to use relative URLs, you should explicitly pass \n{'request': None}\n\nin the serializer context.\n\n\nHow hyperlinked views are determined\n\n\nThere needs to be a way of determining which views should be used for hyperlinking to model instances.\n\n\nBy default hyperlinks are expected to correspond to a view name that matches the style \n'{model_name}-detail'\n, and looks up the instance by a \npk\n keyword argument.\n\n\nYou can override a URL field view name and lookup field by using either, or both of, the \nview_name\n and \nlookup_field\n options in the \nextra_kwargs\n setting, like so:\n\n\nclass AccountSerializer(serializers.HyperlinkedModelSerializer):\n class Meta:\n model = Account\n fields = ('account_url', 'account_name', 'users', 'created')\n extra_kwargs = {\n 'url': {'view_name': 'accounts', 'lookup_field': 'account_name'}\n 'users': {'lookup_field': 'username'}\n }\n\n\n\nAlternatively you can set the fields on the serializer explicitly. For example:\n\n\nclass AccountSerializer(serializers.HyperlinkedModelSerializer):\n url = serializers.HyperlinkedIdentityField(\n view_name='accounts',\n lookup_field='slug'\n )\n users = serializers.HyperlinkedRelatedField(\n view_name='user-detail',\n lookup_field='username',\n many=True,\n read_only=True\n )\n\n class Meta:\n model = Account\n fields = ('url', 'account_name', 'users', 'created')\n\n\n\n\n\nTip\n: Properly matching together hyperlinked representations and your URL conf can sometimes be a bit fiddly. Printing the \nrepr\n of a \nHyperlinkedModelSerializer\n instance is a particularly useful way to inspect exactly which view names and lookup fields the relationships are expected to map too.\n\n\n\n\nChanging the URL field name\n\n\nThe name of the URL field defaults to 'url'. You can override this globally, by using the \nURL_FIELD_NAME\n setting.\n\n\n\n\nListSerializer\n\n\nThe \nListSerializer\n class provides the behavior for serializing and validating multiple objects at once. You won't \ntypically\n need to use \nListSerializer\n directly, but should instead simply pass \nmany=True\n when instantiating a serializer.\n\n\nWhen a serializer is instantiated and \nmany=True\n is passed, a \nListSerializer\n instance will be created. The serializer class then becomes a child of the parent \nListSerializer\n\n\nThe following argument can also be passed to a \nListSerializer\n field or a serializer that is passed \nmany=True\n:\n\n\nallow_empty\n\n\nThis is \nTrue\n by default, but can be set to \nFalse\n if you want to disallow empty lists as valid input.\n\n\nCustomizing \nListSerializer\n behavior\n\n\nThere \nare\n a few use cases when you might want to customize the \nListSerializer\n behavior. For example:\n\n\n\n\nYou want to provide particular validation of the lists, such as checking that one element does not conflict with another element in a list.\n\n\nYou want to customize the create or update behavior of multiple objects.\n\n\n\n\nFor these cases you can modify the class that is used when \nmany=True\n is passed, by using the \nlist_serializer_class\n option on the serializer \nMeta\n class.\n\n\nFor example:\n\n\nclass CustomListSerializer(serializers.ListSerializer):\n ...\n\nclass CustomSerializer(serializers.Serializer):\n ...\n class Meta:\n list_serializer_class = CustomListSerializer\n\n\n\nCustomizing multiple create\n\n\nThe default implementation for multiple object creation is to simply call \n.create()\n for each item in the list. If you want to customize this behavior, you'll need to customize the \n.create()\n method on \nListSerializer\n class that is used when \nmany=True\n is passed.\n\n\nFor example:\n\n\nclass BookListSerializer(serializers.ListSerializer):\n def create(self, validated_data):\n books = [Book(**item) for item in validated_data]\n return Book.objects.bulk_create(books)\n\nclass BookSerializer(serializers.Serializer):\n ...\n class Meta:\n list_serializer_class = BookListSerializer\n\n\n\nCustomizing multiple update\n\n\nBy default the \nListSerializer\n class does not support multiple updates. This is because the behavior that should be expected for insertions and deletions is ambiguous.\n\n\nTo support multiple updates you'll need to do so explicitly. When writing your multiple update code make sure to keep the following in mind:\n\n\n\n\nHow do you determine which instance should be updated for each item in the list of data?\n\n\nHow should insertions be handled? Are they invalid, or do they create new objects?\n\n\nHow should removals be handled? Do they imply object deletion, or removing a relationship? Should they be silently ignored, or are they invalid?\n\n\nHow should ordering be handled? Does changing the position of two items imply any state change or is it ignored?\n\n\n\n\nYou will need to add an explicit \nid\n field to the instance serializer. The default implicitly-generated \nid\n field is marked as \nread_only\n. This causes it to be removed on updates. Once you declare it explicitly, it will be available in the list serializer's \nupdate\n method.\n\n\nHere's an example of how you might choose to implement multiple updates:\n\n\nclass BookListSerializer(serializers.ListSerializer):\n def update(self, instance, validated_data):\n # Maps for id-\ninstance and id-\ndata item.\n book_mapping = {book.id: book for book in instance}\n data_mapping = {item['id']: item for item in validated_data}\n\n # Perform creations and updates.\n ret = []\n for book_id, data in data_mapping.items():\n book = book_mapping.get(book_id, None)\n if book is None:\n ret.append(self.child.create(data))\n else:\n ret.append(self.child.update(book, data))\n\n # Perform deletions.\n for book_id, book in book_mapping.items():\n if book_id not in data_mapping:\n book.delete()\n\n return ret\n\nclass BookSerializer(serializers.Serializer):\n # We need to identify elements in the list using their primary key,\n # so use a writable field here, rather than the default which would be read-only.\n id = serializers.IntegerField()\n\n ...\n id = serializers.IntegerField(required=False)\n\n class Meta:\n list_serializer_class = BookListSerializer\n\n\n\nIt is possible that a third party package may be included alongside the 3.1 release that provides some automatic support for multiple update operations, similar to the \nallow_add_remove\n behavior that was present in REST framework 2.\n\n\nCustomizing ListSerializer initialization\n\n\nWhen a serializer with \nmany=True\n is instantiated, we need to determine which arguments and keyword arguments should be passed to the \n.__init__()\n method for both the child \nSerializer\n class, and for the parent \nListSerializer\n class.\n\n\nThe default implementation is to pass all arguments to both classes, except for \nvalidators\n, and any custom keyword arguments, both of which are assumed to be intended for the child serializer class.\n\n\nOccasionally you might need to explicitly specify how the child and parent classes should be instantiated when \nmany=True\n is passed. You can do so by using the \nmany_init\n class method.\n\n\n @classmethod\n def many_init(cls, *args, **kwargs):\n # Instantiate the child serializer.\n kwargs['child'] = cls()\n # Instantiate the parent list serializer.\n return CustomListSerializer(*args, **kwargs)\n\n\n\n\n\nBaseSerializer\n\n\nBaseSerializer\n class that can be used to easily support alternative serialization and deserialization styles.\n\n\nThis class implements the same basic API as the \nSerializer\n class:\n\n\n\n\n.data\n - Returns the outgoing primitive representation.\n\n\n.is_valid()\n - Deserializes and validates incoming data.\n\n\n.validated_data\n - Returns the validated incoming data.\n\n\n.errors\n - Returns any errors during validation.\n\n\n.save()\n - Persists the validated data into an object instance.\n\n\n\n\nThere are four methods that can be overridden, depending on what functionality you want the serializer class to support:\n\n\n\n\n.to_representation()\n - Override this to support serialization, for read operations.\n\n\n.to_internal_value()\n - Override this to support deserialization, for write operations.\n\n\n.create()\n and \n.update()\n - Override either or both of these to support saving instances.\n\n\n\n\nBecause this class provides the same interface as the \nSerializer\n class, you can use it with the existing generic class-based views exactly as you would for a regular \nSerializer\n or \nModelSerializer\n.\n\n\nThe only difference you'll notice when doing so is the \nBaseSerializer\n classes will not generate HTML forms in the browsable API. This is because the data they return does not include all the field information that would allow each field to be rendered into a suitable HTML input.\n\n\nRead-only \nBaseSerializer\n classes\n\n\nTo implement a read-only serializer using the \nBaseSerializer\n class, we just need to override the \n.to_representation()\n method. Let's take a look at an example using a simple Django model:\n\n\nclass HighScore(models.Model):\n created = models.DateTimeField(auto_now_add=True)\n player_name = models.CharField(max_length=10)\n score = models.IntegerField()\n\n\n\nIt's simple to create a read-only serializer for converting \nHighScore\n instances into primitive data types.\n\n\nclass HighScoreSerializer(serializers.BaseSerializer):\n def to_representation(self, obj):\n return {\n 'score': obj.score,\n 'player_name': obj.player_name\n }\n\n\n\nWe can now use this class to serialize single \nHighScore\n instances:\n\n\n@api_view(['GET'])\ndef high_score(request, pk):\n instance = HighScore.objects.get(pk=pk)\n serializer = HighScoreSerializer(instance)\n return Response(serializer.data)\n\n\n\nOr use it to serialize multiple instances:\n\n\n@api_view(['GET'])\ndef all_high_scores(request):\n queryset = HighScore.objects.order_by('-score')\n serializer = HighScoreSerializer(queryset, many=True)\n return Response(serializer.data)\n\n\n\nRead-write \nBaseSerializer\n classes\n\n\nTo create a read-write serializer we first need to implement a \n.to_internal_value()\n method. This method returns the validated values that will be used to construct the object instance, and may raise a \nValidationError\n if the supplied data is in an incorrect format.\n\n\nOnce you've implemented \n.to_internal_value()\n, the basic validation API will be available on the serializer, and you will be able to use \n.is_valid()\n, \n.validated_data\n and \n.errors\n.\n\n\nIf you want to also support \n.save()\n you'll need to also implement either or both of the \n.create()\n and \n.update()\n methods.\n\n\nHere's a complete example of our previous \nHighScoreSerializer\n, that's been updated to support both read and write operations.\n\n\nclass HighScoreSerializer(serializers.BaseSerializer):\n def to_internal_value(self, data):\n score = data.get('score')\n player_name = data.get('player_name')\n\n # Perform the data validation.\n if not score:\n raise ValidationError({\n 'score': 'This field is required.'\n })\n if not player_name:\n raise ValidationError({\n 'player_name': 'This field is required.'\n })\n if len(player_name) \n 10:\n raise ValidationError({\n 'player_name': 'May not be more than 10 characters.'\n })\n\n # Return the validated values. This will be available as\n # the `.validated_data` property.\n return {\n 'score': int(score),\n 'player_name': player_name\n }\n\n def to_representation(self, obj):\n return {\n 'score': obj.score,\n 'player_name': obj.player_name\n }\n\n def create(self, validated_data):\n return HighScore.objects.create(**validated_data)\n\n\n\nCreating new base classes\n\n\nThe \nBaseSerializer\n class is also useful if you want to implement new generic serializer classes for dealing with particular serialization styles, or for integrating with alternative storage backends.\n\n\nThe following class is an example of a generic serializer that can handle coercing arbitrary objects into primitive representations.\n\n\nclass ObjectSerializer(serializers.BaseSerializer):\n \"\"\"\n A read-only serializer that coerces arbitrary complex objects\n into primitive representations.\n \"\"\"\n def to_representation(self, obj):\n for attribute_name in dir(obj):\n attribute = getattr(obj, attribute_name)\n if attribute_name('_'):\n # Ignore private attributes.\n pass\n elif hasattr(attribute, '__call__'):\n # Ignore methods and other callables.\n pass\n elif isinstance(attribute, (str, int, bool, float, type(None))):\n # Primitive types can be passed through unmodified.\n output[attribute_name] = attribute\n elif isinstance(attribute, list):\n # Recursively deal with items in lists.\n output[attribute_name] = [\n self.to_representation(item) for item in attribute\n ]\n elif isinstance(attribute, dict):\n # Recursively deal with items in dictionaries.\n output[attribute_name] = {\n str(key): self.to_representation(value)\n for key, value in attribute.items()\n }\n else:\n # Force anything else to its string representation.\n output[attribute_name] = str(attribute)\n\n\n\n\n\nAdvanced serializer usage\n\n\nOverriding serialization and deserialization behavior\n\n\nIf you need to alter the serialization, deserialization or validation of a serializer class you can do so by overriding the \n.to_representation()\n or \n.to_internal_value()\n methods.\n\n\nSome reasons this might be useful include...\n\n\n\n\nAdding new behavior for new serializer base classes.\n\n\nModifying the behavior slightly for an existing class.\n\n\nImproving serialization performance for a frequently accessed API endpoint that returns lots of data.\n\n\n\n\nThe signatures for these methods are as follows:\n\n\n.to_representation(self, obj)\n\n\nTakes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API.\n\n\n.to_internal_value(self, data)\n\n\nTakes the unvalidated incoming data as input and should return the validated data that will be made available as \nserializer.validated_data\n. The return value will also be passed to the \n.create()\n or \n.update()\n methods if \n.save()\n is called on the serializer class.\n\n\nIf any of the validation fails, then the method should raise a \nserializers.ValidationError(errors)\n. Typically the \nerrors\n argument here will be a dictionary mapping field names to error messages.\n\n\nThe \ndata\n argument passed to this method will normally be the value of \nrequest.data\n, so the datatype it provides will depend on the parser classes you have configured for your API.\n\n\nSerializer Inheritance\n\n\nSimilar to Django forms, you can extend and reuse serializers through inheritance. This allows you to declare a common set of fields or methods on a parent class that can then be used in a number of serializers. For example,\n\n\nclass MyBaseSerializer(Serializer):\n my_field = serializers.CharField()\n\n def validate_my_field(self):\n ...\n\nclass MySerializer(MyBaseSerializer):\n ...\n\n\n\nLike Django's \nModel\n and \nModelForm\n classes, the inner \nMeta\n class on serializers does not implicitly inherit from it's parents' inner \nMeta\n classes. If you want the \nMeta\n class to inherit from a parent class you must do so explicitly. For example:\n\n\nclass AccountSerializer(MyBaseSerializer):\n class Meta(MyBaseSerializer.Meta):\n model = Account\n\n\n\nTypically we would recommend \nnot\n using inheritance on inner Meta classes, but instead declaring all options explicitly.\n\n\nAdditionally, the following caveats apply to serializer inheritance:\n\n\n\n\nNormal Python name resolution rules apply. If you have multiple base classes that declare a \nMeta\n inner class, only the first one will be used. This means the child\u2019s \nMeta\n, if it exists, otherwise the \nMeta\n of the first parent, etc.\n\n\n\n\nIt\u2019s possible to declaratively remove a \nField\n inherited from a parent class by setting the name to be \nNone\n on the subclass.\n\n\nclass MyBaseSerializer(ModelSerializer):\n my_field = serializers.CharField()\n\nclass MySerializer(MyBaseSerializer):\n my_field = None\n\n\n\nHowever, you can only use this technique to opt out from a field defined declaratively by a parent class; it won\u2019t prevent the \nModelSerializer\n from generating a default field. To opt-out from default fields, see \nSpecifying which fields to include\n.\n\n\n\n\n\n\nDynamically modifying fields\n\n\nOnce a serializer has been initialized, the dictionary of fields that are set on the serializer may be accessed using the \n.fields\n attribute. Accessing and modifying this attribute allows you to dynamically modify the serializer.\n\n\nModifying the \nfields\n argument directly allows you to do interesting things such as changing the arguments on serializer fields at runtime, rather than at the point of declaring the serializer.\n\n\nExample\n\n\nFor example, if you wanted to be able to set which fields should be used by a serializer at the point of initializing it, you could create a serializer class like so:\n\n\nclass DynamicFieldsModelSerializer(serializers.ModelSerializer):\n \"\"\"\n A ModelSerializer that takes an additional `fields` argument that\n controls which fields should be displayed.\n \"\"\"\n\n def __init__(self, *args, **kwargs):\n # Don't pass the 'fields' arg up to the superclass\n fields = kwargs.pop('fields', None)\n\n # Instantiate the superclass normally\n super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)\n\n if fields is not None:\n # Drop any fields that are not specified in the `fields` argument.\n allowed = set(fields)\n existing = set(self.fields.keys())\n for field_name in existing - allowed:\n self.fields.pop(field_name)\n\n\n\nThis would then allow you to do the following:\n\n\n class UserSerializer(DynamicFieldsModelSerializer):\n\n class Meta:\n\n model = User\n\n fields = ('id', 'username', 'email')\n\n\n\n print UserSerializer(user)\n{'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'}\n\n\n\n print UserSerializer(user, fields=('id', 'email'))\n{'id': 2, 'email': 'jon@example.com'}\n\n\n\nCustomizing the default fields\n\n\nREST framework 2 provided an API to allow developers to override how a \nModelSerializer\n class would automatically generate the default set of fields.\n\n\nThis API included the \n.get_field()\n, \n.get_pk_field()\n and other methods.\n\n\nBecause the serializers have been fundamentally redesigned with 3.0 this API no longer exists. You can still modify the fields that get created but you'll need to refer to the source code, and be aware that if the changes you make are against private bits of API then they may be subject to change.\n\n\nA new interface for controlling this behavior is currently planned for REST framework 3.1.\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nDjango REST marshmallow\n\n\nThe \ndjango-rest-marshmallow\n package provides an alternative implementation for serializers, using the python \nmarshmallow\n library. It exposes the same API as the REST framework serializers, and can be used as a drop-in replacement in some use-cases.\n\n\nSerpy\n\n\nThe \nserpy\n package is an alternative implementation for serializers that is built for speed. \nSerpy\n serializes complex datatypes to simple native types. The native types can be easily converted to JSON or any other format needed.\n\n\nMongoengineModelSerializer\n\n\nThe \ndjango-rest-framework-mongoengine\n package provides a \nMongoEngineModelSerializer\n serializer class that supports using MongoDB as the storage layer for Django REST framework.\n\n\nGeoFeatureModelSerializer\n\n\nThe \ndjango-rest-framework-gis\n package provides a \nGeoFeatureModelSerializer\n serializer class that supports GeoJSON both for read and write operations.\n\n\nHStoreSerializer\n\n\nThe \ndjango-rest-framework-hstore\n package provides an \nHStoreSerializer\n to support \ndjango-hstore\n \nDictionaryField\n model field and its \nschema-mode\n feature.\n\n\nDynamic REST\n\n\nThe \ndynamic-rest\n package extends the ModelSerializer and ModelViewSet interfaces, adding API query parameters for filtering, sorting, and including / excluding all fields and relationships defined by your serializers.\n\n\nDynamic Fields Mixin\n\n\nThe \ndrf-dynamic-fields\n package provides a mixin to dynamically limit the fields per serializer to a subset specified by an URL parameter.\n\n\nDRF FlexFields\n\n\nThe \ndrf-flex-fields\n package extends the ModelSerializer and ModelViewSet to provide commonly used functionality for dynamically setting fields and expanding primitive fields to nested models, both from URL parameters and your serializer class definitions.\n\n\nSerializer Extensions\n\n\nThe \ndjango-rest-framework-serializer-extensions\n\npackage provides a collection of tools to DRY up your serializers, by allowing\nfields to be defined on a per-view/request basis. Fields can be whitelisted,\nblacklisted and child serializers can be optionally expanded.\n\n\nHTML JSON Forms\n\n\nThe \nhtml-json-forms\n package provides an algorithm and serializer for processing \nform\n submissions per the (inactive) \nHTML JSON Form specification\n. The serializer facilitates processing of arbitrarily nested JSON structures within HTML. For example, \ninput name=\"items[0][id]\" value=\"5\"\n will be interpreted as \n{\"items\": [{\"id\": \"5\"}]}\n.\n\n\nDRF-Base64\n\n\nDRF-Base64\n provides a set of field and model serializers that handles the upload of base64-encoded files.\n\n\nQueryFields\n\n\ndjangorestframework-queryfields\n allows API clients to specify which fields will be sent in the response via inclusion/exclusion query parameters.",
"title": "Serializers"
},
{
@@ -1727,7 +1727,7 @@
},
{
"location": "/api-guide/serializers/#queryfields",
- "text": "djangorestframework-queryfields allows API clients to specify which fields will be sent in the response via inclusion or exclusion query paramaters.",
+ "text": "djangorestframework-queryfields allows API clients to specify which fields will be sent in the response via inclusion/exclusion query parameters.",
"title": "QueryFields"
},
{
@@ -2462,7 +2462,7 @@
},
{
"location": "/api-guide/permissions/",
- "text": "Permissions\n\n\n\n\nAuthentication or identification by itself is not usually sufficient to gain access to information or code. For that, the entity requesting access must have authorization.\n\n\n \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 retrive 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.",
+ "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.",
"title": "Permissions"
},
{
@@ -2562,7 +2562,7 @@
},
{
"location": "/api-guide/permissions/#dry-rest-permissions",
- "text": "The DRY Rest Permissions package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrive per user.",
+ "text": "The DRY Rest Permissions package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrieve per user.",
"title": "DRY Rest Permissions"
},
{
@@ -2570,6 +2570,11 @@
"text": "The Django Rest Framework Roles package makes it easier to parameterize your API over multiple types of users.",
"title": "Django Rest Framework Roles"
},
+ {
+ "location": "/api-guide/permissions/#django-rest-framework-api-key",
+ "text": "The Django Rest Framework API Key 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.",
+ "title": "Django Rest Framework API Key"
+ },
{
"location": "/api-guide/throttling/",
"text": "Throttling\n\n\n\n\nHTTP/1.1 420 Enhance Your Calm\n\n\nTwitter API rate limiting response\n\n\n\n\nThrottling is similar to \npermissions\n, in that it determines if a request should be authorized. Throttles indicate a temporary state, and are used to control the rate of requests that clients can make to an API.\n\n\nAs with permissions, multiple throttles may be used. Your API might have a restrictive throttle for unauthenticated requests, and a less restrictive throttle for authenticated requests.\n\n\nAnother scenario where you might want to use multiple throttles would be if you need to impose different constraints on different parts of the API, due to some services being particularly resource-intensive.\n\n\nMultiple throttles can also be used if you want to impose both burst throttling rates, and sustained throttling rates. For example, you might want to limit a user to a maximum of 60 requests per minute, and 1000 requests per day.\n\n\nThrottles do not necessarily only refer to rate-limiting requests. For example a storage service might also need to throttle against bandwidth, and a paid data service might want to throttle against a certain number of a records being accessed.\n\n\nHow throttling is determined\n\n\nAs with permissions and authentication, throttling in REST framework is always defined as a list of classes.\n\n\nBefore running the main body of the view each throttle in the list is checked.\nIf any throttle check fails an \nexceptions.Throttled\n exception will be raised, and the main body of the view will not run.\n\n\nSetting the throttling policy\n\n\nThe default throttling policy may be set globally, using the \nDEFAULT_THROTTLE_CLASSES\n and \nDEFAULT_THROTTLE_RATES\n settings. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_THROTTLE_CLASSES': (\n 'rest_framework.throttling.AnonRateThrottle',\n 'rest_framework.throttling.UserRateThrottle'\n ),\n 'DEFAULT_THROTTLE_RATES': {\n 'anon': '100/day',\n 'user': '1000/day'\n }\n}\n\n\n\nThe rate descriptions used in \nDEFAULT_THROTTLE_RATES\n may include \nsecond\n, \nminute\n, \nhour\n or \nday\n as the throttle period.\n\n\nYou can also set the throttling policy on a per-view or per-viewset basis,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.response import Response\nfrom rest_framework.throttling import UserRateThrottle\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n throttle_classes = (UserRateThrottle,)\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\n@api_view(['GET'])\n@throttle_classes([UserRateThrottle])\ndef example_view(request, format=None):\n content = {\n 'status': 'request was permitted'\n }\n return Response(content)\n\n\n\nHow clients are identified\n\n\nThe \nX-Forwarded-For\n and \nRemote-Addr\n HTTP headers are used to uniquely identify client IP addresses for throttling. If the \nX-Forwarded-For\n header is present then it will be used, otherwise the value of the \nRemote-Addr\n header will be used.\n\n\nIf you need to strictly identify unique client IP addresses, you'll need to first configure the number of application proxies that the API runs behind by setting the \nNUM_PROXIES\n setting. This setting should be an integer of zero or more. If set to non-zero then the client IP will be identified as being the last IP address in the \nX-Forwarded-For\n header, once any application proxy IP addresses have first been excluded. If set to zero, then the \nRemote-Addr\n header will always be used as the identifying IP address.\n\n\nIt is important to understand that if you configure the \nNUM_PROXIES\n setting, then all clients behind a unique \nNAT'd\n gateway will be treated as a single client.\n\n\nFurther context on how the \nX-Forwarded-For\n header works, and identifying a remote client IP can be \nfound here\n.\n\n\nSetting up the cache\n\n\nThe throttle classes provided by REST framework use Django's cache backend. You should make sure that you've set appropriate \ncache settings\n. The default value of \nLocMemCache\n backend should be okay for simple setups. See Django's \ncache documentation\n for more details.\n\n\nIf you need to use a cache other than \n'default'\n, you can do so by creating a custom throttle class and setting the \ncache\n attribute. For example:\n\n\nclass CustomAnonRateThrottle(AnonRateThrottle):\n cache = get_cache('alternate')\n\n\n\nYou'll need to remember to also set your custom throttle class in the \n'DEFAULT_THROTTLE_CLASSES'\n settings key, or using the \nthrottle_classes\n view attribute.\n\n\n\n\nAPI Reference\n\n\nAnonRateThrottle\n\n\nThe \nAnonRateThrottle\n will only ever throttle unauthenticated users. The IP address of the incoming request is used to generate a unique key to throttle against.\n\n\nThe allowed request rate is determined from one of the following (in order of preference).\n\n\n\n\nThe \nrate\n property on the class, which may be provided by overriding \nAnonRateThrottle\n and setting the property.\n\n\nThe \nDEFAULT_THROTTLE_RATES['anon']\n setting.\n\n\n\n\nAnonRateThrottle\n is suitable if you want to restrict the rate of requests from unknown sources.\n\n\nUserRateThrottle\n\n\nThe \nUserRateThrottle\n will throttle users to a given rate of requests across the API. The user id is used to generate a unique key to throttle against. Unauthenticated requests will fall back to using the IP address of the incoming request to generate a unique key to throttle against.\n\n\nThe allowed request rate is determined from one of the following (in order of preference).\n\n\n\n\nThe \nrate\n property on the class, which may be provided by overriding \nUserRateThrottle\n and setting the property.\n\n\nThe \nDEFAULT_THROTTLE_RATES['user']\n setting.\n\n\n\n\nAn API may have multiple \nUserRateThrottles\n in place at the same time. To do so, override \nUserRateThrottle\n and set a unique \"scope\" for each class.\n\n\nFor example, multiple user throttle rates could be implemented by using the following classes...\n\n\nclass BurstRateThrottle(UserRateThrottle):\n scope = 'burst'\n\nclass SustainedRateThrottle(UserRateThrottle):\n scope = 'sustained'\n\n\n\n...and the following settings.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_THROTTLE_CLASSES': (\n 'example.throttles.BurstRateThrottle',\n 'example.throttles.SustainedRateThrottle'\n ),\n 'DEFAULT_THROTTLE_RATES': {\n 'burst': '60/min',\n 'sustained': '1000/day'\n }\n}\n\n\n\nUserRateThrottle\n is suitable if you want simple global rate restrictions per-user.\n\n\nScopedRateThrottle\n\n\nThe \nScopedRateThrottle\n class can be used to restrict access to specific parts of the API. This throttle will only be applied if the view that is being accessed includes a \n.throttle_scope\n property. The unique throttle key will then be formed by concatenating the \"scope\" of the request with the unique user id or IP address.\n\n\nThe allowed request rate is determined by the \nDEFAULT_THROTTLE_RATES\n setting using a key from the request \"scope\".\n\n\nFor example, given the following views...\n\n\nclass ContactListView(APIView):\n throttle_scope = 'contacts'\n ...\n\nclass ContactDetailView(APIView):\n throttle_scope = 'contacts'\n ...\n\nclass UploadView(APIView):\n throttle_scope = 'uploads'\n ...\n\n\n\n...and the following settings.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_THROTTLE_CLASSES': (\n 'rest_framework.throttling.ScopedRateThrottle',\n ),\n 'DEFAULT_THROTTLE_RATES': {\n 'contacts': '1000/day',\n 'uploads': '20/day'\n }\n}\n\n\n\nUser requests to either \nContactListView\n or \nContactDetailView\n would be restricted to a total of 1000 requests per-day. User requests to \nUploadView\n would be restricted to 20 requests per day.\n\n\n\n\nCustom throttles\n\n\nTo create a custom throttle, override \nBaseThrottle\n and implement \n.allow_request(self, request, view)\n. The method should return \nTrue\n if the request should be allowed, and \nFalse\n otherwise.\n\n\nOptionally you may also override the \n.wait()\n method. If implemented, \n.wait()\n should return a recommended number of seconds to wait before attempting the next request, or \nNone\n. The \n.wait()\n method will only be called if \n.allow_request()\n has previously returned \nFalse\n.\n\n\nIf the \n.wait()\n method is implemented and the request is throttled, then a \nRetry-After\n header will be included in the response.\n\n\nExample\n\n\nThe following is an example of a rate throttle, that will randomly throttle 1 in every 10 requests.\n\n\nimport random\n\nclass RandomRateThrottle(throttling.BaseThrottle):\n def allow_request(self, request, view):\n return random.randint(1, 10) != 1",
@@ -3012,7 +3017,7 @@
},
{
"location": "/api-guide/metadata/",
- "text": "Metadata\n\n\n\n\n[The \nOPTIONS\n] method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.\n\n\n \nRFC7231, Section 4.3.7.\n\n\n\n\nREST framework includes a configurable mechanism for determining how your API should respond to \nOPTIONS\n requests. This allows you to return API schema or other resource information.\n\n\nThere are not currently any widely adopted conventions for exactly what style of response should be returned for HTTP \nOPTIONS\n requests, so we provide an ad-hoc style that returns some useful information.\n\n\nHere's an example response that demonstrates the information that is returned by default.\n\n\nHTTP 200 OK\nAllow: GET, POST, HEAD, OPTIONS\nContent-Type: application/json\n\n{\n \"name\": \"To Do List\",\n \"description\": \"List existing 'To Do' items, or create a new item.\",\n \"renders\": [\n \"application/json\",\n \"text/html\"\n ],\n \"parses\": [\n \"application/json\",\n \"application/x-www-form-urlencoded\",\n \"multipart/form-data\"\n ],\n \"actions\": {\n \"POST\": {\n \"note\": {\n \"type\": \"string\",\n \"required\": false,\n \"read_only\": false,\n \"label\": \"title\",\n \"max_length\": 100\n }\n }\n }\n}\n\n\n\nSetting the metadata scheme\n\n\nYou can set the metadata class globally using the \n'DEFAULT_METADATA_CLASS'\n settings key:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata'\n}\n\n\n\nOr you can set the metadata class individually for a view:\n\n\nclass APIRoot(APIView):\n metadata_class = APIRootMetadata\n\n def get(self, request, format=None):\n return Response({\n ...\n })\n\n\n\nThe REST framework package only includes a single metadata class implementation, named \nSimpleMetadata\n. If you want to use an alternative style you'll need to implement a custom metadata class.\n\n\nCreating schema endpoints\n\n\nIf you have specific requirements for creating schema endpoints that are accessed with regular \nGET\n requests, you might consider re-using the metadata API for doing so.\n\n\nFor example, the following additional route could be used on a viewset to provide a linkable schema endpoint.\n\n\n@list_route(methods=['GET'])\ndef schema(self, request):\n meta = self.metadata_class()\n data = meta.determine_metadata(request, self)\n return Response(data)\n\n\n\nThere are a couple of reasons that you might choose to take this approach, including that \nOPTIONS\n responses \nare not cacheable\n.\n\n\n\n\nCustom metadata classes\n\n\nIf you want to provide a custom metadata class you should override \nBaseMetadata\n and implement the \ndetermine_metadata(self, request, view)\n method.\n\n\nUseful things that you might want to do could include returning schema information, using a format such as \nJSON schema\n, or returning debug information to admin users.\n\n\nExample\n\n\nThe following class could be used to limit the information that is returned to \nOPTIONS\n requests.\n\n\nclass MinimalMetadata(BaseMetadata):\n \"\"\"\n Don't include field and other information for `OPTIONS` requests.\n Just return the name and description.\n \"\"\"\n def determine_metadata(self, request, view):\n return {\n 'name': view.get_view_name(),\n 'description': view.get_view_description()\n }\n\n\n\nThen configure your settings to use this custom class:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_METADATA_CLASS': 'myproject.apps.core.MinimalMetadata'\n}\n\n\n\nThird party packages\n\n\nThe following third party packages provide additional metadata implementations.\n\n\nDRF-schema-adapter\n\n\ndrf-schema-adapter\n is a set of tools that makes it easier to provide schema information to frontend frameworks and libraries. It provides a metadata mixin as well as 2 metadata classes and several adapters suitable to generate \njson-schema\n as well as schema information readable by various libraries.\n\n\nYou can also write your own adapter to work with your specific frontend.\nIf you whish to do so, it also provides an exporter that can export those schema information to json files.",
+ "text": "Metadata\n\n\n\n\n[The \nOPTIONS\n] method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.\n\n\n \nRFC7231, Section 4.3.7.\n\n\n\n\nREST framework includes a configurable mechanism for determining how your API should respond to \nOPTIONS\n requests. This allows you to return API schema or other resource information.\n\n\nThere are not currently any widely adopted conventions for exactly what style of response should be returned for HTTP \nOPTIONS\n requests, so we provide an ad-hoc style that returns some useful information.\n\n\nHere's an example response that demonstrates the information that is returned by default.\n\n\nHTTP 200 OK\nAllow: GET, POST, HEAD, OPTIONS\nContent-Type: application/json\n\n{\n \"name\": \"To Do List\",\n \"description\": \"List existing 'To Do' items, or create a new item.\",\n \"renders\": [\n \"application/json\",\n \"text/html\"\n ],\n \"parses\": [\n \"application/json\",\n \"application/x-www-form-urlencoded\",\n \"multipart/form-data\"\n ],\n \"actions\": {\n \"POST\": {\n \"note\": {\n \"type\": \"string\",\n \"required\": false,\n \"read_only\": false,\n \"label\": \"title\",\n \"max_length\": 100\n }\n }\n }\n}\n\n\n\nSetting the metadata scheme\n\n\nYou can set the metadata class globally using the \n'DEFAULT_METADATA_CLASS'\n settings key:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata'\n}\n\n\n\nOr you can set the metadata class individually for a view:\n\n\nclass APIRoot(APIView):\n metadata_class = APIRootMetadata\n\n def get(self, request, format=None):\n return Response({\n ...\n })\n\n\n\nThe REST framework package only includes a single metadata class implementation, named \nSimpleMetadata\n. If you want to use an alternative style you'll need to implement a custom metadata class.\n\n\nCreating schema endpoints\n\n\nIf you have specific requirements for creating schema endpoints that are accessed with regular \nGET\n requests, you might consider re-using the metadata API for doing so.\n\n\nFor example, the following additional route could be used on a viewset to provide a linkable schema endpoint.\n\n\n@list_route(methods=['GET'])\ndef schema(self, request):\n meta = self.metadata_class()\n data = meta.determine_metadata(request, self)\n return Response(data)\n\n\n\nThere are a couple of reasons that you might choose to take this approach, including that \nOPTIONS\n responses \nare not cacheable\n.\n\n\n\n\nCustom metadata classes\n\n\nIf you want to provide a custom metadata class you should override \nBaseMetadata\n and implement the \ndetermine_metadata(self, request, view)\n method.\n\n\nUseful things that you might want to do could include returning schema information, using a format such as \nJSON schema\n, or returning debug information to admin users.\n\n\nExample\n\n\nThe following class could be used to limit the information that is returned to \nOPTIONS\n requests.\n\n\nclass MinimalMetadata(BaseMetadata):\n \"\"\"\n Don't include field and other information for `OPTIONS` requests.\n Just return the name and description.\n \"\"\"\n def determine_metadata(self, request, view):\n return {\n 'name': view.get_view_name(),\n 'description': view.get_view_description()\n }\n\n\n\nThen configure your settings to use this custom class:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_METADATA_CLASS': 'myproject.apps.core.MinimalMetadata'\n}\n\n\n\nThird party packages\n\n\nThe following third party packages provide additional metadata implementations.\n\n\nDRF-schema-adapter\n\n\ndrf-schema-adapter\n is a set of tools that makes it easier to provide schema information to frontend frameworks and libraries. It provides a metadata mixin as well as 2 metadata classes and several adapters suitable to generate \njson-schema\n as well as schema information readable by various libraries.\n\n\nYou can also write your own adapter to work with your specific frontend.\nIf you wish to do so, it also provides an exporter that can export those schema information to json files.",
"title": "Metadata"
},
{
@@ -3047,12 +3052,12 @@
},
{
"location": "/api-guide/metadata/#drf-schema-adapter",
- "text": "drf-schema-adapter is a set of tools that makes it easier to provide schema information to frontend frameworks and libraries. It provides a metadata mixin as well as 2 metadata classes and several adapters suitable to generate json-schema as well as schema information readable by various libraries. You can also write your own adapter to work with your specific frontend.\nIf you whish to do so, it also provides an exporter that can export those schema information to json files.",
+ "text": "drf-schema-adapter is a set of tools that makes it easier to provide schema information to frontend frameworks and libraries. It provides a metadata mixin as well as 2 metadata classes and several adapters suitable to generate json-schema as well as schema information readable by various libraries. You can also write your own adapter to work with your specific frontend.\nIf you wish to do so, it also provides an exporter that can export those schema information to json files.",
"title": "DRF-schema-adapter"
},
{
"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\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/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.",
"title": "Schemas"
},
{
@@ -3095,6 +3100,11 @@
"text": "May be used to pass a canonical URL for the schema. schema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/'\n)",
"title": "url"
},
+ {
+ "location": "/api-guide/schemas/#urlconf",
+ "text": "A 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. schema_view = get_schema_view(\n title='Server Monitoring API',\n url='https://www.example.org/api/',\n urlconf='myproject.urls'\n)",
+ "title": "urlconf"
+ },
{
"location": "/api-guide/schemas/#renderer_classes",
"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)",
@@ -3602,7 +3612,7 @@
},
{
"location": "/api-guide/settings/",
- "text": "Settings\n\n\n\n\nNamespaces are one honking great idea - let's do more of those!\n\n\n \nThe Zen of Python\n\n\n\n\nConfiguration for REST framework is all namespaced inside a single Django setting, named \nREST_FRAMEWORK\n.\n\n\nFor example your project's \nsettings.py\n file might include something like this:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework.renderers.JSONRenderer',\n ),\n 'DEFAULT_PARSER_CLASSES': (\n 'rest_framework.parsers.JSONParser',\n )\n}\n\n\n\nAccessing settings\n\n\nIf you need to access the values of REST framework's API settings in your project,\nyou should use the \napi_settings\n object. For example.\n\n\nfrom rest_framework.settings import api_settings\n\nprint api_settings.DEFAULT_AUTHENTICATION_CLASSES\n\n\n\nThe \napi_settings\n object will check for any user-defined settings, and otherwise fall back to the default values. Any setting that uses string import paths to refer to a class will automatically import and return the referenced class, instead of the string literal.\n\n\n\n\nAPI Reference\n\n\nAPI policy settings\n\n\nThe following settings control the basic API policies, and are applied to every \nAPIView\n class-based view, or \n@api_view\n function based view.\n\n\nDEFAULT_RENDERER_CLASSES\n\n\nA list or tuple of renderer classes, that determines the default set of renderers that may be used when returning a \nResponse\n object.\n\n\nDefault:\n\n\n(\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n)\n\n\n\nDEFAULT_PARSER_CLASSES\n\n\nA list or tuple of parser classes, that determines the default set of parsers used when accessing the \nrequest.data\n property.\n\n\nDefault:\n\n\n(\n 'rest_framework.parsers.JSONParser',\n 'rest_framework.parsers.FormParser',\n 'rest_framework.parsers.MultiPartParser'\n)\n\n\n\nDEFAULT_AUTHENTICATION_CLASSES\n\n\nA list or tuple of authentication classes, that determines the default set of authenticators used when accessing the \nrequest.user\n or \nrequest.auth\n properties.\n\n\nDefault:\n\n\n(\n 'rest_framework.authentication.SessionAuthentication',\n 'rest_framework.authentication.BasicAuthentication'\n)\n\n\n\nDEFAULT_PERMISSION_CLASSES\n\n\nA list or tuple of permission classes, that determines the default set of permissions checked at the start of a view. Permission must be granted by every class in the list.\n\n\nDefault:\n\n\n(\n 'rest_framework.permissions.AllowAny',\n)\n\n\n\nDEFAULT_THROTTLE_CLASSES\n\n\nA list or tuple of throttle classes, that determines the default set of throttles checked at the start of a view.\n\n\nDefault: \n()\n\n\nDEFAULT_CONTENT_NEGOTIATION_CLASS\n\n\nA content negotiation class, that determines how a renderer is selected for the response, given an incoming request.\n\n\nDefault: \n'rest_framework.negotiation.DefaultContentNegotiation'\n\n\n\n\nGeneric view settings\n\n\nThe following settings control the behavior of the generic class-based views.\n\n\nDEFAULT_PAGINATION_SERIALIZER_CLASS\n\n\n\n\nThis setting has been removed.\n\n\nThe pagination API does not use serializers to determine the output format, and\nyou'll need to instead override the `get_paginated_response method on a\npagination class in order to specify how the output format is controlled.\n\n\n\n\nDEFAULT_FILTER_BACKENDS\n\n\nA list of filter backend classes that should be used for generic filtering.\nIf set to \nNone\n then generic filtering is disabled.\n\n\nPAGINATE_BY\n\n\n\n\nThis setting has been removed.\n\n\nSee the pagination documentation for further guidance on \nsetting the pagination style\n.\n\n\n\n\nPAGE_SIZE\n\n\nThe default page size to use for pagination. If set to \nNone\n, pagination is disabled by default.\n\n\nDefault: \nNone\n\n\nPAGINATE_BY_PARAM\n\n\n\n\nThis setting has been removed.\n\n\nSee the pagination documentation for further guidance on \nsetting the pagination style\n.\n\n\n\n\nMAX_PAGINATE_BY\n\n\n\n\nThis setting is pending deprecation.\n\n\nSee the pagination documentation for further guidance on \nsetting the pagination style\n.\n\n\n\n\nSEARCH_PARAM\n\n\nThe name of a query parameter, which can be used to specify the search term used by \nSearchFilter\n.\n\n\nDefault: \nsearch\n\n\nORDERING_PARAM\n\n\nThe name of a query parameter, which can be used to specify the ordering of results returned by \nOrderingFilter\n.\n\n\nDefault: \nordering\n\n\n\n\nVersioning settings\n\n\nDEFAULT_VERSION\n\n\nThe value that should be used for \nrequest.version\n when no versioning information is present.\n\n\nDefault: \nNone\n\n\nALLOWED_VERSIONS\n\n\nIf set, this value will restrict the set of versions that may be returned by the versioning scheme, and will raise an error if the provided version if not in this set.\n\n\nDefault: \nNone\n\n\nVERSION_PARAM\n\n\nThe string that should used for any versioning parameters, such as in the media type or URL query parameters.\n\n\nDefault: \n'version'\n\n\n\n\nAuthentication settings\n\n\nThe following settings control the behavior of unauthenticated requests.\n\n\nUNAUTHENTICATED_USER\n\n\nThe class that should be used to initialize \nrequest.user\n for unauthenticated requests.\n\n\nDefault: \ndjango.contrib.auth.models.AnonymousUser\n\n\nUNAUTHENTICATED_TOKEN\n\n\nThe class that should be used to initialize \nrequest.auth\n for unauthenticated requests.\n\n\nDefault: \nNone\n\n\n\n\nTest settings\n\n\nThe following settings control the behavior of APIRequestFactory and APIClient\n\n\nTEST_REQUEST_DEFAULT_FORMAT\n\n\nThe default format that should be used when making test requests.\n\n\nThis should match up with the format of one of the renderer classes in the \nTEST_REQUEST_RENDERER_CLASSES\n setting.\n\n\nDefault: \n'multipart'\n\n\nTEST_REQUEST_RENDERER_CLASSES\n\n\nThe renderer classes that are supported when building test requests.\n\n\nThe format of any of these renderer classes may be used when constructing a test request, for example: \nclient.post('/users', {'username': 'jamie'}, format='json')\n\n\nDefault:\n\n\n(\n 'rest_framework.renderers.MultiPartRenderer',\n 'rest_framework.renderers.JSONRenderer'\n)\n\n\n\n\n\nSchema generation controls\n\n\nSCHEMA_COERCE_PATH_PK\n\n\nIf set, this maps the \n'pk'\n identifier in the URL conf onto the actual field\nname when generating a schema path parameter. Typically this will be \n'id'\n.\nThis gives a more suitable representation as \"primary key\" is an implementation\ndetail, wheras \"identifier\" is a more general concept.\n\n\nDefault: \nTrue\n\n\nSCHEMA_COERCE_METHOD_NAMES\n\n\nIf set, this is used to map internal viewset method names onto external action\nnames used in the schema generation. This allows us to generate names that\nare more suitable for an external representation than those that are used\ninternally in the codebase.\n\n\nDefault: \n{'retrieve': 'read', 'destroy': 'delete'}\n\n\n\n\nContent type controls\n\n\nURL_FORMAT_OVERRIDE\n\n\nThe name of a URL parameter that may be used to override the default content negotiation \nAccept\n header behavior, by using a \nformat=\u2026\n query parameter in the request URL.\n\n\nFor example: \nhttp://example.com/organizations/?format=csv\n\n\nIf the value of this setting is \nNone\n then URL format overrides will be disabled.\n\n\nDefault: \n'format'\n\n\nFORMAT_SUFFIX_KWARG\n\n\nThe name of a parameter in the URL conf that may be used to provide a format suffix. This setting is applied when using \nformat_suffix_patterns\n to include suffixed URL patterns.\n\n\nFor example: \nhttp://example.com/organizations.csv/\n\n\nDefault: \n'format'\n\n\n\n\nDate and time formatting\n\n\nThe following settings are used to control how date and time representations may be parsed and rendered.\n\n\nDATETIME_FORMAT\n\n\nA format string that should be used by default for rendering the output of \nDateTimeField\n serializer fields. If \nNone\n, then \nDateTimeField\n serializer fields will return Python \ndatetime\n objects, and the datetime encoding will be determined by the renderer.\n\n\nMay be any of \nNone\n, \n'iso-8601'\n or a Python \nstrftime format\n string.\n\n\nDefault: \n'iso-8601'\n\n\nDATETIME_INPUT_FORMATS\n\n\nA list of format strings that should be used by default for parsing inputs to \nDateTimeField\n serializer fields.\n\n\nMay be a list including the string \n'iso-8601'\n or Python \nstrftime format\n strings.\n\n\nDefault: \n['iso-8601']\n\n\nDATE_FORMAT\n\n\nA format string that should be used by default for rendering the output of \nDateField\n serializer fields. If \nNone\n, then \nDateField\n serializer fields will return Python \ndate\n objects, and the date encoding will be determined by the renderer.\n\n\nMay be any of \nNone\n, \n'iso-8601'\n or a Python \nstrftime format\n string.\n\n\nDefault: \n'iso-8601'\n\n\nDATE_INPUT_FORMATS\n\n\nA list of format strings that should be used by default for parsing inputs to \nDateField\n serializer fields.\n\n\nMay be a list including the string \n'iso-8601'\n or Python \nstrftime format\n strings.\n\n\nDefault: \n['iso-8601']\n\n\nTIME_FORMAT\n\n\nA format string that should be used by default for rendering the output of \nTimeField\n serializer fields. If \nNone\n, then \nTimeField\n serializer fields will return Python \ntime\n objects, and the time encoding will be determined by the renderer.\n\n\nMay be any of \nNone\n, \n'iso-8601'\n or a Python \nstrftime format\n string.\n\n\nDefault: \n'iso-8601'\n\n\nTIME_INPUT_FORMATS\n\n\nA list of format strings that should be used by default for parsing inputs to \nTimeField\n serializer fields.\n\n\nMay be a list including the string \n'iso-8601'\n or Python \nstrftime format\n strings.\n\n\nDefault: \n['iso-8601']\n\n\n\n\nEncodings\n\n\nUNICODE_JSON\n\n\nWhen set to \nTrue\n, JSON responses will allow unicode characters in responses. For example:\n\n\n{\"unicode black star\":\"\u2605\"}\n\n\n\nWhen set to \nFalse\n, JSON responses will escape non-ascii characters, like so:\n\n\n{\"unicode black star\":\"\\u2605\"}\n\n\n\nBoth styles conform to \nRFC 4627\n, and are syntactically valid JSON. The unicode style is preferred as being more user-friendly when inspecting API responses.\n\n\nDefault: \nTrue\n\n\nCOMPACT_JSON\n\n\nWhen set to \nTrue\n, JSON responses will return compact representations, with no spacing after \n':'\n and \n','\n characters. For example:\n\n\n{\"is_admin\":false,\"email\":\"jane@example\"}\n\n\n\nWhen set to \nFalse\n, JSON responses will return slightly more verbose representations, like so:\n\n\n{\"is_admin\": false, \"email\": \"jane@example\"}\n\n\n\nThe default style is to return minified responses, in line with \nHeroku's API design guidelines\n.\n\n\nDefault: \nTrue\n\n\nCOERCE_DECIMAL_TO_STRING\n\n\nWhen returning decimal objects in API representations that do not support a native decimal type, it is normally best to return the value as a string. This avoids the loss of precision that occurs with binary floating point implementations.\n\n\nWhen set to \nTrue\n, the serializer \nDecimalField\n class will return strings instead of \nDecimal\n objects. When set to \nFalse\n, serializers will return \nDecimal\n objects, which the default JSON encoder will return as floats.\n\n\nDefault: \nTrue\n\n\n\n\nView names and descriptions\n\n\nThe following settings are used to generate the view names and descriptions, as used in responses to \nOPTIONS\n requests, and as used in the browsable API.\n\n\nVIEW_NAME_FUNCTION\n\n\nA string representing the function that should be used when generating view names.\n\n\nThis should be a function with the following signature:\n\n\nview_name(cls, suffix=None)\n\n\n\n\n\ncls\n: The view class. Typically the name function would inspect the name of the class when generating a descriptive name, by accessing \ncls.__name__\n.\n\n\nsuffix\n: The optional suffix used when differentiating individual views in a viewset.\n\n\n\n\nDefault: \n'rest_framework.views.get_view_name'\n\n\nVIEW_DESCRIPTION_FUNCTION\n\n\nA string representing the function that should be used when generating view descriptions.\n\n\nThis setting can be changed to support markup styles other than the default markdown. For example, you can use it to support \nrst\n markup in your view docstrings being output in the browsable API.\n\n\nThis should be a function with the following signature:\n\n\nview_description(cls, html=False)\n\n\n\n\n\ncls\n: The view class. Typically the description function would inspect the docstring of the class when generating a description, by accessing \ncls.__doc__\n\n\nhtml\n: A boolean indicating if HTML output is required. \nTrue\n when used in the browsable API, and \nFalse\n when used in generating \nOPTIONS\n responses.\n\n\n\n\nDefault: \n'rest_framework.views.get_view_description'\n\n\nHTML Select Field cutoffs\n\n\nGlobal settings for \nselect field cutoffs for rendering relational fields\n in the browsable API.\n\n\nHTML_SELECT_CUTOFF\n\n\nGlobal setting for the \nhtml_cutoff\n value. Must be an integer.\n\n\nDefault: 1000\n\n\nHTML_SELECT_CUTOFF_TEXT\n\n\nA string representing a global setting for \nhtml_cutoff_text\n.\n\n\nDefault: \n\"More than {count} items...\"\n\n\n\n\nMiscellaneous settings\n\n\nEXCEPTION_HANDLER\n\n\nA string representing the function that should be used when returning a response for any given exception. If the function returns \nNone\n, a 500 error will be raised.\n\n\nThis setting can be changed to support error responses other than the default \n{\"detail\": \"Failure...\"}\n responses. For example, you can use it to provide API responses like \n{\"errors\": [{\"message\": \"Failure...\", \"code\": \"\"} ...]}\n.\n\n\nThis should be a function with the following signature:\n\n\nexception_handler(exc, context)\n\n\n\n\n\nexc\n: The exception.\n\n\n\n\nDefault: \n'rest_framework.views.exception_handler'\n\n\nNON_FIELD_ERRORS_KEY\n\n\nA string representing the key that should be used for serializer errors that do not refer to a specific field, but are instead general errors.\n\n\nDefault: \n'non_field_errors'\n\n\nURL_FIELD_NAME\n\n\nA string representing the key that should be used for the URL fields generated by \nHyperlinkedModelSerializer\n.\n\n\nDefault: \n'url'\n\n\nNUM_PROXIES\n\n\nAn integer of 0 or more, that may be used to specify the number of application proxies that the API runs behind. This allows throttling to more accurately identify client IP addresses. If set to \nNone\n then less strict IP matching will be used by the throttle classes.\n\n\nDefault: \nNone",
+ "text": "Settings\n\n\n\n\nNamespaces are one honking great idea - let's do more of those!\n\n\n \nThe Zen of Python\n\n\n\n\nConfiguration for REST framework is all namespaced inside a single Django setting, named \nREST_FRAMEWORK\n.\n\n\nFor example your project's \nsettings.py\n file might include something like this:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': (\n 'rest_framework.renderers.JSONRenderer',\n ),\n 'DEFAULT_PARSER_CLASSES': (\n 'rest_framework.parsers.JSONParser',\n )\n}\n\n\n\nAccessing settings\n\n\nIf you need to access the values of REST framework's API settings in your project,\nyou should use the \napi_settings\n object. For example.\n\n\nfrom rest_framework.settings import api_settings\n\nprint api_settings.DEFAULT_AUTHENTICATION_CLASSES\n\n\n\nThe \napi_settings\n object will check for any user-defined settings, and otherwise fall back to the default values. Any setting that uses string import paths to refer to a class will automatically import and return the referenced class, instead of the string literal.\n\n\n\n\nAPI Reference\n\n\nAPI policy settings\n\n\nThe following settings control the basic API policies, and are applied to every \nAPIView\n class-based view, or \n@api_view\n function based view.\n\n\nDEFAULT_RENDERER_CLASSES\n\n\nA list or tuple of renderer classes, that determines the default set of renderers that may be used when returning a \nResponse\n object.\n\n\nDefault:\n\n\n(\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n)\n\n\n\nDEFAULT_PARSER_CLASSES\n\n\nA list or tuple of parser classes, that determines the default set of parsers used when accessing the \nrequest.data\n property.\n\n\nDefault:\n\n\n(\n 'rest_framework.parsers.JSONParser',\n 'rest_framework.parsers.FormParser',\n 'rest_framework.parsers.MultiPartParser'\n)\n\n\n\nDEFAULT_AUTHENTICATION_CLASSES\n\n\nA list or tuple of authentication classes, that determines the default set of authenticators used when accessing the \nrequest.user\n or \nrequest.auth\n properties.\n\n\nDefault:\n\n\n(\n 'rest_framework.authentication.SessionAuthentication',\n 'rest_framework.authentication.BasicAuthentication'\n)\n\n\n\nDEFAULT_PERMISSION_CLASSES\n\n\nA list or tuple of permission classes, that determines the default set of permissions checked at the start of a view. Permission must be granted by every class in the list.\n\n\nDefault:\n\n\n(\n 'rest_framework.permissions.AllowAny',\n)\n\n\n\nDEFAULT_THROTTLE_CLASSES\n\n\nA list or tuple of throttle classes, that determines the default set of throttles checked at the start of a view.\n\n\nDefault: \n()\n\n\nDEFAULT_CONTENT_NEGOTIATION_CLASS\n\n\nA content negotiation class, that determines how a renderer is selected for the response, given an incoming request.\n\n\nDefault: \n'rest_framework.negotiation.DefaultContentNegotiation'\n\n\n\n\nGeneric view settings\n\n\nThe following settings control the behavior of the generic class-based views.\n\n\nDEFAULT_PAGINATION_SERIALIZER_CLASS\n\n\n\n\nThis setting has been removed.\n\n\nThe pagination API does not use serializers to determine the output format, and\nyou'll need to instead override the `get_paginated_response method on a\npagination class in order to specify how the output format is controlled.\n\n\n\n\nDEFAULT_FILTER_BACKENDS\n\n\nA list of filter backend classes that should be used for generic filtering.\nIf set to \nNone\n then generic filtering is disabled.\n\n\nPAGINATE_BY\n\n\n\n\nThis setting has been removed.\n\n\nSee the pagination documentation for further guidance on \nsetting the pagination style\n.\n\n\n\n\nPAGE_SIZE\n\n\nThe default page size to use for pagination. If set to \nNone\n, pagination is disabled by default.\n\n\nDefault: \nNone\n\n\nPAGINATE_BY_PARAM\n\n\n\n\nThis setting has been removed.\n\n\nSee the pagination documentation for further guidance on \nsetting the pagination style\n.\n\n\n\n\nMAX_PAGINATE_BY\n\n\n\n\nThis setting is pending deprecation.\n\n\nSee the pagination documentation for further guidance on \nsetting the pagination style\n.\n\n\n\n\nSEARCH_PARAM\n\n\nThe name of a query parameter, which can be used to specify the search term used by \nSearchFilter\n.\n\n\nDefault: \nsearch\n\n\nORDERING_PARAM\n\n\nThe name of a query parameter, which can be used to specify the ordering of results returned by \nOrderingFilter\n.\n\n\nDefault: \nordering\n\n\n\n\nVersioning settings\n\n\nDEFAULT_VERSION\n\n\nThe value that should be used for \nrequest.version\n when no versioning information is present.\n\n\nDefault: \nNone\n\n\nALLOWED_VERSIONS\n\n\nIf set, this value will restrict the set of versions that may be returned by the versioning scheme, and will raise an error if the provided version if not in this set.\n\n\nDefault: \nNone\n\n\nVERSION_PARAM\n\n\nThe string that should used for any versioning parameters, such as in the media type or URL query parameters.\n\n\nDefault: \n'version'\n\n\n\n\nAuthentication settings\n\n\nThe following settings control the behavior of unauthenticated requests.\n\n\nUNAUTHENTICATED_USER\n\n\nThe class that should be used to initialize \nrequest.user\n for unauthenticated requests.\n\n\nDefault: \ndjango.contrib.auth.models.AnonymousUser\n\n\nUNAUTHENTICATED_TOKEN\n\n\nThe class that should be used to initialize \nrequest.auth\n for unauthenticated requests.\n\n\nDefault: \nNone\n\n\n\n\nTest settings\n\n\nThe following settings control the behavior of APIRequestFactory and APIClient\n\n\nTEST_REQUEST_DEFAULT_FORMAT\n\n\nThe default format that should be used when making test requests.\n\n\nThis should match up with the format of one of the renderer classes in the \nTEST_REQUEST_RENDERER_CLASSES\n setting.\n\n\nDefault: \n'multipart'\n\n\nTEST_REQUEST_RENDERER_CLASSES\n\n\nThe renderer classes that are supported when building test requests.\n\n\nThe format of any of these renderer classes may be used when constructing a test request, for example: \nclient.post('/users', {'username': 'jamie'}, format='json')\n\n\nDefault:\n\n\n(\n 'rest_framework.renderers.MultiPartRenderer',\n 'rest_framework.renderers.JSONRenderer'\n)\n\n\n\n\n\nSchema generation controls\n\n\nSCHEMA_COERCE_PATH_PK\n\n\nIf set, this maps the \n'pk'\n identifier in the URL conf onto the actual field\nname when generating a schema path parameter. Typically this will be \n'id'\n.\nThis gives a more suitable representation as \"primary key\" is an implementation\ndetail, whereas \"identifier\" is a more general concept.\n\n\nDefault: \nTrue\n\n\nSCHEMA_COERCE_METHOD_NAMES\n\n\nIf set, this is used to map internal viewset method names onto external action\nnames used in the schema generation. This allows us to generate names that\nare more suitable for an external representation than those that are used\ninternally in the codebase.\n\n\nDefault: \n{'retrieve': 'read', 'destroy': 'delete'}\n\n\n\n\nContent type controls\n\n\nURL_FORMAT_OVERRIDE\n\n\nThe name of a URL parameter that may be used to override the default content negotiation \nAccept\n header behavior, by using a \nformat=\u2026\n query parameter in the request URL.\n\n\nFor example: \nhttp://example.com/organizations/?format=csv\n\n\nIf the value of this setting is \nNone\n then URL format overrides will be disabled.\n\n\nDefault: \n'format'\n\n\nFORMAT_SUFFIX_KWARG\n\n\nThe name of a parameter in the URL conf that may be used to provide a format suffix. This setting is applied when using \nformat_suffix_patterns\n to include suffixed URL patterns.\n\n\nFor example: \nhttp://example.com/organizations.csv/\n\n\nDefault: \n'format'\n\n\n\n\nDate and time formatting\n\n\nThe following settings are used to control how date and time representations may be parsed and rendered.\n\n\nDATETIME_FORMAT\n\n\nA format string that should be used by default for rendering the output of \nDateTimeField\n serializer fields. If \nNone\n, then \nDateTimeField\n serializer fields will return Python \ndatetime\n objects, and the datetime encoding will be determined by the renderer.\n\n\nMay be any of \nNone\n, \n'iso-8601'\n or a Python \nstrftime format\n string.\n\n\nDefault: \n'iso-8601'\n\n\nDATETIME_INPUT_FORMATS\n\n\nA list of format strings that should be used by default for parsing inputs to \nDateTimeField\n serializer fields.\n\n\nMay be a list including the string \n'iso-8601'\n or Python \nstrftime format\n strings.\n\n\nDefault: \n['iso-8601']\n\n\nDATE_FORMAT\n\n\nA format string that should be used by default for rendering the output of \nDateField\n serializer fields. If \nNone\n, then \nDateField\n serializer fields will return Python \ndate\n objects, and the date encoding will be determined by the renderer.\n\n\nMay be any of \nNone\n, \n'iso-8601'\n or a Python \nstrftime format\n string.\n\n\nDefault: \n'iso-8601'\n\n\nDATE_INPUT_FORMATS\n\n\nA list of format strings that should be used by default for parsing inputs to \nDateField\n serializer fields.\n\n\nMay be a list including the string \n'iso-8601'\n or Python \nstrftime format\n strings.\n\n\nDefault: \n['iso-8601']\n\n\nTIME_FORMAT\n\n\nA format string that should be used by default for rendering the output of \nTimeField\n serializer fields. If \nNone\n, then \nTimeField\n serializer fields will return Python \ntime\n objects, and the time encoding will be determined by the renderer.\n\n\nMay be any of \nNone\n, \n'iso-8601'\n or a Python \nstrftime format\n string.\n\n\nDefault: \n'iso-8601'\n\n\nTIME_INPUT_FORMATS\n\n\nA list of format strings that should be used by default for parsing inputs to \nTimeField\n serializer fields.\n\n\nMay be a list including the string \n'iso-8601'\n or Python \nstrftime format\n strings.\n\n\nDefault: \n['iso-8601']\n\n\n\n\nEncodings\n\n\nUNICODE_JSON\n\n\nWhen set to \nTrue\n, JSON responses will allow unicode characters in responses. For example:\n\n\n{\"unicode black star\":\"\u2605\"}\n\n\n\nWhen set to \nFalse\n, JSON responses will escape non-ascii characters, like so:\n\n\n{\"unicode black star\":\"\\u2605\"}\n\n\n\nBoth styles conform to \nRFC 4627\n, and are syntactically valid JSON. The unicode style is preferred as being more user-friendly when inspecting API responses.\n\n\nDefault: \nTrue\n\n\nCOMPACT_JSON\n\n\nWhen set to \nTrue\n, JSON responses will return compact representations, with no spacing after \n':'\n and \n','\n characters. For example:\n\n\n{\"is_admin\":false,\"email\":\"jane@example\"}\n\n\n\nWhen set to \nFalse\n, JSON responses will return slightly more verbose representations, like so:\n\n\n{\"is_admin\": false, \"email\": \"jane@example\"}\n\n\n\nThe default style is to return minified responses, in line with \nHeroku's API design guidelines\n.\n\n\nDefault: \nTrue\n\n\nCOERCE_DECIMAL_TO_STRING\n\n\nWhen returning decimal objects in API representations that do not support a native decimal type, it is normally best to return the value as a string. This avoids the loss of precision that occurs with binary floating point implementations.\n\n\nWhen set to \nTrue\n, the serializer \nDecimalField\n class will return strings instead of \nDecimal\n objects. When set to \nFalse\n, serializers will return \nDecimal\n objects, which the default JSON encoder will return as floats.\n\n\nDefault: \nTrue\n\n\n\n\nView names and descriptions\n\n\nThe following settings are used to generate the view names and descriptions, as used in responses to \nOPTIONS\n requests, and as used in the browsable API.\n\n\nVIEW_NAME_FUNCTION\n\n\nA string representing the function that should be used when generating view names.\n\n\nThis should be a function with the following signature:\n\n\nview_name(cls, suffix=None)\n\n\n\n\n\ncls\n: The view class. Typically the name function would inspect the name of the class when generating a descriptive name, by accessing \ncls.__name__\n.\n\n\nsuffix\n: The optional suffix used when differentiating individual views in a viewset.\n\n\n\n\nDefault: \n'rest_framework.views.get_view_name'\n\n\nVIEW_DESCRIPTION_FUNCTION\n\n\nA string representing the function that should be used when generating view descriptions.\n\n\nThis setting can be changed to support markup styles other than the default markdown. For example, you can use it to support \nrst\n markup in your view docstrings being output in the browsable API.\n\n\nThis should be a function with the following signature:\n\n\nview_description(cls, html=False)\n\n\n\n\n\ncls\n: The view class. Typically the description function would inspect the docstring of the class when generating a description, by accessing \ncls.__doc__\n\n\nhtml\n: A boolean indicating if HTML output is required. \nTrue\n when used in the browsable API, and \nFalse\n when used in generating \nOPTIONS\n responses.\n\n\n\n\nDefault: \n'rest_framework.views.get_view_description'\n\n\nHTML Select Field cutoffs\n\n\nGlobal settings for \nselect field cutoffs for rendering relational fields\n in the browsable API.\n\n\nHTML_SELECT_CUTOFF\n\n\nGlobal setting for the \nhtml_cutoff\n value. Must be an integer.\n\n\nDefault: 1000\n\n\nHTML_SELECT_CUTOFF_TEXT\n\n\nA string representing a global setting for \nhtml_cutoff_text\n.\n\n\nDefault: \n\"More than {count} items...\"\n\n\n\n\nMiscellaneous settings\n\n\nEXCEPTION_HANDLER\n\n\nA string representing the function that should be used when returning a response for any given exception. If the function returns \nNone\n, a 500 error will be raised.\n\n\nThis setting can be changed to support error responses other than the default \n{\"detail\": \"Failure...\"}\n responses. For example, you can use it to provide API responses like \n{\"errors\": [{\"message\": \"Failure...\", \"code\": \"\"} ...]}\n.\n\n\nThis should be a function with the following signature:\n\n\nexception_handler(exc, context)\n\n\n\n\n\nexc\n: The exception.\n\n\n\n\nDefault: \n'rest_framework.views.exception_handler'\n\n\nNON_FIELD_ERRORS_KEY\n\n\nA string representing the key that should be used for serializer errors that do not refer to a specific field, but are instead general errors.\n\n\nDefault: \n'non_field_errors'\n\n\nURL_FIELD_NAME\n\n\nA string representing the key that should be used for the URL fields generated by \nHyperlinkedModelSerializer\n.\n\n\nDefault: \n'url'\n\n\nNUM_PROXIES\n\n\nAn integer of 0 or more, that may be used to specify the number of application proxies that the API runs behind. This allows throttling to more accurately identify client IP addresses. If set to \nNone\n then less strict IP matching will be used by the throttle classes.\n\n\nDefault: \nNone",
"title": "Settings"
},
{
@@ -3757,7 +3767,7 @@
},
{
"location": "/api-guide/settings/#schema_coerce_path_pk",
- "text": "If set, this maps the 'pk' identifier in the URL conf onto the actual field\nname when generating a schema path parameter. Typically this will be 'id' .\nThis gives a more suitable representation as \"primary key\" is an implementation\ndetail, wheras \"identifier\" is a more general concept. Default: True",
+ "text": "If set, this maps the 'pk' identifier in the URL conf onto the actual field\nname when generating a schema path parameter. Typically this will be 'id' .\nThis gives a more suitable representation as \"primary key\" is an implementation\ndetail, whereas \"identifier\" is a more general concept. Default: True",
"title": "SCHEMA_COERCE_PATH_PK"
},
{
@@ -3892,7 +3902,7 @@
},
{
"location": "/topics/documenting-your-api/",
- "text": "Documenting your API\n\n\n\n\nA REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state.\n\n\n Roy Fielding, \nREST APIs must be hypertext driven\n\n\n\n\nThere are a variety of approaches to API documentation. This document introduces a few of the various tools and options you might choose from. The approaches should not be considered exclusive - you may want to provide more than one documentation style for you API, such as a self describing API that also includes static documentation of the various API endpoints.\n\n\nEndpoint documentation\n\n\nThe most common way to document Web APIs today is to produce documentation that lists the API endpoints verbatim, and describes the allowable operations on each. There are various tools that allow you to do this in an automated or semi-automated way.\n\n\n\n\nDRF Docs\n\n\nDRF Docs\n allows you to document Web APIs made with Django REST Framework and it is authored by Emmanouil Konstantinidis. It's made to work out of the box and its setup should not take more than a couple of minutes. Complete documentation can be found on the \nwebsite\n while there is also a \ndemo\n available for people to see what it looks like. \nLive API Endpoints\n allow you to utilize the endpoints from within the documentation in a neat way.\n\n\nFeatures include customizing the template with your branding, settings for hiding the docs depending on the environment and more.\n\n\nBoth this package and Django REST Swagger are fully documented, well supported, and come highly recommended.\n\n\n\n\n\n\nDjango REST Swagger\n\n\nMarc Gibbons' \nDjango REST Swagger\n integrates REST framework with the \nSwagger\n API documentation tool. The package produces well presented API documentation, and includes interactive tools for testing API endpoints.\n\n\nDjango REST Swagger supports REST framework versions 2.3 and above.\n\n\nMark is also the author of the \nREST Framework Docs\n package which offers clean, simple autogenerated documentation for your API but is deprecated and has moved to Django REST Swagger.\n\n\nBoth this package and DRF docs are fully documented, well supported, and come highly recommended.\n\n\n\n\n\n\nDRF AutoDocs\n\n\nOleksander Mashianovs' \nDRF Auto Docs\n automated api renderer.\n\n\nCollects almost all the code you written into documentation effortlessly.\n\n\nSupports:\n\n\n\n\nfunctional view docs\n\n\ntree-like structure\n\n\nDocstrings:\n\n\nmarkdown\n\n\npreserve space \n newlines\n\n\nformatting with nice syntax\n\n\nFields:\n\n\nchoices rendering\n\n\nhelp_text (to specify SerializerMethodField output, etc)\n\n\nsmart read_only/required rendering\n\n\nEndpoint properties:\n\n\nfilter_backends\n\n\nauthentication_classes\n\n\npermission_classes\n\n\nextra url params(GET params)\n\n\n\n\n\n\n\n\nApiary\n\n\nThere are various other online tools and services for providing API documentation. One notable service is \nApiary\n. With Apiary, you describe your API using a simple markdown-like syntax. The generated documentation includes API interaction, a mock server for testing \n prototyping, and various other tools.\n\n\n\n\n\n\nSelf describing APIs\n\n\nThe browsable API that REST framework provides makes it possible for your API to be entirely self describing. The documentation for each API endpoint can be provided simply by visiting the URL in your browser.\n\n\n\n\n\n\nSetting the title\n\n\nThe title that is used in the browsable API is generated from the view class name or function name. Any trailing \nView\n or \nViewSet\n suffix is stripped, and the string is whitespace separated on uppercase/lowercase boundaries or underscores.\n\n\nFor example, the view \nUserListView\n, will be named \nUser List\n when presented in the browsable API.\n\n\nWhen working with viewsets, an appropriate suffix is appended to each generated view. For example, the view set \nUserViewSet\n will generate views named \nUser List\n and \nUser Instance\n.\n\n\nSetting the description\n\n\nThe description in the browsable API is generated from the docstring of the view or viewset.\n\n\nIf the python \nmarkdown\n library is installed, then \nmarkdown syntax\n may be used in the docstring, and will be converted to HTML in the browsable API. For example:\n\n\nclass AccountListView(views.APIView):\n \"\"\"\n Returns a list of all **active** accounts in the system.\n\n For more details on how accounts are activated please [see here][ref].\n\n [ref]: http://example.com/activating-accounts\n \"\"\"\n\n\n\nNote that one constraint of using viewsets is that any documentation be used for all generated views, so for example, you cannot have differing documentation for the generated list view and detail view.\n\n\nThe \nOPTIONS\n method\n\n\nREST framework APIs also support programmatically accessible descriptions, using the \nOPTIONS\n HTTP method. A view will respond to an \nOPTIONS\n request with metadata including the name, description, and the various media types it accepts and responds with.\n\n\nWhen using the generic views, any \nOPTIONS\n requests will additionally respond with metadata regarding any \nPOST\n or \nPUT\n actions available, describing which fields are on the serializer.\n\n\nYou can modify the response behavior to \nOPTIONS\n requests by overriding the \nmetadata\n view method. For example:\n\n\ndef metadata(self, request):\n \"\"\"\n Don't include the view description in OPTIONS responses.\n \"\"\"\n data = super(ExampleView, self).metadata(request)\n data.pop('description')\n return data\n\n\n\n\n\nThe hypermedia approach\n\n\nTo be fully RESTful an API should present its available actions as hypermedia controls in the responses that it sends.\n\n\nIn this approach, rather than documenting the available API endpoints up front, the description instead concentrates on the \nmedia types\n that are used. The available actions that may be taken on any given URL are not strictly fixed, but are instead made available by the presence of link and form controls in the returned document.\n\n\nTo implement a hypermedia API you'll need to decide on an appropriate media type for the API, and implement a custom renderer and parser for that media type. The \nREST, Hypermedia \n HATEOAS\n section of the documentation includes pointers to background reading, as well as links to various hypermedia formats.",
+ "text": "Documenting your API\n\n\n\n\nA REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state.\n\n\n Roy Fielding, \nREST APIs must be hypertext driven\n\n\n\n\nThere are a variety of approaches to API documentation. This document introduces a few of the various tools and options you might choose from. The approaches should not be considered exclusive - you may want to provide more than one documentation style for you API, such as a self describing API that also includes static documentation of the various API endpoints.\n\n\nEndpoint documentation\n\n\nThe most common way to document Web APIs today is to produce documentation that lists the API endpoints verbatim, and describes the allowable operations on each. There are various tools that allow you to do this in an automated or semi-automated way.\n\n\n\n\nDRF Docs\n\n\nDRF Docs\n allows you to document Web APIs made with Django REST Framework and it is authored by Emmanouil Konstantinidis. It's made to work out of the box and its setup should not take more than a couple of minutes. Complete documentation can be found on the \nwebsite\n while there is also a \ndemo\n available for people to see what it looks like. \nLive API Endpoints\n allow you to utilize the endpoints from within the documentation in a neat way.\n\n\nFeatures include customizing the template with your branding, settings for hiding the docs depending on the environment and more.\n\n\nBoth this package and Django REST Swagger are fully documented, well supported, and come highly recommended.\n\n\n\n\n\n\nDjango REST Swagger\n\n\nMarc Gibbons' \nDjango REST Swagger\n integrates REST framework with the \nSwagger\n API documentation tool. The package produces well presented API documentation, and includes interactive tools for testing API endpoints.\n\n\nDjango REST Swagger supports REST framework versions 2.3 and above.\n\n\nMark is also the author of the \nREST Framework Docs\n package which offers clean, simple autogenerated documentation for your API but is deprecated and has moved to Django REST Swagger.\n\n\nBoth this package and DRF docs are fully documented, well supported, and come highly recommended.\n\n\n\n\n\n\nDRF AutoDocs\n\n\nOleksander Mashianovs' \nDRF Auto Docs\n automated api renderer.\n\n\nCollects almost all the code you written into documentation effortlessly.\n\n\nSupports:\n\n\n\n\nfunctional view docs\n\n\ntree-like structure\n\n\nDocstrings:\n\n\nmarkdown\n\n\npreserve space \n newlines\n\n\nformatting with nice syntax\n\n\nFields:\n\n\nchoices rendering\n\n\nhelp_text (to specify SerializerMethodField output, etc)\n\n\nsmart read_only/required rendering\n\n\nEndpoint properties:\n\n\nfilter_backends\n\n\nauthentication_classes\n\n\npermission_classes\n\n\nextra url params(GET params)\n\n\n\n\n\n\n\n\nApiary\n\n\nThere are various other online tools and services for providing API documentation. One notable service is \nApiary\n. With Apiary, you describe your API using a simple markdown-like syntax. The generated documentation includes API interaction, a mock server for testing \n prototyping, and various other tools.\n\n\n\n\n\n\nSelf describing APIs\n\n\nThe browsable API that REST framework provides makes it possible for your API to be entirely self describing. The documentation for each API endpoint can be provided simply by visiting the URL in your browser.\n\n\n\n\n\n\nSetting the title\n\n\nThe title that is used in the browsable API is generated from the view class name or function name. Any trailing \nView\n or \nViewSet\n suffix is stripped, and the string is whitespace separated on uppercase/lowercase boundaries or underscores.\n\n\nFor example, the view \nUserListView\n, will be named \nUser List\n when presented in the browsable API.\n\n\nWhen working with viewsets, an appropriate suffix is appended to each generated view. For example, the view set \nUserViewSet\n will generate views named \nUser List\n and \nUser Instance\n.\n\n\nSetting the description\n\n\nThe description in the browsable API is generated from the docstring of the view or viewset.\n\n\nIf the python \nmarkdown\n library is installed, then \nmarkdown syntax\n may be used in the docstring, and will be converted to HTML in the browsable API. For example:\n\n\nclass AccountListView(views.APIView):\n \"\"\"\n Returns a list of all **active** accounts in the system.\n\n For more details on how accounts are activated please [see here][ref].\n\n [ref]: http://example.com/activating-accounts\n \"\"\"\n\n\n\nNote that when using viewsets the basic docstring is used for all generated views. To provide descriptions for each view, such as for the the list and retrieve views, use docstring sections as described in \nSchemas as documentation: Examples\n.\n\n\nThe \nOPTIONS\n method\n\n\nREST framework APIs also support programmatically accessible descriptions, using the \nOPTIONS\n HTTP method. A view will respond to an \nOPTIONS\n request with metadata including the name, description, and the various media types it accepts and responds with.\n\n\nWhen using the generic views, any \nOPTIONS\n requests will additionally respond with metadata regarding any \nPOST\n or \nPUT\n actions available, describing which fields are on the serializer.\n\n\nYou can modify the response behavior to \nOPTIONS\n requests by overriding the \nmetadata\n view method. For example:\n\n\ndef metadata(self, request):\n \"\"\"\n Don't include the view description in OPTIONS responses.\n \"\"\"\n data = super(ExampleView, self).metadata(request)\n data.pop('description')\n return data\n\n\n\n\n\nThe hypermedia approach\n\n\nTo be fully RESTful an API should present its available actions as hypermedia controls in the responses that it sends.\n\n\nIn this approach, rather than documenting the available API endpoints up front, the description instead concentrates on the \nmedia types\n that are used. The available actions that may be taken on any given URL are not strictly fixed, but are instead made available by the presence of link and form controls in the returned document.\n\n\nTo implement a hypermedia API you'll need to decide on an appropriate media type for the API, and implement a custom renderer and parser for that media type. The \nREST, Hypermedia \n HATEOAS\n section of the documentation includes pointers to background reading, as well as links to various hypermedia formats.",
"title": "Documenting your API"
},
{
@@ -3937,7 +3947,7 @@
},
{
"location": "/topics/documenting-your-api/#setting-the-description",
- "text": "The description in the browsable API is generated from the docstring of the view or viewset. If the python markdown library is installed, then markdown syntax may be used in the docstring, and will be converted to HTML in the browsable API. For example: class AccountListView(views.APIView):\n \"\"\"\n Returns a list of all **active** accounts in the system.\n\n For more details on how accounts are activated please [see here][ref].\n\n [ref]: http://example.com/activating-accounts\n \"\"\" Note that one constraint of using viewsets is that any documentation be used for all generated views, so for example, you cannot have differing documentation for the generated list view and detail view.",
+ "text": "The description in the browsable API is generated from the docstring of the view or viewset. If the python markdown library is installed, then markdown syntax may be used in the docstring, and will be converted to HTML in the browsable API. For example: class AccountListView(views.APIView):\n \"\"\"\n Returns a list of all **active** accounts in the system.\n\n For more details on how accounts are activated please [see here][ref].\n\n [ref]: http://example.com/activating-accounts\n \"\"\" Note that when using viewsets the basic docstring is used for all generated views. To provide descriptions for each view, such as for the the list and retrieve views, use docstring sections as described in Schemas as documentation: Examples .",
"title": "Setting the description"
},
{
@@ -3952,7 +3962,7 @@
},
{
"location": "/topics/api-clients/",
- "text": "API Clients\n\n\nAn API client handles the underlying details of how network requests are made\nand how responses are decoded. They present the developer with an application\ninterface to work against, rather than working directly with the network interface.\n\n\nThe API clients documented here are not restricted to APIs built with Django REST framework.\n They can be used with any API that exposes a supported schema format.\n\n\nFor example, \nthe Heroku platform API\n exposes a schema in the JSON\nHyperschema format. As a result, the Core API command line client and Python\nclient library can be \nused to interact with the Heroku API\n.\n\n\nClient-side Core API\n\n\nCore API\n is a document specification that can be used to describe APIs. It can\nbe used either server-side, as is done with REST framework's \nschema generation\n,\nor used client-side, as described here.\n\n\nWhen used client-side, Core API allows for \ndynamically driven client libraries\n\nthat can interact with any API that exposes a supported schema or hypermedia\nformat.\n\n\nUsing a dynamically driven client has a number of advantages over interacting\nwith an API by building HTTP requests directly.\n\n\nMore meaningful interaction\n\n\nAPI interactions are presented in a more meaningful way. You're working at\nthe application interface layer, rather than the network interface layer.\n\n\nResilience \n evolvability\n\n\nThe client determines what endpoints are available, what parameters exist\nagainst each particular endpoint, and how HTTP requests are formed.\n\n\nThis also allows for a degree of API evolvability. URLs can be modified\nwithout breaking existing clients, or more efficient encodings can be used\non-the-wire, with clients transparently upgrading.\n\n\nSelf-descriptive APIs\n\n\nA dynamically driven client is able to present documentation on the API to the\nend user. This documentation allows the user to discover the available endpoints\nand parameters, and better understand the API they are working with.\n\n\nBecause this documentation is driven by the API schema it will always be fully\nup to date with the most recently deployed version of the service.\n\n\n\n\nCommand line client\n\n\nThe command line client allows you to inspect and interact with any API that\nexposes a supported schema format.\n\n\nGetting started\n\n\nTo install the Core API command line client, use \npip\n.\n\n\nNote that the command-line client is a separate package to the\npython client library. Make sure to install \ncoreapi-cli\n.\n\n\n$ pip install coreapi-cli\n\n\n\nTo start inspecting and interacting with an API the schema must first be loaded\nfrom the network.\n\n\n$ coreapi get http://api.example.org/\n\nPastebin API \"http://127.0.0.1:8000/\"\n\nsnippets: {\n create(code, [title], [linenos], [language], [style])\n destroy(pk)\n highlight(pk)\n list([page])\n partial_update(pk, [title], [code], [linenos], [language], [style])\n retrieve(pk)\n update(pk, code, [title], [linenos], [language], [style])\n}\nusers: {\n list([page])\n retrieve(pk)\n}\n\n\n\nThis will then load the schema, displaying the resulting \nDocument\n. This\n\nDocument\n includes all the available interactions that may be made against the API.\n\n\nTo interact with the API, use the \naction\n command. This command requires a list\nof keys that are used to index into the link.\n\n\n$ coreapi action users list\n[\n {\n \"url\": \"http://127.0.0.1:8000/users/2/\",\n \"id\": 2,\n \"username\": \"aziz\",\n \"snippets\": []\n },\n ...\n]\n\n\n\nTo inspect the underlying HTTP request and response, use the \n--debug\n flag.\n\n\n$ coreapi action users list --debug\n\n GET /users/ HTTP/1.1\n\n Accept: application/vnd.coreapi+json, */*\n\n Authorization: Basic bWF4Om1heA==\n\n Host: 127.0.0.1\n\n User-Agent: coreapi\n\n 200 OK\n\n Allow: GET, HEAD, OPTIONS\n\n Content-Type: application/json\n\n Date: Thu, 30 Jun 2016 10:51:46 GMT\n\n Server: WSGIServer/0.1 Python/2.7.10\n\n Vary: Accept, Cookie\n\n\n\n [{\"url\":\"http://127.0.0.1/users/2/\",\"id\":2,\"username\":\"aziz\",\"snippets\":[]},{\"url\":\"http://127.0.0.1/users/3/\",\"id\":3,\"username\":\"amy\",\"snippets\":[\"http://127.0.0.1/snippets/3/\"]},{\"url\":\"http://127.0.0.1/users/4/\",\"id\":4,\"username\":\"max\",\"snippets\":[\"http://127.0.0.1/snippets/4/\",\"http://127.0.0.1/snippets/5/\",\"http://127.0.0.1/snippets/6/\",\"http://127.0.0.1/snippets/7/\"]},{\"url\":\"http://127.0.0.1/users/5/\",\"id\":5,\"username\":\"jose\",\"snippets\":[]},{\"url\":\"http://127.0.0.1/users/6/\",\"id\":6,\"username\":\"admin\",\"snippets\":[\"http://127.0.0.1/snippets/1/\",\"http://127.0.0.1/snippets/2/\"]}]\n\n[\n ...\n]\n\n\n\nSome actions may include optional or required parameters.\n\n\n$ coreapi action users create --param username=example\n\n\n\nWhen using \n--param\n, the type of the input will be determined automatically.\n\n\nIf you want to be more explicit about the parameter type then use \n--data\n for\nany null, numeric, boolean, list, or object inputs, and use \n--string\n for string inputs.\n\n\n$ coreapi action users edit --string username=tomchristie --data is_admin=true\n\n\n\nAuthentication \n headers\n\n\nThe \ncredentials\n command is used to manage the request \nAuthentication:\n header.\nAny credentials added are always linked to a particular domain, so as to ensure\nthat credentials are not leaked across differing APIs.\n\n\nThe format for adding a new credential is:\n\n\n$ coreapi credentials add \ndomain\n \ncredentials string\n\n\n\n\nFor instance:\n\n\n$ coreapi credentials add api.example.org \"Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b\"\n\n\n\nThe optional \n--auth\n flag also allows you to add specific types of authentication,\nhandling the encoding for you. Currently only \n\"basic\"\n is supported as an option here.\nFor example:\n\n\n$ coreapi credentials add api.example.org tomchristie:foobar --auth basic\n\n\n\nYou can also add specific request headers, using the \nheaders\n command:\n\n\n$ coreapi headers add api.example.org x-api-version 2\n\n\n\nFor more information and a listing of the available subcommands use \ncoreapi\ncredentials --help\n or \ncoreapi headers --help\n.\n\n\nCodecs\n\n\nBy default the command line client only includes support for reading Core JSON\nschemas, however it includes a plugin system for installing additional codecs.\n\n\n$ pip install openapi-codec jsonhyperschema-codec hal-codec\n$ coreapi codecs show\nCodecs\ncorejson application/vnd.coreapi+json encoding, decoding\nhal application/hal+json encoding, decoding\nopenapi application/openapi+json encoding, decoding\njsonhyperschema application/schema+json decoding\njson application/json data\ntext text/* data\n\n\n\nUtilities\n\n\nThe command line client includes functionality for bookmarking API URLs\nunder a memorable name. For example, you can add a bookmark for the\nexisting API, like so...\n\n\n$ coreapi bookmarks add accountmanagement\n\n\n\nThere is also functionality for navigating forward or backward through the\nhistory of which API URLs have been accessed.\n\n\n$ coreapi history show\n$ coreapi history back\n\n\n\nFor more information and a listing of the available subcommands use\n\ncoreapi bookmarks --help\n or \ncoreapi history --help\n.\n\n\nOther commands\n\n\nTo display the current \nDocument\n:\n\n\n$ coreapi show\n\n\n\nTo reload the current \nDocument\n from the network:\n\n\n$ coreapi reload\n\n\n\nTo load a schema file from disk:\n\n\n$ coreapi load my-api-schema.json --format corejson\n\n\n\nTo dump the current document to console in a given format:\n\n\n$ coreapi dump --format openapi\n\n\n\nTo remove the current document, along with all currently saved history,\ncredentials, headers and bookmarks:\n\n\n$ coreapi clear\n\n\n\n\n\nPython client library\n\n\nThe \ncoreapi\n Python package allows you to programatically interact with any\nAPI that exposes a supported schema format.\n\n\nGetting started\n\n\nYou'll need to install the \ncoreapi\n package using \npip\n before you can get\nstarted.\n\n\n$ pip install coreapi\n\n\n\nIn order to start working with an API, we first need a \nClient\n instance. The\nclient holds any configuration around which codecs and transports are supported\nwhen interacting with an API, which allows you to provide for more advanced\nkinds of behaviour.\n\n\nimport coreapi\nclient = coreapi.Client()\n\n\n\nOnce we have a \nClient\n instance, we can fetch an API schema from the network.\n\n\nschema = client.get('https://api.example.org/')\n\n\n\nThe object returned from this call will be a \nDocument\n instance, which is\nthe internal representation of the interface that we are interacting with.\n\n\nNow that we have our schema \nDocument\n, we can now start to interact with the API:\n\n\nusers = client.action(schema, ['users', 'list'])\n\n\n\nSome endpoints may include named parameters, which might be either optional or required:\n\n\nnew_user = client.action(schema, ['users', 'create'], params={\"username\": \"max\"})\n\n\n\nCodecs\n\n\nCodecs are responsible for encoding or decoding Documents.\n\n\nThe decoding process is used by a client to take a bytestring of an API schema\ndefinition, and returning the Core API \nDocument\n that represents that interface.\n\n\nA codec should be associated with a particular media type, such as \n'application/coreapi+json'\n.\n\n\nThis media type is used by the server in the response \nContent-Type\n header,\nin order to indicate what kind of data is being returned in the response.\n\n\nConfiguring codecs\n\n\nThe codecs that are available can be configured when instantiating a client.\nThe keyword argument used here is \ndecoders\n, because in the context of a\nclient the codecs are only for \ndecoding\n responses.\n\n\nIn the following example we'll configure a client to only accept \nCore JSON\n\nand \nJSON\n responses. This will allow us to receive and decode a Core JSON schema,\nand subsequently to receive JSON responses made against the API.\n\n\nfrom coreapi import codecs, Client\n\ndecoders = [codecs.CoreJSONCodec(), codecs.JSONCodec()]\nclient = Client(decoders=decoders)\n\n\n\nLoading and saving schemas\n\n\nYou can use a codec directly, in order to load an existing schema definition,\nand return the resulting \nDocument\n.\n\n\ninput_file = open('my-api-schema.json', 'rb')\nschema_definition = input_file.read()\ncodec = codecs.CoreJSONCodec()\nschema = codec.load(schema_definition)\n\n\n\nYou can also use a codec directly to generate a schema definition given a \nDocument\n instance:\n\n\nschema_definition = codec.dump(schema)\noutput_file = open('my-api-schema.json', 'rb')\noutput_file.write(schema_definition)\n\n\n\nTransports\n\n\nTransports are responsible for making network requests. The set of transports\nthat a client has installed determines which network protocols it is able to\nsupport.\n\n\nCurrently the \ncoreapi\n library only includes an HTTP/HTTPS transport, but\nother protocols can also be supported.\n\n\nConfiguring transports\n\n\nThe behaviour of the network layer can be customized by configuring the\ntransports that the client is instantiated with.\n\n\nimport requests\nfrom coreapi import transports, Client\n\ncredentials = {'api.example.org': 'Token 3bd44a009d16ff'}\ntransports = transports.HTTPTransport(credentials=credentials)\nclient = Client(transports=transports)\n\n\n\nMore complex customizations can also be achieved, for example modifying the\nunderlying \nrequests.Session\n instance to \nattach transport adaptors\n\nthat modify the outgoing requests.",
+ "text": "API Clients\n\n\nAn API client handles the underlying details of how network requests are made\nand how responses are decoded. They present the developer with an application\ninterface to work against, rather than working directly with the network interface.\n\n\nThe API clients documented here are not restricted to APIs built with Django REST framework.\n They can be used with any API that exposes a supported schema format.\n\n\nFor example, \nthe Heroku platform API\n exposes a schema in the JSON\nHyperschema format. As a result, the Core API command line client and Python\nclient library can be \nused to interact with the Heroku API\n.\n\n\nClient-side Core API\n\n\nCore API\n is a document specification that can be used to describe APIs. It can\nbe used either server-side, as is done with REST framework's \nschema generation\n,\nor used client-side, as described here.\n\n\nWhen used client-side, Core API allows for \ndynamically driven client libraries\n\nthat can interact with any API that exposes a supported schema or hypermedia\nformat.\n\n\nUsing a dynamically driven client has a number of advantages over interacting\nwith an API by building HTTP requests directly.\n\n\nMore meaningful interaction\n\n\nAPI interactions are presented in a more meaningful way. You're working at\nthe application interface layer, rather than the network interface layer.\n\n\nResilience \n evolvability\n\n\nThe client determines what endpoints are available, what parameters exist\nagainst each particular endpoint, and how HTTP requests are formed.\n\n\nThis also allows for a degree of API evolvability. URLs can be modified\nwithout breaking existing clients, or more efficient encodings can be used\non-the-wire, with clients transparently upgrading.\n\n\nSelf-descriptive APIs\n\n\nA dynamically driven client is able to present documentation on the API to the\nend user. This documentation allows the user to discover the available endpoints\nand parameters, and better understand the API they are working with.\n\n\nBecause this documentation is driven by the API schema it will always be fully\nup to date with the most recently deployed version of the service.\n\n\n\n\nCommand line client\n\n\nThe command line client allows you to inspect and interact with any API that\nexposes a supported schema format.\n\n\nGetting started\n\n\nTo install the Core API command line client, use \npip\n.\n\n\nNote that the command-line client is a separate package to the\npython client library. Make sure to install \ncoreapi-cli\n.\n\n\n$ pip install coreapi-cli\n\n\n\nTo start inspecting and interacting with an API the schema must first be loaded\nfrom the network.\n\n\n$ coreapi get http://api.example.org/\n\nPastebin API \"http://127.0.0.1:8000/\"\n\nsnippets: {\n create(code, [title], [linenos], [language], [style])\n destroy(pk)\n highlight(pk)\n list([page])\n partial_update(pk, [title], [code], [linenos], [language], [style])\n retrieve(pk)\n update(pk, code, [title], [linenos], [language], [style])\n}\nusers: {\n list([page])\n retrieve(pk)\n}\n\n\n\nThis will then load the schema, displaying the resulting \nDocument\n. This\n\nDocument\n includes all the available interactions that may be made against the API.\n\n\nTo interact with the API, use the \naction\n command. This command requires a list\nof keys that are used to index into the link.\n\n\n$ coreapi action users list\n[\n {\n \"url\": \"http://127.0.0.1:8000/users/2/\",\n \"id\": 2,\n \"username\": \"aziz\",\n \"snippets\": []\n },\n ...\n]\n\n\n\nTo inspect the underlying HTTP request and response, use the \n--debug\n flag.\n\n\n$ coreapi action users list --debug\n\n GET /users/ HTTP/1.1\n\n Accept: application/vnd.coreapi+json, */*\n\n Authorization: Basic bWF4Om1heA==\n\n Host: 127.0.0.1\n\n User-Agent: coreapi\n\n 200 OK\n\n Allow: GET, HEAD, OPTIONS\n\n Content-Type: application/json\n\n Date: Thu, 30 Jun 2016 10:51:46 GMT\n\n Server: WSGIServer/0.1 Python/2.7.10\n\n Vary: Accept, Cookie\n\n\n\n [{\"url\":\"http://127.0.0.1/users/2/\",\"id\":2,\"username\":\"aziz\",\"snippets\":[]},{\"url\":\"http://127.0.0.1/users/3/\",\"id\":3,\"username\":\"amy\",\"snippets\":[\"http://127.0.0.1/snippets/3/\"]},{\"url\":\"http://127.0.0.1/users/4/\",\"id\":4,\"username\":\"max\",\"snippets\":[\"http://127.0.0.1/snippets/4/\",\"http://127.0.0.1/snippets/5/\",\"http://127.0.0.1/snippets/6/\",\"http://127.0.0.1/snippets/7/\"]},{\"url\":\"http://127.0.0.1/users/5/\",\"id\":5,\"username\":\"jose\",\"snippets\":[]},{\"url\":\"http://127.0.0.1/users/6/\",\"id\":6,\"username\":\"admin\",\"snippets\":[\"http://127.0.0.1/snippets/1/\",\"http://127.0.0.1/snippets/2/\"]}]\n\n[\n ...\n]\n\n\n\nSome actions may include optional or required parameters.\n\n\n$ coreapi action users create --param username=example\n\n\n\nWhen using \n--param\n, the type of the input will be determined automatically.\n\n\nIf you want to be more explicit about the parameter type then use \n--data\n for\nany null, numeric, boolean, list, or object inputs, and use \n--string\n for string inputs.\n\n\n$ coreapi action users edit --string username=tomchristie --data is_admin=true\n\n\n\nAuthentication \n headers\n\n\nThe \ncredentials\n command is used to manage the request \nAuthentication:\n header.\nAny credentials added are always linked to a particular domain, so as to ensure\nthat credentials are not leaked across differing APIs.\n\n\nThe format for adding a new credential is:\n\n\n$ coreapi credentials add \ndomain\n \ncredentials string\n\n\n\n\nFor instance:\n\n\n$ coreapi credentials add api.example.org \"Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b\"\n\n\n\nThe optional \n--auth\n flag also allows you to add specific types of authentication,\nhandling the encoding for you. Currently only \n\"basic\"\n is supported as an option here.\nFor example:\n\n\n$ coreapi credentials add api.example.org tomchristie:foobar --auth basic\n\n\n\nYou can also add specific request headers, using the \nheaders\n command:\n\n\n$ coreapi headers add api.example.org x-api-version 2\n\n\n\nFor more information and a listing of the available subcommands use \ncoreapi\ncredentials --help\n or \ncoreapi headers --help\n.\n\n\nCodecs\n\n\nBy default the command line client only includes support for reading Core JSON\nschemas, however it includes a plugin system for installing additional codecs.\n\n\n$ pip install openapi-codec jsonhyperschema-codec hal-codec\n$ coreapi codecs show\nCodecs\ncorejson application/vnd.coreapi+json encoding, decoding\nhal application/hal+json encoding, decoding\nopenapi application/openapi+json encoding, decoding\njsonhyperschema application/schema+json decoding\njson application/json data\ntext text/* data\n\n\n\nUtilities\n\n\nThe command line client includes functionality for bookmarking API URLs\nunder a memorable name. For example, you can add a bookmark for the\nexisting API, like so...\n\n\n$ coreapi bookmarks add accountmanagement\n\n\n\nThere is also functionality for navigating forward or backward through the\nhistory of which API URLs have been accessed.\n\n\n$ coreapi history show\n$ coreapi history back\n\n\n\nFor more information and a listing of the available subcommands use\n\ncoreapi bookmarks --help\n or \ncoreapi history --help\n.\n\n\nOther commands\n\n\nTo display the current \nDocument\n:\n\n\n$ coreapi show\n\n\n\nTo reload the current \nDocument\n from the network:\n\n\n$ coreapi reload\n\n\n\nTo load a schema file from disk:\n\n\n$ coreapi load my-api-schema.json --format corejson\n\n\n\nTo dump the current document to console in a given format:\n\n\n$ coreapi dump --format openapi\n\n\n\nTo remove the current document, along with all currently saved history,\ncredentials, headers and bookmarks:\n\n\n$ coreapi clear\n\n\n\n\n\nPython client library\n\n\nThe \ncoreapi\n Python package allows you to programmatically interact with any\nAPI that exposes a supported schema format.\n\n\nGetting started\n\n\nYou'll need to install the \ncoreapi\n package using \npip\n before you can get\nstarted.\n\n\n$ pip install coreapi\n\n\n\nIn order to start working with an API, we first need a \nClient\n instance. The\nclient holds any configuration around which codecs and transports are supported\nwhen interacting with an API, which allows you to provide for more advanced\nkinds of behaviour.\n\n\nimport coreapi\nclient = coreapi.Client()\n\n\n\nOnce we have a \nClient\n instance, we can fetch an API schema from the network.\n\n\nschema = client.get('https://api.example.org/')\n\n\n\nThe object returned from this call will be a \nDocument\n instance, which is\nthe internal representation of the interface that we are interacting with.\n\n\nNow that we have our schema \nDocument\n, we can now start to interact with the API:\n\n\nusers = client.action(schema, ['users', 'list'])\n\n\n\nSome endpoints may include named parameters, which might be either optional or required:\n\n\nnew_user = client.action(schema, ['users', 'create'], params={\"username\": \"max\"})\n\n\n\nCodecs\n\n\nCodecs are responsible for encoding or decoding Documents.\n\n\nThe decoding process is used by a client to take a bytestring of an API schema\ndefinition, and returning the Core API \nDocument\n that represents that interface.\n\n\nA codec should be associated with a particular media type, such as \n'application/coreapi+json'\n.\n\n\nThis media type is used by the server in the response \nContent-Type\n header,\nin order to indicate what kind of data is being returned in the response.\n\n\nConfiguring codecs\n\n\nThe codecs that are available can be configured when instantiating a client.\nThe keyword argument used here is \ndecoders\n, because in the context of a\nclient the codecs are only for \ndecoding\n responses.\n\n\nIn the following example we'll configure a client to only accept \nCore JSON\n\nand \nJSON\n responses. This will allow us to receive and decode a Core JSON schema,\nand subsequently to receive JSON responses made against the API.\n\n\nfrom coreapi import codecs, Client\n\ndecoders = [codecs.CoreJSONCodec(), codecs.JSONCodec()]\nclient = Client(decoders=decoders)\n\n\n\nLoading and saving schemas\n\n\nYou can use a codec directly, in order to load an existing schema definition,\nand return the resulting \nDocument\n.\n\n\ninput_file = open('my-api-schema.json', 'rb')\nschema_definition = input_file.read()\ncodec = codecs.CoreJSONCodec()\nschema = codec.load(schema_definition)\n\n\n\nYou can also use a codec directly to generate a schema definition given a \nDocument\n instance:\n\n\nschema_definition = codec.dump(schema)\noutput_file = open('my-api-schema.json', 'rb')\noutput_file.write(schema_definition)\n\n\n\nTransports\n\n\nTransports are responsible for making network requests. The set of transports\nthat a client has installed determines which network protocols it is able to\nsupport.\n\n\nCurrently the \ncoreapi\n library only includes an HTTP/HTTPS transport, but\nother protocols can also be supported.\n\n\nConfiguring transports\n\n\nThe behaviour of the network layer can be customized by configuring the\ntransports that the client is instantiated with.\n\n\nimport requests\nfrom coreapi import transports, Client\n\ncredentials = {'api.example.org': 'Token 3bd44a009d16ff'}\ntransports = transports.HTTPTransport(credentials=credentials)\nclient = Client(transports=transports)\n\n\n\nMore complex customizations can also be achieved, for example modifying the\nunderlying \nrequests.Session\n instance to \nattach transport adaptors\n\nthat modify the outgoing requests.",
"title": "API Clients"
},
{
@@ -4012,7 +4022,7 @@
},
{
"location": "/topics/api-clients/#python-client-library",
- "text": "The coreapi Python package allows you to programatically interact with any\nAPI that exposes a supported schema format.",
+ "text": "The coreapi Python package allows you to programmatically interact with any\nAPI that exposes a supported schema format.",
"title": "Python client library"
},
{
@@ -4907,7 +4917,7 @@
},
{
"location": "/topics/3.1-announcement/",
- "text": "Django REST framework 3.1\n\n\nThe 3.1 release is an intermediate step in the Kickstarter project releases, and includes a range of new functionality.\n\n\nSome highlights include:\n\n\n\n\nA super-smart cursor pagination scheme.\n\n\nAn improved pagination API, supporting header or in-body pagination styles.\n\n\nPagination controls rendering in the browsable API.\n\n\nBetter support for API versioning.\n\n\nBuilt-in internationalization support.\n\n\nSupport for Django 1.8's \nHStoreField\n and \nArrayField\n.\n\n\n\n\n\n\nPagination\n\n\nThe pagination API has been improved, making it both easier to use, and more powerful.\n\n\nA guide to the headline features follows. For full details, see \nthe pagination documentation\n.\n\n\nNote that as a result of this work a number of settings keys and generic view attributes are now moved to pending deprecation. Controlling pagination styles is now largely handled by overriding a pagination class and modifying its configuration attributes.\n\n\n\n\nThe \nPAGINATE_BY\n settings key will continue to work but is now pending deprecation. The more obviously named \nPAGE_SIZE\n settings key should now be used instead.\n\n\nThe \nPAGINATE_BY_PARAM\n, \nMAX_PAGINATE_BY\n settings keys will continue to work but are now pending deprecation, in favor of setting configuration attributes on the configured pagination class.\n\n\nThe \npaginate_by\n, \npage_query_param\n, \npaginate_by_param\n and \nmax_paginate_by\n generic view attributes will continue to work but are now pending deprecation, in favor of setting configuration attributes on the configured pagination class.\n\n\nThe \npagination_serializer_class\n view attribute and \nDEFAULT_PAGINATION_SERIALIZER_CLASS\n settings key \nare no longer valid\n. The pagination API does not use serializers to determine the output format, and you'll need to instead override the \nget_paginated_response\n method on a pagination class in order to specify how the output format is controlled.\n\n\n\n\nNew pagination schemes.\n\n\nUntil now, there has only been a single built-in pagination style in REST framework. We now have page, limit/offset and cursor based schemes included by default.\n\n\nThe cursor based pagination scheme is particularly smart, and is a better approach for clients iterating through large or frequently changing result sets. The scheme supports paging against non-unique indexes, by using both cursor and limit/offset information. It also allows for both forward and reverse cursor pagination. Much credit goes to David Cramer for \nthis blog post\n on the subject.\n\n\nPagination controls in the browsable API.\n\n\nPaginated results now include controls that render directly in the browsable API. If you're using the page or limit/offset style, then you'll see a page based control displayed in the browsable API:\n\n\n\n\nThe cursor based pagination renders a more simple style of control:\n\n\n\n\nSupport for header-based pagination.\n\n\nThe pagination API was previously only able to alter the pagination style in the body of the response. The API now supports being able to write pagination information in response headers, making it possible to use pagination schemes that use the \nLink\n or \nContent-Range\n headers.\n\n\nFor more information, see the \ncustom pagination styles\n documentation.\n\n\n\n\nVersioning\n\n\nWe've made it \neasier to build versioned APIs\n. Built-in schemes for versioning include both URL based and Accept header based variations.\n\n\nWhen using a URL based scheme, hyperlinked serializers will resolve relationships to the same API version as used on the incoming request.\n\n\nFor example, when using \nNamespaceVersioning\n, and the following hyperlinked serializer:\n\n\nclass AccountsSerializer(serializer.HyperlinkedModelSerializer):\n class Meta:\n model = Accounts\n fields = ('account_name', 'users')\n\n\n\nThe output representation would match the version used on the incoming request. Like so:\n\n\nGET http://example.org/v2/accounts/10 # Version 'v2'\n\n{\n \"account_name\": \"europa\",\n \"users\": [\n \"http://example.org/v2/users/12\", # Version 'v2'\n \"http://example.org/v2/users/54\",\n \"http://example.org/v2/users/87\"\n ]\n}\n\n\n\n\n\nInternationalization\n\n\nREST framework now includes a built-in set of translations, and \nsupports internationalized error responses\n. This allows you to either change the default language, or to allow clients to specify the language via the \nAccept-Language\n header.\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{\n \"detail\": \"No se ha podido satisfacer la solicitud de cabecera de Accept.\"\n}\n\n\n\nNote that the structure of the error responses is still the same. We still have a \ndetail\n key in the response. If needed you can modify this behavior too, by using a \ncustom exception handler\n.\n\n\nWe include built-in translations both for standard exception cases, and for serializer validation errors.\n\n\nThe full list of supported languages can be found on our \nTransifex project page\n.\n\n\nIf you only wish to support a subset of the supported languages, use Django's standard \nLANGUAGES\n setting:\n\n\nLANGUAGES = [\n ('de', _('German')),\n ('en', _('English')),\n]\n\n\n\nFor more details, see the \ninternationalization documentation\n.\n\n\nMany thanks to \nCraig Blaszczyk\n for helping push this through.\n\n\n\n\nNew field types\n\n\nDjango 1.8's new \nArrayField\n, \nHStoreField\n and \nUUIDField\n are now all fully supported.\n\n\nThis work also means that we now have both \nserializers.DictField()\n, and \nserializers.ListField()\n types, allowing you to express and validate a wider set of representations.\n\n\nIf you're building a new 1.8 project, then you should probably consider using \nUUIDField\n as the primary keys for all your models. This style will work automatically with hyperlinked serializers, returning URLs in the following style:\n\n\nhttp://example.org/api/purchases/9b1a433f-e90d-4948-848b-300fdc26365d\n\n\n\n\n\nModelSerializer API\n\n\nThe serializer redesign in 3.0 did not include any public API for modifying how ModelSerializer classes automatically generate a set of fields from a given mode class. We've now re-introduced an API for this, allowing you to create new ModelSerializer base classes that behave differently, such as using a different default style for relationships.\n\n\nFor more information, see the documentation on \ncustomizing field mappings\n for ModelSerializer classes.\n\n\n\n\nMoving packages out of core\n\n\nWe've now moved a number of packages out of the core of REST framework, and into separately installable packages. If you're currently using these you don't need to worry, you simply need to \npip install\n the new packages, and change any import paths.\n\n\nWe're making this change in order to help distribute the maintainance workload, and keep better focus of the core essentials of the framework.\n\n\nThe change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained \nDjango OAuth toolkit\n has now been promoted as our recommended option for integrating OAuth support.\n\n\nThe following packages are now moved out of core and should be separately installed:\n\n\n\n\nOAuth - \ndjangorestframework-oauth\n\n\nXML - \ndjangorestframework-xml\n\n\nYAML - \ndjangorestframework-yaml\n\n\nJSONP - \ndjangorestframework-jsonp\n\n\n\n\nIt's worth reiterating that this change in policy shouldn't mean any work in your codebase other than adding a new requirement and modifying some import paths. For example to install XML rendering, you would now do:\n\n\npip install djangorestframework-xml\n\n\n\nAnd modify your settings, like so:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': [\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n 'rest_framework_xml.renderers.XMLRenderer'\n ]\n}\n\n\n\nThanks go to the latest member of our maintenance team, \nJos\u00e9 Padilla\n, for handling this work and taking on ownership of these packages.\n\n\n\n\nDeprecations\n\n\nThe \nrequest.DATA\n, \nrequest.FILES\n and \nrequest.QUERY_PARAMS\n attributes move from pending deprecation, to deprecated. Use \nrequest.data\n and \nrequest.query_params\n instead, as discussed in the 3.0 release notes.\n\n\nThe ModelSerializer Meta options for \nwrite_only_fields\n, \nview_name\n and \nlookup_field\n are also moved from pending deprecation, to deprecated. Use \nextra_kwargs\n instead, as discussed in the 3.0 release notes.\n\n\nAll these attributes and options will still work in 3.1, but their usage will raise a warning. They will be fully removed in 3.2.\n\n\n\n\nWhat's next?\n\n\nThe next focus will be on HTML renderings of API output and will include:\n\n\n\n\nHTML form rendering of serializers.\n\n\nFiltering controls built-in to the browsable API.\n\n\nAn alternative admin-style interface.\n\n\n\n\nThis will either be made as a single 3.2 release, or split across two separate releases, with the HTML forms and filter controls coming in 3.2, and the admin-style interface coming in a 3.3 release.",
+ "text": "Django REST framework 3.1\n\n\nThe 3.1 release is an intermediate step in the Kickstarter project releases, and includes a range of new functionality.\n\n\nSome highlights include:\n\n\n\n\nA super-smart cursor pagination scheme.\n\n\nAn improved pagination API, supporting header or in-body pagination styles.\n\n\nPagination controls rendering in the browsable API.\n\n\nBetter support for API versioning.\n\n\nBuilt-in internationalization support.\n\n\nSupport for Django 1.8's \nHStoreField\n and \nArrayField\n.\n\n\n\n\n\n\nPagination\n\n\nThe pagination API has been improved, making it both easier to use, and more powerful.\n\n\nA guide to the headline features follows. For full details, see \nthe pagination documentation\n.\n\n\nNote that as a result of this work a number of settings keys and generic view attributes are now moved to pending deprecation. Controlling pagination styles is now largely handled by overriding a pagination class and modifying its configuration attributes.\n\n\n\n\nThe \nPAGINATE_BY\n settings key will continue to work but is now pending deprecation. The more obviously named \nPAGE_SIZE\n settings key should now be used instead.\n\n\nThe \nPAGINATE_BY_PARAM\n, \nMAX_PAGINATE_BY\n settings keys will continue to work but are now pending deprecation, in favor of setting configuration attributes on the configured pagination class.\n\n\nThe \npaginate_by\n, \npage_query_param\n, \npaginate_by_param\n and \nmax_paginate_by\n generic view attributes will continue to work but are now pending deprecation, in favor of setting configuration attributes on the configured pagination class.\n\n\nThe \npagination_serializer_class\n view attribute and \nDEFAULT_PAGINATION_SERIALIZER_CLASS\n settings key \nare no longer valid\n. The pagination API does not use serializers to determine the output format, and you'll need to instead override the \nget_paginated_response\n method on a pagination class in order to specify how the output format is controlled.\n\n\n\n\nNew pagination schemes.\n\n\nUntil now, there has only been a single built-in pagination style in REST framework. We now have page, limit/offset and cursor based schemes included by default.\n\n\nThe cursor based pagination scheme is particularly smart, and is a better approach for clients iterating through large or frequently changing result sets. The scheme supports paging against non-unique indexes, by using both cursor and limit/offset information. It also allows for both forward and reverse cursor pagination. Much credit goes to David Cramer for \nthis blog post\n on the subject.\n\n\nPagination controls in the browsable API.\n\n\nPaginated results now include controls that render directly in the browsable API. If you're using the page or limit/offset style, then you'll see a page based control displayed in the browsable API:\n\n\n\n\nThe cursor based pagination renders a more simple style of control:\n\n\n\n\nSupport for header-based pagination.\n\n\nThe pagination API was previously only able to alter the pagination style in the body of the response. The API now supports being able to write pagination information in response headers, making it possible to use pagination schemes that use the \nLink\n or \nContent-Range\n headers.\n\n\nFor more information, see the \ncustom pagination styles\n documentation.\n\n\n\n\nVersioning\n\n\nWe've made it \neasier to build versioned APIs\n. Built-in schemes for versioning include both URL based and Accept header based variations.\n\n\nWhen using a URL based scheme, hyperlinked serializers will resolve relationships to the same API version as used on the incoming request.\n\n\nFor example, when using \nNamespaceVersioning\n, and the following hyperlinked serializer:\n\n\nclass AccountsSerializer(serializer.HyperlinkedModelSerializer):\n class Meta:\n model = Accounts\n fields = ('account_name', 'users')\n\n\n\nThe output representation would match the version used on the incoming request. Like so:\n\n\nGET http://example.org/v2/accounts/10 # Version 'v2'\n\n{\n \"account_name\": \"europa\",\n \"users\": [\n \"http://example.org/v2/users/12\", # Version 'v2'\n \"http://example.org/v2/users/54\",\n \"http://example.org/v2/users/87\"\n ]\n}\n\n\n\n\n\nInternationalization\n\n\nREST framework now includes a built-in set of translations, and \nsupports internationalized error responses\n. This allows you to either change the default language, or to allow clients to specify the language via the \nAccept-Language\n header.\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{\n \"detail\": \"No se ha podido satisfacer la solicitud de cabecera de Accept.\"\n}\n\n\n\nNote that the structure of the error responses is still the same. We still have a \ndetail\n key in the response. If needed you can modify this behavior too, by using a \ncustom exception handler\n.\n\n\nWe include built-in translations both for standard exception cases, and for serializer validation errors.\n\n\nThe full list of supported languages can be found on our \nTransifex project page\n.\n\n\nIf you only wish to support a subset of the supported languages, use Django's standard \nLANGUAGES\n setting:\n\n\nLANGUAGES = [\n ('de', _('German')),\n ('en', _('English')),\n]\n\n\n\nFor more details, see the \ninternationalization documentation\n.\n\n\nMany thanks to \nCraig Blaszczyk\n for helping push this through.\n\n\n\n\nNew field types\n\n\nDjango 1.8's new \nArrayField\n, \nHStoreField\n and \nUUIDField\n are now all fully supported.\n\n\nThis work also means that we now have both \nserializers.DictField()\n, and \nserializers.ListField()\n types, allowing you to express and validate a wider set of representations.\n\n\nIf you're building a new 1.8 project, then you should probably consider using \nUUIDField\n as the primary keys for all your models. This style will work automatically with hyperlinked serializers, returning URLs in the following style:\n\n\nhttp://example.org/api/purchases/9b1a433f-e90d-4948-848b-300fdc26365d\n\n\n\n\n\nModelSerializer API\n\n\nThe serializer redesign in 3.0 did not include any public API for modifying how ModelSerializer classes automatically generate a set of fields from a given mode class. We've now re-introduced an API for this, allowing you to create new ModelSerializer base classes that behave differently, such as using a different default style for relationships.\n\n\nFor more information, see the documentation on \ncustomizing field mappings\n for ModelSerializer classes.\n\n\n\n\nMoving packages out of core\n\n\nWe've now moved a number of packages out of the core of REST framework, and into separately installable packages. If you're currently using these you don't need to worry, you simply need to \npip install\n the new packages, and change any import paths.\n\n\nWe're making this change in order to help distribute the maintenance workload, and keep better focus of the core essentials of the framework.\n\n\nThe change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained \nDjango OAuth toolkit\n has now been promoted as our recommended option for integrating OAuth support.\n\n\nThe following packages are now moved out of core and should be separately installed:\n\n\n\n\nOAuth - \ndjangorestframework-oauth\n\n\nXML - \ndjangorestframework-xml\n\n\nYAML - \ndjangorestframework-yaml\n\n\nJSONP - \ndjangorestframework-jsonp\n\n\n\n\nIt's worth reiterating that this change in policy shouldn't mean any work in your codebase other than adding a new requirement and modifying some import paths. For example to install XML rendering, you would now do:\n\n\npip install djangorestframework-xml\n\n\n\nAnd modify your settings, like so:\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': [\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n 'rest_framework_xml.renderers.XMLRenderer'\n ]\n}\n\n\n\nThanks go to the latest member of our maintenance team, \nJos\u00e9 Padilla\n, for handling this work and taking on ownership of these packages.\n\n\n\n\nDeprecations\n\n\nThe \nrequest.DATA\n, \nrequest.FILES\n and \nrequest.QUERY_PARAMS\n attributes move from pending deprecation, to deprecated. Use \nrequest.data\n and \nrequest.query_params\n instead, as discussed in the 3.0 release notes.\n\n\nThe ModelSerializer Meta options for \nwrite_only_fields\n, \nview_name\n and \nlookup_field\n are also moved from pending deprecation, to deprecated. Use \nextra_kwargs\n instead, as discussed in the 3.0 release notes.\n\n\nAll these attributes and options will still work in 3.1, but their usage will raise a warning. They will be fully removed in 3.2.\n\n\n\n\nWhat's next?\n\n\nThe next focus will be on HTML renderings of API output and will include:\n\n\n\n\nHTML form rendering of serializers.\n\n\nFiltering controls built-in to the browsable API.\n\n\nAn alternative admin-style interface.\n\n\n\n\nThis will either be made as a single 3.2 release, or split across two separate releases, with the HTML forms and filter controls coming in 3.2, and the admin-style interface coming in a 3.3 release.",
"title": "3.1 Announcement"
},
{
@@ -4957,7 +4967,7 @@
},
{
"location": "/topics/3.1-announcement/#moving-packages-out-of-core",
- "text": "We've now moved a number of packages out of the core of REST framework, and into separately installable packages. If you're currently using these you don't need to worry, you simply need to pip install the new packages, and change any import paths. We're making this change in order to help distribute the maintainance workload, and keep better focus of the core essentials of the framework. The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained Django OAuth toolkit has now been promoted as our recommended option for integrating OAuth support. The following packages are now moved out of core and should be separately installed: OAuth - djangorestframework-oauth XML - djangorestframework-xml YAML - djangorestframework-yaml JSONP - djangorestframework-jsonp It's worth reiterating that this change in policy shouldn't mean any work in your codebase other than adding a new requirement and modifying some import paths. For example to install XML rendering, you would now do: pip install djangorestframework-xml And modify your settings, like so: REST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': [\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n 'rest_framework_xml.renderers.XMLRenderer'\n ]\n} Thanks go to the latest member of our maintenance team, Jos\u00e9 Padilla , for handling this work and taking on ownership of these packages.",
+ "text": "We've now moved a number of packages out of the core of REST framework, and into separately installable packages. If you're currently using these you don't need to worry, you simply need to pip install the new packages, and change any import paths. We're making this change in order to help distribute the maintenance workload, and keep better focus of the core essentials of the framework. The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained Django OAuth toolkit has now been promoted as our recommended option for integrating OAuth support. The following packages are now moved out of core and should be separately installed: OAuth - djangorestframework-oauth XML - djangorestframework-xml YAML - djangorestframework-yaml JSONP - djangorestframework-jsonp It's worth reiterating that this change in policy shouldn't mean any work in your codebase other than adding a new requirement and modifying some import paths. For example to install XML rendering, you would now do: pip install djangorestframework-xml And modify your settings, like so: REST_FRAMEWORK = {\n 'DEFAULT_RENDERER_CLASSES': [\n 'rest_framework.renderers.JSONRenderer',\n 'rest_framework.renderers.BrowsableAPIRenderer',\n 'rest_framework_xml.renderers.XMLRenderer'\n ]\n} Thanks go to the latest member of our maintenance team, Jos\u00e9 Padilla , for handling this work and taking on ownership of these packages.",
"title": "Moving packages out of core"
},
{
@@ -5042,7 +5052,7 @@
},
{
"location": "/topics/3.4-announcement/",
- "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\nDjango REST framework 3.4\n\n\nThe 3.4 release is the first in a planned series that will be addressing schema\ngeneration, hypermedia support, API clients, and finally realtime support.\n\n\n\n\nFunding\n\n\nThe 3.4 release has been made possible a recent \nMozilla grant\n, and by our\n\ncollaborative funding model\n. If you use REST framework commercially, and would\nlike to see this work continue, we strongly encourage you to invest in its\ncontinued development by \nsigning up for a paid plan\n.\n\n\nThe initial aim is to provide a single full-time position on REST framework.\nRight now we're over 60% of the way towards achieving that.\n\nEvery single sign-up makes a significant impact.\n\n\n\n \nRover.com\n\n \nSentry\n\n \nStream\n\n\n\n\n\n\n\n\nMany thanks to all our \nawesome sponsors\n, and in particular to our premium backers, \nRover\n, \nSentry\n, and \nStream\n.\n\n\n\n\nSchemas \n client libraries\n\n\nREST framework 3.4 brings built-in support for generating API schemas.\n\n\nWe provide this support by using \nCore API\n, a Document Object Model\nfor describing APIs.\n\n\nBecause Core API represents the API schema in an format-independent\nmanner, we're able to render the Core API \nDocument\n object into many different\nschema formats, by allowing the renderer class to determine how the internal\nrepresentation maps onto the external schema format.\n\n\nThis approach should also open the door to a range of auto-generated API\ndocumentation options in the future, by rendering the \nDocument\n object into\nHTML documentation pages.\n\n\nAlongside the built-in schema support, we're also now providing the following:\n\n\n\n\nA \ncommand line tool\n for interacting with APIs.\n\n\nA \nPython client library\n for interacting with APIs.\n\n\n\n\nThese API clients are dynamically driven, and able to interact with any API\nthat exposes a supported schema format.\n\n\nDynamically driven clients allow you to interact with an API at an application\nlayer interface, rather than a network layer interface, while still providing\nthe benefits of RESTful Web API design.\n\n\nWe're expecting to expand the range of languages that we provide client libraries\nfor over the coming months.\n\n\nFurther work on maturing the API schema support is also planned, including\ndocumentation on supporting file upload and download, and improved support for\ndocumentation generation and parameter annotation.\n\n\n\n\nCurrent support for schema formats is as follows:\n\n\n\n\n\n\n\n\nName\n\n\nSupport\n\n\nPyPI package\n\n\n\n\n\n\n\n\n\n\nCore JSON\n\n\nSchema generation \n client support.\n\n\nBuilt-in support in \ncoreapi\n\n\n\n\n\n\nSwagger / OpenAPI\n\n\nSchema generation \n client support.\n\n\nThe \nopenapi-codec\npackage.\n\n\n\n\n\n\nJSON Hyper-Schema\n\n\nCurrrently client support only.\n\n\nThe \nhyperschema-codec\npackage.\n\n\n\n\n\n\nAPI Blueprint\n\n\nNot yet available.\n\n\nNot yet available.\n\n\n\n\n\n\n\n\n\n\nYou can read more about any of this new functionality in the following:\n\n\n\n\nNew tutorial section on \nschemas \n client libraries\n.\n\n\nDocumentation page on \nschema generation\n.\n\n\nTopic page on \nAPI clients\n.\n\n\n\n\nIt is also worth noting that Marc Gibbons is currently working towards a 2.0 release of\nthe popular Django REST Swagger package, which will tie in with our new built-in support.\n\n\n\n\nSupported versions\n\n\nThe 3.4.0 release adds support for Django 1.10.\n\n\nThe following versions of Python and Django are now supported:\n\n\n\n\nDjango versions 1.8, 1.9, and 1.10.\n\n\nPython versions 2.7, 3.2(*), 3.3(*), 3.4, 3.5.\n\n\n\n\n(*) Note that Python 3.2 and 3.3 are not supported from Django 1.9 onwards.\n\n\n\n\nDeprecations and changes\n\n\nThe 3.4 release includes very limited deprecation or behavioral changes, and\nshould present a straightforward upgrade.\n\n\nUse fields or exclude on serializer classes.\n\n\nThe following change in 3.3.0 is now escalated from \"pending deprecation\" to\n\"deprecated\". Its usage will continue to function but will raise warnings:\n\n\nModelSerializer\n and \nHyperlinkedModelSerializer\n should include either a \nfields\n\noption, or an \nexclude\n option. The \nfields = '__all__'\n shortcut may be used\nto explicitly include all fields.\n\n\nMicrosecond precision when returning time or datetime.\n\n\nUsing the default JSON renderer and directly returning a \ndatetime\n or \ntime\n\ninstance will now render with microsecond precision (6 digits), rather than\nmillisecond precision (3 digits). This makes the output format consistent with the\ndefault string output of \nserializers.DateTimeField\n and \nserializers.TimeField\n.\n\n\nThis change \ndoes not affect the default behavior when using serializers\n,\nwhich is to serialize \ndatetime\n and \ntime\n instances into strings with\nmicrosecond precision.\n\n\nThe serializer behavior can be modified if needed, using the \nDATETIME_FORMAT\n\nand \nTIME_FORMAT\n settings.\n\n\nThe renderer behavior can be modified by setting a custom \nencoder_class\n\nattribute on a \nJSONRenderer\n subclass.\n\n\nRelational choices no longer displayed in OPTIONS requests.\n\n\nMaking an \nOPTIONS\n request to views that have a serializer choice field\nwill result in a list of the available choices being returned in the response.\n\n\nIn cases where there is a relational field, the previous behavior would be\nto return a list of available instances to choose from for that relational field.\n\n\nIn order to minimise exposed information the behavior now is to \nnot\n return\nchoices information for relational fields.\n\n\nIf you want to override this new behavior you'll need to \nimplement a custom\nmetadata class\n.\n\n\nSee \nissue #3751\n for more information on this behavioral change.\n\n\n\n\nOther improvements\n\n\nThis release includes further work from a huge number of \npull requests and issues\n.\n\n\nMany 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.\n\n\nThe full set of itemized release notes \nare available here\n.",
+ "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\nDjango REST framework 3.4\n\n\nThe 3.4 release is the first in a planned series that will be addressing schema\ngeneration, hypermedia support, API clients, and finally realtime support.\n\n\n\n\nFunding\n\n\nThe 3.4 release has been made possible a recent \nMozilla grant\n, and by our\n\ncollaborative funding model\n. If you use REST framework commercially, and would\nlike to see this work continue, we strongly encourage you to invest in its\ncontinued development by \nsigning up for a paid plan\n.\n\n\nThe initial aim is to provide a single full-time position on REST framework.\nRight now we're over 60% of the way towards achieving that.\n\nEvery single sign-up makes a significant impact.\n\n\n\n \nRover.com\n\n \nSentry\n\n \nStream\n\n\n\n\n\n\n\n\nMany thanks to all our \nawesome sponsors\n, and in particular to our premium backers, \nRover\n, \nSentry\n, and \nStream\n.\n\n\n\n\nSchemas \n client libraries\n\n\nREST framework 3.4 brings built-in support for generating API schemas.\n\n\nWe provide this support by using \nCore API\n, a Document Object Model\nfor describing APIs.\n\n\nBecause Core API represents the API schema in an format-independent\nmanner, we're able to render the Core API \nDocument\n object into many different\nschema formats, by allowing the renderer class to determine how the internal\nrepresentation maps onto the external schema format.\n\n\nThis approach should also open the door to a range of auto-generated API\ndocumentation options in the future, by rendering the \nDocument\n object into\nHTML documentation pages.\n\n\nAlongside the built-in schema support, we're also now providing the following:\n\n\n\n\nA \ncommand line tool\n for interacting with APIs.\n\n\nA \nPython client library\n for interacting with APIs.\n\n\n\n\nThese API clients are dynamically driven, and able to interact with any API\nthat exposes a supported schema format.\n\n\nDynamically driven clients allow you to interact with an API at an application\nlayer interface, rather than a network layer interface, while still providing\nthe benefits of RESTful Web API design.\n\n\nWe're expecting to expand the range of languages that we provide client libraries\nfor over the coming months.\n\n\nFurther work on maturing the API schema support is also planned, including\ndocumentation on supporting file upload and download, and improved support for\ndocumentation generation and parameter annotation.\n\n\n\n\nCurrent support for schema formats is as follows:\n\n\n\n\n\n\n\n\nName\n\n\nSupport\n\n\nPyPI package\n\n\n\n\n\n\n\n\n\n\nCore JSON\n\n\nSchema generation \n client support.\n\n\nBuilt-in support in \ncoreapi\n\n\n\n\n\n\nSwagger / OpenAPI\n\n\nSchema generation \n client support.\n\n\nThe \nopenapi-codec\npackage.\n\n\n\n\n\n\nJSON Hyper-Schema\n\n\nCurrently client support only.\n\n\nThe \nhyperschema-codec\npackage.\n\n\n\n\n\n\nAPI Blueprint\n\n\nNot yet available.\n\n\nNot yet available.\n\n\n\n\n\n\n\n\n\n\nYou can read more about any of this new functionality in the following:\n\n\n\n\nNew tutorial section on \nschemas \n client libraries\n.\n\n\nDocumentation page on \nschema generation\n.\n\n\nTopic page on \nAPI clients\n.\n\n\n\n\nIt is also worth noting that Marc Gibbons is currently working towards a 2.0 release of\nthe popular Django REST Swagger package, which will tie in with our new built-in support.\n\n\n\n\nSupported versions\n\n\nThe 3.4.0 release adds support for Django 1.10.\n\n\nThe following versions of Python and Django are now supported:\n\n\n\n\nDjango versions 1.8, 1.9, and 1.10.\n\n\nPython versions 2.7, 3.2(*), 3.3(*), 3.4, 3.5.\n\n\n\n\n(*) Note that Python 3.2 and 3.3 are not supported from Django 1.9 onwards.\n\n\n\n\nDeprecations and changes\n\n\nThe 3.4 release includes very limited deprecation or behavioral changes, and\nshould present a straightforward upgrade.\n\n\nUse fields or exclude on serializer classes.\n\n\nThe following change in 3.3.0 is now escalated from \"pending deprecation\" to\n\"deprecated\". Its usage will continue to function but will raise warnings:\n\n\nModelSerializer\n and \nHyperlinkedModelSerializer\n should include either a \nfields\n\noption, or an \nexclude\n option. The \nfields = '__all__'\n shortcut may be used\nto explicitly include all fields.\n\n\nMicrosecond precision when returning time or datetime.\n\n\nUsing the default JSON renderer and directly returning a \ndatetime\n or \ntime\n\ninstance will now render with microsecond precision (6 digits), rather than\nmillisecond precision (3 digits). This makes the output format consistent with the\ndefault string output of \nserializers.DateTimeField\n and \nserializers.TimeField\n.\n\n\nThis change \ndoes not affect the default behavior when using serializers\n,\nwhich is to serialize \ndatetime\n and \ntime\n instances into strings with\nmicrosecond precision.\n\n\nThe serializer behavior can be modified if needed, using the \nDATETIME_FORMAT\n\nand \nTIME_FORMAT\n settings.\n\n\nThe renderer behavior can be modified by setting a custom \nencoder_class\n\nattribute on a \nJSONRenderer\n subclass.\n\n\nRelational choices no longer displayed in OPTIONS requests.\n\n\nMaking an \nOPTIONS\n request to views that have a serializer choice field\nwill result in a list of the available choices being returned in the response.\n\n\nIn cases where there is a relational field, the previous behavior would be\nto return a list of available instances to choose from for that relational field.\n\n\nIn order to minimise exposed information the behavior now is to \nnot\n return\nchoices information for relational fields.\n\n\nIf you want to override this new behavior you'll need to \nimplement a custom\nmetadata class\n.\n\n\nSee \nissue #3751\n for more information on this behavioral change.\n\n\n\n\nOther improvements\n\n\nThis release includes further work from a huge number of \npull requests and issues\n.\n\n\nMany 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.\n\n\nThe full set of itemized release notes \nare available here\n.",
"title": "3.4 Announcement"
},
{
@@ -5057,7 +5067,7 @@
},
{
"location": "/topics/3.4-announcement/#schemas-client-libraries",
- "text": "REST framework 3.4 brings built-in support for generating API schemas. We provide this support by using Core API , a Document Object Model\nfor describing APIs. Because Core API represents the API schema in an format-independent\nmanner, we're able to render the Core API Document object into many different\nschema formats, by allowing the renderer class to determine how the internal\nrepresentation maps onto the external schema format. This approach should also open the door to a range of auto-generated API\ndocumentation options in the future, by rendering the Document object into\nHTML documentation pages. Alongside the built-in schema support, we're also now providing the following: A command line tool for interacting with APIs. A Python client library for interacting with APIs. These API clients are dynamically driven, and able to interact with any API\nthat exposes a supported schema format. Dynamically driven clients allow you to interact with an API at an application\nlayer interface, rather than a network layer interface, while still providing\nthe benefits of RESTful Web API design. We're expecting to expand the range of languages that we provide client libraries\nfor over the coming months. Further work on maturing the API schema support is also planned, including\ndocumentation on supporting file upload and download, and improved support for\ndocumentation generation and parameter annotation. Current support for schema formats is as follows: Name Support PyPI package Core JSON Schema generation client support. Built-in support in coreapi Swagger / OpenAPI Schema generation client support. The openapi-codec package. JSON Hyper-Schema Currrently client support only. The hyperschema-codec package. API Blueprint Not yet available. Not yet available. You can read more about any of this new functionality in the following: New tutorial section on schemas client libraries . Documentation page on schema generation . Topic page on API clients . It is also worth noting that Marc Gibbons is currently working towards a 2.0 release of\nthe popular Django REST Swagger package, which will tie in with our new built-in support.",
+ "text": "REST framework 3.4 brings built-in support for generating API schemas. We provide this support by using Core API , a Document Object Model\nfor describing APIs. Because Core API represents the API schema in an format-independent\nmanner, we're able to render the Core API Document object into many different\nschema formats, by allowing the renderer class to determine how the internal\nrepresentation maps onto the external schema format. This approach should also open the door to a range of auto-generated API\ndocumentation options in the future, by rendering the Document object into\nHTML documentation pages. Alongside the built-in schema support, we're also now providing the following: A command line tool for interacting with APIs. A Python client library for interacting with APIs. These API clients are dynamically driven, and able to interact with any API\nthat exposes a supported schema format. Dynamically driven clients allow you to interact with an API at an application\nlayer interface, rather than a network layer interface, while still providing\nthe benefits of RESTful Web API design. We're expecting to expand the range of languages that we provide client libraries\nfor over the coming months. Further work on maturing the API schema support is also planned, including\ndocumentation on supporting file upload and download, and improved support for\ndocumentation generation and parameter annotation. Current support for schema formats is as follows: Name Support PyPI package Core JSON Schema generation client support. Built-in support in coreapi Swagger / OpenAPI Schema generation client support. The openapi-codec package. JSON Hyper-Schema Currently client support only. The hyperschema-codec package. API Blueprint Not yet available. Not yet available. You can read more about any of this new functionality in the following: New tutorial section on schemas client libraries . Documentation page on schema generation . Topic page on API clients . It is also worth noting that Marc Gibbons is currently working towards a 2.0 release of\nthe popular Django REST Swagger package, which will tie in with our new built-in support.",
"title": "Schemas & client libraries"
},
{
@@ -5177,7 +5187,7 @@
},
{
"location": "/topics/kickstarter-announcement/",
- "text": "Kickstarting Django REST framework 3\n\n\n\n\n \n\n\n\n\n\nIn order to continue to drive the project forward, I'm launching a Kickstarter campaign to help fund the development of a major new release - Django REST framework 3.\n\n\nProject details\n\n\nThis new release will allow us to comprehensively address some of the shortcomings of the framework, and will aim to include the following:\n\n\n\n\nFaster, simpler and easier-to-use serializers.\n\n\nAn alternative admin-style interface for the browsable API.\n\n\nSearch and filtering controls made accessible in the browsable API.\n\n\nAlternative API pagination styles.\n\n\nDocumentation around API versioning.\n\n\nTriage of outstanding tickets.\n\n\nImproving the ongoing quality and maintainability of the project.\n\n\n\n\nFull details are available now on the \nproject page\n.\n\n\nIf you're interested in helping make sustainable open source development a reality please \nvisit the Kickstarter page\n and consider funding the project.\n\n\nI can't wait to see where this takes us!\n\n\nMany thanks to everyone for your support so far,\n\n\nTom Christie :)\n\n\n\n\nSponsors\n\n\nWe've now blazed way past all our goals, with a staggering \u00a330,000 (~$50,000), meaning I'll be in a position to work on the project significantly beyond what we'd originally planned for. I owe a huge debt of gratitude to all the wonderful companies and individuals who have been backing the project so generously, and making this possible.\n\n\n\n\nPlatinum sponsors\n\n\nOur platinum sponsors have each made a hugely substantial contribution to the future development of Django REST framework, and I simply can't thank them enough.\n\n\n\n\nEventbrite\n\n\n\n\n\n\n\nDivio\n\n\nLulu\n\n\nPotato\n\n\nWiredrive\n\n\nCyan\n\n\nRunscope\n\n\nSimple Energy\n\n\nVOKAL Interactive\n\n\nPurple Bit\n\n\nKuwaitNET\n\n\n\n\n\n\n\n\n\n\nGold sponsors\n\n\nOur gold sponsors include companies large and small. Many thanks for their significant funding of the project and their commitment to sustainable open-source development.\n\n\n\n\nLaterPay\n\n\nSchuberg Philis\n\n\nProReNata AB\n\n\nSGA Websites\n\n\nSirono\n\n\nVinta Software Studio\n\n\nRapasso\n\n\nMirus Research\n\n\nHipo\n\n\nByte\n\n\nLightning Kite\n\n\nOpbeat\n\n\nKoordinates\n\n\nPulsecode Inc.\n\n\nSinging Horse Studio Ltd.\n\n\nHeroku\n\n\nRheinwerk Verlag\n\n\nSecurity Compass\n\n\nDjango Software Foundation\n\n\nHipflask\n\n\nCrate\n\n\nCryptico Corp\n\n\nNextHub\n\n\nCompile\n\n\nWusaWork\n\n\nEnvision Linux\n\n\n\n\n\n\n\n\n\n\nSilver sponsors\n\n\nThe serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank\nyou to individuals who have choosen to privately support the project at this level.\n\n\n\n\nIMT Computer Services\n\n\nWildfish\n\n\nThermondo GmbH\n\n\nProvidenz\n\n\nalwaysdata.com\n\n\nTriggered Messaging\n\n\nPushPull Technology Ltd\n\n\nTranscode\n\n\nGarfo\n\n\nShippo\n\n\nGizmag\n\n\nTivix\n\n\nSafari\n\n\nBright Loop\n\n\nABA Systems\n\n\nbeefarm.ru\n\n\nVzzual.com\n\n\nInfinite Code\n\n\nCrossword Tracker\n\n\nPkgFarm\n\n\nLife. The Game.\n\n\nBlimp\n\n\nPathwright\n\n\nFluxility\n\n\nTeonite\n\n\nTrackMaven\n\n\nPhurba\n\n\nNephila\n\n\nAditium\n\n\nOpenEye Scientific Software\n\n\nHolvi\n\n\nCantemo\n\n\nMakeSpace\n\n\nAX Semantics\n\n\nISL\n\n\n\n\n\n\n\n\nIndividual backers\n: Paul Hallett, \nPaul Whipp\n, Dylan Roy, Jannis Leidel, \nXavier Ordoquy\n, \nJohannes Spielmann\n, \nRob Spectre\n, \nChris Heisel\n, Marwan Alsabbagh, Haris Ali, Tuomas Toivonen.\n\n\n\n\nAdvocates\n\n\nThe following individuals made a significant financial contribution to the development of Django REST framework 3, for which I can only offer a huge, warm and sincere thank you!\n\n\nIndividual backers\n: Jure Cuhalev, Kevin Brolly, Ferenc Szalai, Dougal Matthews, Stefan Foulis, Carlos Hernando, Alen Mujezinovic, Ross Crawford-d'Heureuse, George Kappel, Alasdair Nicol, John Carr, Steve Winton, Trey, Manuel Miranda, David Horn, Vince Mi, Daniel Sears, Jamie Matthews, Ryan Currah, Marty Kemka, Scott Nixon, Moshin Elahi, Kevin Campbell, Jose Antonio Leiva Izquierdo, Kevin Stone, Andrew Godwin, Tijs Teulings, Roger Boardman, Xavier Antoviaque, Darian Moody, Lujeni, Jon Dugan, Wiley Kestner, Daniel C. Silverstein, Daniel Hahler, Subodh Nijsure, Philipp Weidenhiller, Yusuke Muraoka, Danny Roa, Reto Aebersold, Kyle Getrost, D\u00e9c\u00e9bal Hormuz, James Dacosta, Matt Long, Mauro Rocco, Tyrel Souza, Ryan Campbell, Ville Jyrkk\u00e4, Charalampos Papaloizou, Nikolai R\u00f8ed Kristiansen, Antoni Aloy L\u00f3pez, Celia Oakley, Micha\u0142 Krawczak, Ivan VenOsdel, Tim Watts, Martin Warne, Nicola Jordan, Ryan Kaskel.\n\n\nCorporate backers\n: Savannah Informatics, Prism Skylabs, Musical Operating Devices.\n\n\n\n\nSupporters\n\n\nThere were also almost 300 further individuals choosing to help fund the project at other levels or choosing to give anonymously. Again, thank you, thank you, thank you!",
+ "text": "Kickstarting Django REST framework 3\n\n\n\n\n \n\n\n\n\n\nIn order to continue to drive the project forward, I'm launching a Kickstarter campaign to help fund the development of a major new release - Django REST framework 3.\n\n\nProject details\n\n\nThis new release will allow us to comprehensively address some of the shortcomings of the framework, and will aim to include the following:\n\n\n\n\nFaster, simpler and easier-to-use serializers.\n\n\nAn alternative admin-style interface for the browsable API.\n\n\nSearch and filtering controls made accessible in the browsable API.\n\n\nAlternative API pagination styles.\n\n\nDocumentation around API versioning.\n\n\nTriage of outstanding tickets.\n\n\nImproving the ongoing quality and maintainability of the project.\n\n\n\n\nFull details are available now on the \nproject page\n.\n\n\nIf you're interested in helping make sustainable open source development a reality please \nvisit the Kickstarter page\n and consider funding the project.\n\n\nI can't wait to see where this takes us!\n\n\nMany thanks to everyone for your support so far,\n\n\nTom Christie :)\n\n\n\n\nSponsors\n\n\nWe've now blazed way past all our goals, with a staggering \u00a330,000 (~$50,000), meaning I'll be in a position to work on the project significantly beyond what we'd originally planned for. I owe a huge debt of gratitude to all the wonderful companies and individuals who have been backing the project so generously, and making this possible.\n\n\n\n\nPlatinum sponsors\n\n\nOur platinum sponsors have each made a hugely substantial contribution to the future development of Django REST framework, and I simply can't thank them enough.\n\n\n\n\nEventbrite\n\n\n\n\n\n\n\nDivio\n\n\nLulu\n\n\nPotato\n\n\nWiredrive\n\n\nCyan\n\n\nRunscope\n\n\nSimple Energy\n\n\nVOKAL Interactive\n\n\nPurple Bit\n\n\nKuwaitNET\n\n\n\n\n\n\n\n\n\n\nGold sponsors\n\n\nOur gold sponsors include companies large and small. Many thanks for their significant funding of the project and their commitment to sustainable open-source development.\n\n\n\n\nLaterPay\n\n\nSchuberg Philis\n\n\nProReNata AB\n\n\nSGA Websites\n\n\nSirono\n\n\nVinta Software Studio\n\n\nRapasso\n\n\nMirus Research\n\n\nHipo\n\n\nByte\n\n\nLightning Kite\n\n\nOpbeat\n\n\nKoordinates\n\n\nPulsecode Inc.\n\n\nSinging Horse Studio Ltd.\n\n\nHeroku\n\n\nRheinwerk Verlag\n\n\nSecurity Compass\n\n\nDjango Software Foundation\n\n\nHipflask\n\n\nCrate\n\n\nCryptico Corp\n\n\nNextHub\n\n\nCompile\n\n\nWusaWork\n\n\nEnvision Linux\n\n\n\n\n\n\n\n\n\n\nSilver sponsors\n\n\nThe serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank\nyou to individuals who have chosen to privately support the project at this level.\n\n\n\n\nIMT Computer Services\n\n\nWildfish\n\n\nThermondo GmbH\n\n\nProvidenz\n\n\nalwaysdata.com\n\n\nTriggered Messaging\n\n\nPushPull Technology Ltd\n\n\nTranscode\n\n\nGarfo\n\n\nShippo\n\n\nGizmag\n\n\nTivix\n\n\nSafari\n\n\nBright Loop\n\n\nABA Systems\n\n\nbeefarm.ru\n\n\nVzzual.com\n\n\nInfinite Code\n\n\nCrossword Tracker\n\n\nPkgFarm\n\n\nLife. The Game.\n\n\nBlimp\n\n\nPathwright\n\n\nFluxility\n\n\nTeonite\n\n\nTrackMaven\n\n\nPhurba\n\n\nNephila\n\n\nAditium\n\n\nOpenEye Scientific Software\n\n\nHolvi\n\n\nCantemo\n\n\nMakeSpace\n\n\nAX Semantics\n\n\nISL\n\n\n\n\n\n\n\n\nIndividual backers\n: Paul Hallett, \nPaul Whipp\n, Dylan Roy, Jannis Leidel, \nXavier Ordoquy\n, \nJohannes Spielmann\n, \nRob Spectre\n, \nChris Heisel\n, Marwan Alsabbagh, Haris Ali, Tuomas Toivonen.\n\n\n\n\nAdvocates\n\n\nThe following individuals made a significant financial contribution to the development of Django REST framework 3, for which I can only offer a huge, warm and sincere thank you!\n\n\nIndividual backers\n: Jure Cuhalev, Kevin Brolly, Ferenc Szalai, Dougal Matthews, Stefan Foulis, Carlos Hernando, Alen Mujezinovic, Ross Crawford-d'Heureuse, George Kappel, Alasdair Nicol, John Carr, Steve Winton, Trey, Manuel Miranda, David Horn, Vince Mi, Daniel Sears, Jamie Matthews, Ryan Currah, Marty Kemka, Scott Nixon, Moshin Elahi, Kevin Campbell, Jose Antonio Leiva Izquierdo, Kevin Stone, Andrew Godwin, Tijs Teulings, Roger Boardman, Xavier Antoviaque, Darian Moody, Lujeni, Jon Dugan, Wiley Kestner, Daniel C. Silverstein, Daniel Hahler, Subodh Nijsure, Philipp Weidenhiller, Yusuke Muraoka, Danny Roa, Reto Aebersold, Kyle Getrost, D\u00e9c\u00e9bal Hormuz, James Dacosta, Matt Long, Mauro Rocco, Tyrel Souza, Ryan Campbell, Ville Jyrkk\u00e4, Charalampos Papaloizou, Nikolai R\u00f8ed Kristiansen, Antoni Aloy L\u00f3pez, Celia Oakley, Micha\u0142 Krawczak, Ivan VenOsdel, Tim Watts, Martin Warne, Nicola Jordan, Ryan Kaskel.\n\n\nCorporate backers\n: Savannah Informatics, Prism Skylabs, Musical Operating Devices.\n\n\n\n\nSupporters\n\n\nThere were also almost 300 further individuals choosing to help fund the project at other levels or choosing to give anonymously. Again, thank you, thank you, thank you!",
"title": "Kickstarter Announcement"
},
{
@@ -5207,7 +5217,7 @@
},
{
"location": "/topics/kickstarter-announcement/#silver-sponsors",
- "text": "The serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank you to individuals who have choosen to privately support the project at this level. IMT Computer Services Wildfish Thermondo GmbH Providenz alwaysdata.com Triggered Messaging PushPull Technology Ltd Transcode Garfo Shippo Gizmag Tivix Safari Bright Loop ABA Systems beefarm.ru Vzzual.com Infinite Code Crossword Tracker PkgFarm Life. The Game. Blimp Pathwright Fluxility Teonite TrackMaven Phurba Nephila Aditium OpenEye Scientific Software Holvi Cantemo MakeSpace AX Semantics ISL Individual backers : Paul Hallett, Paul Whipp , Dylan Roy, Jannis Leidel, Xavier Ordoquy , Johannes Spielmann , Rob Spectre , Chris Heisel , Marwan Alsabbagh, Haris Ali, Tuomas Toivonen.",
+ "text": "The serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank you to individuals who have chosen to privately support the project at this level. IMT Computer Services Wildfish Thermondo GmbH Providenz alwaysdata.com Triggered Messaging PushPull Technology Ltd Transcode Garfo Shippo Gizmag Tivix Safari Bright Loop ABA Systems beefarm.ru Vzzual.com Infinite Code Crossword Tracker PkgFarm Life. The Game. Blimp Pathwright Fluxility Teonite TrackMaven Phurba Nephila Aditium OpenEye Scientific Software Holvi Cantemo MakeSpace AX Semantics ISL Individual backers : Paul Hallett, Paul Whipp , Dylan Roy, Jannis Leidel, Xavier Ordoquy , Johannes Spielmann , Rob Spectre , Chris Heisel , Marwan Alsabbagh, Haris Ali, Tuomas Toivonen.",
"title": "Silver sponsors"
},
{
@@ -5282,7 +5292,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.5.x series\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 adjustements. (\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.5.x series\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.",
"title": "Release Notes"
},
{
@@ -5372,7 +5382,7 @@
},
{
"location": "/topics/release-notes/#340",
- "text": "Date : 14th July 2016 Don't strip microseconds in JSON output. ( #4256 ) Two slightly different iso 8601 datetime serialization. ( #4255 ) Resolve incorrect inclusion of media type parameters. ( #4254 ) Response Content-Type potentially malformed. ( #4253 ) Fix setup.py error on some platforms. ( #4246 ) Move alternate formats in coreapi into separate packages. ( #4244 ) Add localize keyword argument to DecimalField . ( #4233 ) Fix issues with routers for custom list-route and detail-routes. ( #4229 ) Namespace versioning with nested namespaces. ( #4219 ) Robust uniqueness checks. ( #4217 ) Minor refactoring of must_call_distinct . ( #4215 ) Overridable offset cutoff in CursorPagination. ( #4212 ) Pass through strings as-in with date/time fields. ( #4196 ) Add test confirming that required=False is valid on a relational field. ( #4195 ) In LimitOffsetPagination limit=0 should revert to default limit. ( #4194 ) Exclude read_only=True fields from unique_together validation add docs. ( #4192 ) Handle bytestrings in JSON. ( #4191 ) JSONField(binary=True) represents using binary strings, which JSONRenderer does not support. ( #4187 ) JSONField(binary=True) represents using binary strings, which JSONRenderer does not support. ( #4185 ) More robust form rendering in the browsable API. ( #4181 ) Empty cases of .validated_data and .errors as lists not dicts for ListSerializer. ( #4180 ) Schemas client libraries. ( #4179 ) Removed AUTH_USER_MODEL compat property. ( #4176 ) Clean up existing deprecation warnings. ( #4166 ) Django 1.10 support. ( #4158 ) Updated jQuery version to 1.12.4. ( #4157 ) More robust default behavior on OrderingFilter. ( #4156 ) description.py codes and tests removal. ( #4153 ) Wrap guardian.VERSION in tuple. ( #4149 ) Refine validator for fields with kwargs. ( #4146 ) Fix None values representation in childs of ListField, DictField. ( #4118 ) Resolve TimeField representation for midnight value. ( #4107 ) Set proper status code in AdminRenderer for the redirection after POST/DELETE requests. ( #4106 ) TimeField render returns None instead of 00:00:00. ( #4105 ) Fix incorrectly named zh-hans and zh-hant locale path. ( #4103 ) Prevent raising exception when limit is 0. ( #4098 ) TokenAuthentication: Allow custom keyword in the header. ( #4097 ) Handle incorrectly padded HTTP basic auth header. ( #4090 ) LimitOffset pagination crashes Browseable API when limit=0. ( #4079 ) Fixed DecimalField arbitrary precision support. ( #4075 ) Added support for custom CSRF cookie names. ( #4049 ) Fix regression introduced by #4035. ( #4041 ) No auth view failing permission should raise 403. ( #4040 ) Fix string_types / text_types confusion. ( #4025 ) Do not list related field choices in OPTIONS requests. ( #4021 ) Fix typo. ( #4008 ) Reorder initializing the view. ( #4006 ) Type error in DjangoObjectPermissionsFilter on Python 3.4. ( #4005 ) Fixed use of deprecated Query.aggregates. ( #4003 ) Fix blank lines around docstrings. ( #4002 ) Fixed admin pagination when limit is 0. ( #3990 ) OrderingFilter adjustements. ( #3983 ) Non-required serializer related fields. ( #3976 ) Using safer calling way of \"@api_view\" in tutorial. ( #3971 ) ListSerializer doesn't handle unique_together constraints. ( #3970 ) Add missing migration file. ( #3968 ) OrderingFilter should call get_serializer_class() to determine default fields. ( #3964 ) Remove old django checks from tests and compat. ( #3953 ) Support callable as the value of initial for any serializer.Field . ( #3943 ) Prevented unnecessary distinct() call in SearchFilter. ( #3938 ) Fix None UUID ForeignKey serialization. ( #3936 ) Drop EOL Django 1.7. ( #3933 ) Add missing space in serializer error message. ( #3926 ) Fixed _force_text_recursive typo. ( #3908 ) Attempt to address Django 2.0 deprecate warnings related to field.rel . ( #3906 ) Fix parsing multipart data using a nested serializer with list. ( #3820 ) Resolving APIs URL to different namespaces. ( #3816 ) Do not HTML-escape help_text in Browsable API forms. ( #3812 ) OPTIONS fetches and shows all possible foreign keys in choices field. ( #3751 ) Django 1.9 deprecation warnings ( #3729 ) Test case for #3598 ( #3710 ) Adding support for multiple values for search filter. ( #3541 ) Use get_serializer_class in ordering filter. ( #3487 ) Serializers with many=True should return empty list rather than empty dict. ( #3476 ) LimitOffsetPagination limit=0 fix. ( #3444 ) Enable Validators to defer string evaluation and handle new string format. ( #3438 ) Unique validator is executed and breaks if field is invalid. ( #3381 ) Do not ignore overridden View.get_view_name() in breadcrumbs. ( #3273 ) Retry form rendering when rendering with serializer fails. ( #3164 ) Unique constraint prevents nested serializers from updating. ( #2996 ) Uniqueness validators should not be run for excluded (read_only) fields. ( #2848 ) UniqueValidator raises exception for nested objects. ( #2403 ) lookup_type is deprecated in favor of lookup_expr . ( #4259 )",
+ "text": "Date : 14th July 2016 Don't strip microseconds in JSON output. ( #4256 ) Two slightly different iso 8601 datetime serialization. ( #4255 ) Resolve incorrect inclusion of media type parameters. ( #4254 ) Response Content-Type potentially malformed. ( #4253 ) Fix setup.py error on some platforms. ( #4246 ) Move alternate formats in coreapi into separate packages. ( #4244 ) Add localize keyword argument to DecimalField . ( #4233 ) Fix issues with routers for custom list-route and detail-routes. ( #4229 ) Namespace versioning with nested namespaces. ( #4219 ) Robust uniqueness checks. ( #4217 ) Minor refactoring of must_call_distinct . ( #4215 ) Overridable offset cutoff in CursorPagination. ( #4212 ) Pass through strings as-in with date/time fields. ( #4196 ) Add test confirming that required=False is valid on a relational field. ( #4195 ) In LimitOffsetPagination limit=0 should revert to default limit. ( #4194 ) Exclude read_only=True fields from unique_together validation add docs. ( #4192 ) Handle bytestrings in JSON. ( #4191 ) JSONField(binary=True) represents using binary strings, which JSONRenderer does not support. ( #4187 ) JSONField(binary=True) represents using binary strings, which JSONRenderer does not support. ( #4185 ) More robust form rendering in the browsable API. ( #4181 ) Empty cases of .validated_data and .errors as lists not dicts for ListSerializer. ( #4180 ) Schemas client libraries. ( #4179 ) Removed AUTH_USER_MODEL compat property. ( #4176 ) Clean up existing deprecation warnings. ( #4166 ) Django 1.10 support. ( #4158 ) Updated jQuery version to 1.12.4. ( #4157 ) More robust default behavior on OrderingFilter. ( #4156 ) description.py codes and tests removal. ( #4153 ) Wrap guardian.VERSION in tuple. ( #4149 ) Refine validator for fields with kwargs. ( #4146 ) Fix None values representation in childs of ListField, DictField. ( #4118 ) Resolve TimeField representation for midnight value. ( #4107 ) Set proper status code in AdminRenderer for the redirection after POST/DELETE requests. ( #4106 ) TimeField render returns None instead of 00:00:00. ( #4105 ) Fix incorrectly named zh-hans and zh-hant locale path. ( #4103 ) Prevent raising exception when limit is 0. ( #4098 ) TokenAuthentication: Allow custom keyword in the header. ( #4097 ) Handle incorrectly padded HTTP basic auth header. ( #4090 ) LimitOffset pagination crashes Browseable API when limit=0. ( #4079 ) Fixed DecimalField arbitrary precision support. ( #4075 ) Added support for custom CSRF cookie names. ( #4049 ) Fix regression introduced by #4035. ( #4041 ) No auth view failing permission should raise 403. ( #4040 ) Fix string_types / text_types confusion. ( #4025 ) Do not list related field choices in OPTIONS requests. ( #4021 ) Fix typo. ( #4008 ) Reorder initializing the view. ( #4006 ) Type error in DjangoObjectPermissionsFilter on Python 3.4. ( #4005 ) Fixed use of deprecated Query.aggregates. ( #4003 ) Fix blank lines around docstrings. ( #4002 ) Fixed admin pagination when limit is 0. ( #3990 ) OrderingFilter adjustments. ( #3983 ) Non-required serializer related fields. ( #3976 ) Using safer calling way of \"@api_view\" in tutorial. ( #3971 ) ListSerializer doesn't handle unique_together constraints. ( #3970 ) Add missing migration file. ( #3968 ) OrderingFilter should call get_serializer_class() to determine default fields. ( #3964 ) Remove old django checks from tests and compat. ( #3953 ) Support callable as the value of initial for any serializer.Field . ( #3943 ) Prevented unnecessary distinct() call in SearchFilter. ( #3938 ) Fix None UUID ForeignKey serialization. ( #3936 ) Drop EOL Django 1.7. ( #3933 ) Add missing space in serializer error message. ( #3926 ) Fixed _force_text_recursive typo. ( #3908 ) Attempt to address Django 2.0 deprecate warnings related to field.rel . ( #3906 ) Fix parsing multipart data using a nested serializer with list. ( #3820 ) Resolving APIs URL to different namespaces. ( #3816 ) Do not HTML-escape help_text in Browsable API forms. ( #3812 ) OPTIONS fetches and shows all possible foreign keys in choices field. ( #3751 ) Django 1.9 deprecation warnings ( #3729 ) Test case for #3598 ( #3710 ) Adding support for multiple values for search filter. ( #3541 ) Use get_serializer_class in ordering filter. ( #3487 ) Serializers with many=True should return empty list rather than empty dict. ( #3476 ) LimitOffsetPagination limit=0 fix. ( #3444 ) Enable Validators to defer string evaluation and handle new string format. ( #3438 ) Unique validator is executed and breaks if field is invalid. ( #3381 ) Do not ignore overridden View.get_view_name() in breadcrumbs. ( #3273 ) Retry form rendering when rendering with serializer fails. ( #3164 ) Unique constraint prevents nested serializers from updating. ( #2996 ) Uniqueness validators should not be run for excluded (read_only) fields. ( #2848 ) UniqueValidator raises exception for nested objects. ( #2403 ) lookup_type is deprecated in favor of lookup_expr . ( #4259 )",
"title": "3.4.0"
},
{
diff --git a/sitemap.xml b/sitemap.xml
index 697d82caa..caaddf6b5 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -4,7 +4,7 @@
http://www.django-rest-framework.org//
- 2017-01-08
+ 2017-01-27
daily
@@ -13,49 +13,49 @@
http://www.django-rest-framework.org//tutorial/quickstart/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//tutorial/1-serialization/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//tutorial/2-requests-and-responses/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//tutorial/3-class-based-views/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//tutorial/4-authentication-and-permissions/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//tutorial/5-relationships-and-hyperlinked-apis/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//tutorial/6-viewsets-and-routers/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//tutorial/7-schemas-and-client-libraries/
- 2017-01-08
+ 2017-01-27
daily
@@ -65,163 +65,163 @@
http://www.django-rest-framework.org//api-guide/requests/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/responses/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/views/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/generic-views/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/viewsets/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/routers/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/parsers/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/renderers/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/serializers/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/fields/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/relations/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/validators/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/authentication/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/permissions/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/throttling/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/filtering/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/pagination/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/versioning/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/content-negotiation/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/metadata/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/schemas/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/format-suffixes/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/reverse/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/exceptions/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/status-codes/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/testing/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//api-guide/settings/
- 2017-01-08
+ 2017-01-27
daily
@@ -231,127 +231,127 @@
http://www.django-rest-framework.org//topics/documenting-your-api/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/api-clients/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/internationalization/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/ajax-csrf-cors/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/html-and-forms/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/browser-enhancements/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/browsable-api/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/rest-hypermedia-hateoas/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/third-party-resources/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/contributing/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/project-management/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/3.0-announcement/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/3.1-announcement/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/3.2-announcement/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/3.3-announcement/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/3.4-announcement/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/3.5-announcement/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/kickstarter-announcement/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/mozilla-grant/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/funding/
- 2017-01-08
+ 2017-01-27
daily
http://www.django-rest-framework.org//topics/release-notes/
- 2017-01-08
+ 2017-01-27
daily
diff --git a/topics/3.0-announcement/index.html b/topics/3.0-announcement/index.html
index 5a5db3c45..5cfdb2dc6 100644
--- a/topics/3.0-announcement/index.html
+++ b/topics/3.0-announcement/index.html
@@ -4,7 +4,6 @@
-
3.0 Announcement - Django REST framework
diff --git a/topics/3.1-announcement/index.html b/topics/3.1-announcement/index.html
index 534a3d019..594562db3 100644
--- a/topics/3.1-announcement/index.html
+++ b/topics/3.1-announcement/index.html
@@ -4,7 +4,6 @@
-
3.1 Announcement - Django REST framework
@@ -524,7 +523,7 @@ Host: example.org
Moving packages out of core
We've now moved a number of packages out of the core of REST framework, and into separately installable packages. If you're currently using these you don't need to worry, you simply need to pip install
the new packages, and change any import paths.
-We're making this change in order to help distribute the maintainance workload, and keep better focus of the core essentials of the framework.
+We're making this change in order to help distribute the maintenance workload, and keep better focus of the core essentials of the framework.
The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained Django OAuth toolkit has now been promoted as our recommended option for integrating OAuth support.
The following packages are now moved out of core and should be separately installed:
diff --git a/topics/3.2-announcement/index.html b/topics/3.2-announcement/index.html
index 1a238e2b1..9345ca4e1 100644
--- a/topics/3.2-announcement/index.html
+++ b/topics/3.2-announcement/index.html
@@ -4,7 +4,6 @@
-
3.2 Announcement - Django REST framework
diff --git a/topics/3.3-announcement/index.html b/topics/3.3-announcement/index.html
index b28c26703..396fbcb4d 100644
--- a/topics/3.3-announcement/index.html
+++ b/topics/3.3-announcement/index.html
@@ -4,7 +4,6 @@
-
3.3 Announcement - Django REST framework
diff --git a/topics/3.4-announcement/index.html b/topics/3.4-announcement/index.html
index 4d59b1117..a003fcdf1 100644
--- a/topics/3.4-announcement/index.html
+++ b/topics/3.4-announcement/index.html
@@ -4,7 +4,6 @@
-
3.4 Announcement - Django REST framework
@@ -496,7 +495,7 @@ documentation generation and parameter annotation.
JSON Hyper-Schema
-Currrently client support only.
+Currently client support only.
The hyperschema-codec
package.
diff --git a/topics/3.5-announcement/index.html b/topics/3.5-announcement/index.html
index d1233c672..99af36450 100644
--- a/topics/3.5-announcement/index.html
+++ b/topics/3.5-announcement/index.html
@@ -4,7 +4,6 @@
-
3.5 Announcement - Django REST framework
diff --git a/topics/ajax-csrf-cors/index.html b/topics/ajax-csrf-cors/index.html
index 0168ca67c..84c20ecf2 100644
--- a/topics/ajax-csrf-cors/index.html
+++ b/topics/ajax-csrf-cors/index.html
@@ -4,7 +4,6 @@
-
AJAX, CSRF & CORS - Django REST framework
diff --git a/topics/api-clients/index.html b/topics/api-clients/index.html
index bbbf2a1ef..a7677abdf 100644
--- a/topics/api-clients/index.html
+++ b/topics/api-clients/index.html
@@ -4,7 +4,6 @@
-
API Clients - Django REST framework
@@ -603,7 +602,7 @@ credentials, headers and bookmarks:
Python client library
-The coreapi
Python package allows you to programatically interact with any
+
The coreapi
Python package allows you to programmatically interact with any
API that exposes a supported schema format.
Getting started
You'll need to install the coreapi
package using pip
before you can get
diff --git a/topics/browsable-api/index.html b/topics/browsable-api/index.html
index c19116b78..ffb642472 100644
--- a/topics/browsable-api/index.html
+++ b/topics/browsable-api/index.html
@@ -4,7 +4,6 @@
-
The Browsable API - Django REST framework
diff --git a/topics/browser-enhancements/index.html b/topics/browser-enhancements/index.html
index a81abd0d1..9d5e8e75d 100644
--- a/topics/browser-enhancements/index.html
+++ b/topics/browser-enhancements/index.html
@@ -4,7 +4,6 @@
-
Browser Enhancements - Django REST framework
diff --git a/topics/contributing/index.html b/topics/contributing/index.html
index 42002e374..dd231b15f 100644
--- a/topics/contributing/index.html
+++ b/topics/contributing/index.html
@@ -4,7 +4,6 @@
-
Contributing to REST framework - Django REST framework
diff --git a/topics/documenting-your-api/index.html b/topics/documenting-your-api/index.html
index 9ebfad8ec..96d896d34 100644
--- a/topics/documenting-your-api/index.html
+++ b/topics/documenting-your-api/index.html
@@ -4,7 +4,6 @@
-
Documenting your API - Django REST framework
@@ -467,7 +466,7 @@
[ref]: http://example.com/activating-accounts
"""
-Note that one constraint of using viewsets is that any documentation be used for all generated views, so for example, you cannot have differing documentation for the generated list view and detail view.
+Note that when using viewsets the basic docstring is used for all generated views. To provide descriptions for each view, such as for the the list and retrieve views, use docstring sections as described in Schemas as documentation: Examples.
The OPTIONS
method
REST framework APIs also support programmatically accessible descriptions, using the OPTIONS
HTTP method. A view will respond to an OPTIONS
request with metadata including the name, description, and the various media types it accepts and responds with.
When using the generic views, any OPTIONS
requests will additionally respond with metadata regarding any POST
or PUT
actions available, describing which fields are on the serializer.
diff --git a/topics/funding/index.html b/topics/funding/index.html
index b33933cb9..9a80c8607 100644
--- a/topics/funding/index.html
+++ b/topics/funding/index.html
@@ -4,7 +4,6 @@
-
Funding - Django REST framework
diff --git a/topics/html-and-forms/index.html b/topics/html-and-forms/index.html
index 0e797eba5..118ec9181 100644
--- a/topics/html-and-forms/index.html
+++ b/topics/html-and-forms/index.html
@@ -4,7 +4,6 @@
-
HTML & Forms - Django REST framework
diff --git a/topics/internationalization/index.html b/topics/internationalization/index.html
index ce72b7b8e..6a79b2a92 100644
--- a/topics/internationalization/index.html
+++ b/topics/internationalization/index.html
@@ -4,7 +4,6 @@
-
Internationalization - Django REST framework
diff --git a/topics/kickstarter-announcement/index.html b/topics/kickstarter-announcement/index.html
index a059d8c6c..b424ddbce 100644
--- a/topics/kickstarter-announcement/index.html
+++ b/topics/kickstarter-announcement/index.html
@@ -4,7 +4,6 @@
-
Kickstarter Announcement - Django REST framework
@@ -477,7 +476,7 @@
Silver sponsors
-The serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank you to individuals who have choosen to privately support the project at this level.
+The serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank you to individuals who have chosen to privately support the project at this level.
- IMT Computer Services
- Wildfish
diff --git a/topics/mozilla-grant/index.html b/topics/mozilla-grant/index.html
index 20ea73bb3..3247abd4c 100644
--- a/topics/mozilla-grant/index.html
+++ b/topics/mozilla-grant/index.html
@@ -4,7 +4,6 @@
-
Mozilla Grant - Django REST framework
diff --git a/topics/project-management/index.html b/topics/project-management/index.html
index 93244f176..a511e926d 100644
--- a/topics/project-management/index.html
+++ b/topics/project-management/index.html
@@ -4,7 +4,6 @@
-
Project management - Django REST framework
diff --git a/topics/release-notes/index.html b/topics/release-notes/index.html
index 5b132dc40..5c0b25655 100644
--- a/topics/release-notes/index.html
+++ b/topics/release-notes/index.html
@@ -4,7 +4,6 @@
-
Release Notes - Django REST framework
@@ -628,7 +627,7 @@
- Fixed use of deprecated Query.aggregates. (#4003)
- Fix blank lines around docstrings. (#4002)
- Fixed admin pagination when limit is 0. (#3990)
-- OrderingFilter adjustements. (#3983)
+- OrderingFilter adjustments. (#3983)
- Non-required serializer related fields. (#3976)
- Using safer calling way of "@api_view" in tutorial. (#3971)
- ListSerializer doesn't handle unique_together constraints. (#3970)
diff --git a/topics/rest-hypermedia-hateoas/index.html b/topics/rest-hypermedia-hateoas/index.html
index 8efc55c8e..81a5cdba7 100644
--- a/topics/rest-hypermedia-hateoas/index.html
+++ b/topics/rest-hypermedia-hateoas/index.html
@@ -4,7 +4,6 @@
-
REST, Hypermedia & HATEOAS - Django REST framework
diff --git a/topics/third-party-resources/index.html b/topics/third-party-resources/index.html
index 7b9b33335..895817289 100644
--- a/topics/third-party-resources/index.html
+++ b/topics/third-party-resources/index.html
@@ -4,7 +4,6 @@
-
Third Party Resources - Django REST framework
diff --git a/tutorial/1-serialization/index.html b/tutorial/1-serialization/index.html
index 0628bf7fa..46e49037f 100644
--- a/tutorial/1-serialization/index.html
+++ b/tutorial/1-serialization/index.html
@@ -4,7 +4,6 @@
-
1 - Serialization - Django REST framework
diff --git a/tutorial/2-requests-and-responses/index.html b/tutorial/2-requests-and-responses/index.html
index 5f77b44c1..720a6268e 100644
--- a/tutorial/2-requests-and-responses/index.html
+++ b/tutorial/2-requests-and-responses/index.html
@@ -4,7 +4,6 @@
-
2 - Requests and responses - Django REST framework
diff --git a/tutorial/3-class-based-views/index.html b/tutorial/3-class-based-views/index.html
index 262d80cd5..c5fb41a1c 100644
--- a/tutorial/3-class-based-views/index.html
+++ b/tutorial/3-class-based-views/index.html
@@ -4,7 +4,6 @@
-
3 - Class based views - Django REST framework
@@ -456,7 +455,7 @@ class SnippetList(APIView):
return Response(status=status.HTTP_204_NO_CONTENT)
That's looking good. Again, it's still pretty similar to the function based view right now.
-We'll also need to refactor our urls.py
slightly now we're using class-based views.
+We'll also need to refactor our urls.py
slightly now that we're using class-based views.
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
diff --git a/tutorial/4-authentication-and-permissions/index.html b/tutorial/4-authentication-and-permissions/index.html
index c3d3fe6d4..d932ce373 100644
--- a/tutorial/4-authentication-and-permissions/index.html
+++ b/tutorial/4-authentication-and-permissions/index.html
@@ -4,7 +4,6 @@
-
4 - Authentication and permissions - Django REST framework
diff --git a/tutorial/5-relationships-and-hyperlinked-apis/index.html b/tutorial/5-relationships-and-hyperlinked-apis/index.html
index 759154ce6..78dd2723a 100644
--- a/tutorial/5-relationships-and-hyperlinked-apis/index.html
+++ b/tutorial/5-relationships-and-hyperlinked-apis/index.html
@@ -4,7 +4,6 @@
-
5 - Relationships and hyperlinked APIs - Django REST framework
diff --git a/tutorial/6-viewsets-and-routers/index.html b/tutorial/6-viewsets-and-routers/index.html
index cc60e7978..dcbb453c1 100644
--- a/tutorial/6-viewsets-and-routers/index.html
+++ b/tutorial/6-viewsets-and-routers/index.html
@@ -4,7 +4,6 @@
-
6 - Viewsets and routers - Django REST framework
diff --git a/tutorial/7-schemas-and-client-libraries/index.html b/tutorial/7-schemas-and-client-libraries/index.html
index b3675c1f9..6a694a86f 100644
--- a/tutorial/7-schemas-and-client-libraries/index.html
+++ b/tutorial/7-schemas-and-client-libraries/index.html
@@ -4,7 +4,6 @@
-
7 - Schemas and client libraries - Django REST framework
diff --git a/tutorial/quickstart/index.html b/tutorial/quickstart/index.html
index 1ddb36a70..b42f14f6f 100644
--- a/tutorial/quickstart/index.html
+++ b/tutorial/quickstart/index.html
@@ -4,7 +4,6 @@
-
Quickstart - Django REST framework