diff --git a/api-guide/authentication/index.html b/api-guide/authentication/index.html index 6ad990e64..4588e5214 100644 --- a/api-guide/authentication/index.html +++ b/api-guide/authentication/index.html @@ -589,7 +589,7 @@ print token.key

If successfully authenticated, TokenAuthentication provides the following credentials.

Unauthenticated responses that are denied permission will result in an HTTP 401 Unauthorized response with an appropriate WWW-Authenticate header. For example:

WWW-Authenticate: Token
diff --git a/api-guide/generic-views/index.html b/api-guide/generic-views/index.html
index 019768a59..394f8aee3 100644
--- a/api-guide/generic-views/index.html
+++ b/api-guide/generic-views/index.html
@@ -727,7 +727,8 @@ class UserList(generics.ListCreateAPIView):
         queryset = self.filter_queryset(queryset)  # Apply any filter backends
         filter = {}
         for field in self.lookup_fields:
-            filter[field] = self.kwargs[field]
+            if self.kwargs[field]: # Ignore empty fields.
+                filter[field] = self.kwargs[field]
         return get_object_or_404(queryset, **filter)  # Lookup the object
 

You can then simply apply this mixin to a view or viewset anytime you need to apply the custom behavior.

diff --git a/api-guide/serializers/index.html b/api-guide/serializers/index.html index c6fd455e8..2d8c249fd 100644 --- a/api-guide/serializers/index.html +++ b/api-guide/serializers/index.html @@ -928,7 +928,7 @@ serializer.data fields = ('id', 'account_name', 'users', 'created')

By default, all the model fields on the class will be mapped to a corresponding serializer fields.

-

Any relationships such as foreign keys on the model will be mapped to PrimaryKeyRelatedField. Reverse relationships are not included by default unless explicitly included as described below.

+

Any relationships such as foreign keys on the model will be mapped to PrimaryKeyRelatedField. Reverse relationships are not included by default unless explicitly included as specified in the serializer relations documentation.

Inspecting a ModelSerializer

Serializer classes generate helpful verbose representation strings, that allow you to fully inspect the state of their fields. This is particularly useful when working with ModelSerializers where you want to determine what set of fields and validators are being automatically created for you.

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

diff --git a/api-guide/throttling/index.html b/api-guide/throttling/index.html index f1ae60cf9..3c4e4d0e6 100644 --- a/api-guide/throttling/index.html +++ b/api-guide/throttling/index.html @@ -572,7 +572,7 @@ class UploadView(APIView): class RandomRateThrottle(throttling.BaseThrottle): def allow_request(self, request, view): - return random.randint(1, 10) == 1 + return random.randint(1, 10) != 1 diff --git a/img/premium/stream-readme.png b/img/premium/stream-readme.png index a04009d7f..955c11429 100644 Binary files a/img/premium/stream-readme.png and b/img/premium/stream-readme.png differ diff --git a/mkdocs/search_index.json b/mkdocs/search_index.json index 319c89796..c7f7e9b54 100644 --- a/mkdocs/search_index.json +++ b/mkdocs/search_index.json @@ -712,7 +712,7 @@ }, { "location": "/api-guide/generic-views/", - "text": "Generic views\n\n\n\n\nDjango\u2019s generic views... were developed as a shortcut for common usage patterns... They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to repeat yourself.\n\n\n \nDjango Documentation\n\n\n\n\nOne of the key benefits of class-based views is the way they allow you to compose bits of reusable behavior. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns.\n\n\nThe generic views provided by REST framework allow you to quickly build API views that map closely to your database models.\n\n\nIf the generic views don't suit the needs of your API, you can drop down to using the regular \nAPIView\n class, or reuse the mixins and base classes used by the generic views to compose your own set of reusable generic views.\n\n\nExamples\n\n\nTypically when using the generic views, you'll override the view, and set several class attributes.\n\n\nfrom django.contrib.auth.models import User\nfrom myapp.serializers import UserSerializer\nfrom rest_framework import generics\nfrom rest_framework.permissions import IsAdminUser\n\nclass UserList(generics.ListCreateAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n permission_classes = (IsAdminUser,)\n\n\n\nFor more complex cases you might also want to override various methods on the view class. For example.\n\n\nclass UserList(generics.ListCreateAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n permission_classes = (IsAdminUser,)\n\n def list(self, request):\n # Note the use of `get_queryset()` instead of `self.queryset`\n queryset = self.get_queryset()\n serializer = UserSerializer(queryset, many=True)\n return Response(serializer.data)\n\n\n\nFor very simple cases you might want to pass through any class attributes using the \n.as_view()\n method. For example, your URLconf might include something like the following entry:\n\n\nurl(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')\n\n\n\n\n\nAPI Reference\n\n\nGenericAPIView\n\n\nThis class extends REST framework's \nAPIView\n class, adding commonly required behavior for standard list and detail views.\n\n\nEach of the concrete generic views provided is built by combining \nGenericAPIView\n, with one or more mixin classes.\n\n\nAttributes\n\n\nBasic settings\n:\n\n\nThe following attributes control the basic view behavior.\n\n\n\n\nqueryset\n - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the \nget_queryset()\n method. If you are overriding a view method, it is important that you call \nget_queryset()\n instead of accessing this property directly, as \nqueryset\n will get evaluated once, and those results will be cached for all subsequent requests.\n\n\nserializer_class\n - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the \nget_serializer_class()\n method.\n\n\nlookup_field\n - The model field that should be used to for performing object lookup of individual model instances. Defaults to \n'pk'\n. Note that when using hyperlinked APIs you'll need to ensure that \nboth\n the API views \nand\n the serializer classes set the lookup fields if you need to use a custom value.\n\n\nlookup_url_kwarg\n - The URL keyword argument that should be used for object lookup. The URL conf should include a keyword argument corresponding to this value. If unset this defaults to using the same value as \nlookup_field\n.\n\n\n\n\nPagination\n:\n\n\nThe following attributes are used to control pagination when used with list views.\n\n\n\n\npagination_class\n - The pagination class that should be used when paginating list results. Defaults to the same value as the \nDEFAULT_PAGINATION_CLASS\n setting, which is \n'rest_framework.pagination.PageNumberPagination'\n.\n\n\n\n\nFiltering\n:\n\n\n\n\nfilter_backends\n - A list of filter backend classes that should be used for filtering the queryset. Defaults to the same value as the \nDEFAULT_FILTER_BACKENDS\n setting.\n\n\n\n\nMethods\n\n\nBase methods\n:\n\n\nget_queryset(self)\n\n\nReturns the queryset that should be used for list views, and that should be used as the base for lookups in detail views. Defaults to returning the queryset specified by the \nqueryset\n attribute.\n\n\nThis method should always be used rather than accessing \nself.queryset\n directly, as \nself.queryset\n gets evaluated only once, and those results are cached for all subsequent requests.\n\n\nMay be overridden to provide dynamic behavior, such as returning a queryset, that is specific to the user making the request.\n\n\nFor example:\n\n\ndef get_queryset(self):\n user = self.request.user\n return user.accounts.all()\n\n\n\nget_object(self)\n\n\nReturns an object instance that should be used for detail views. Defaults to using the \nlookup_field\n parameter to filter the base queryset.\n\n\nMay be overridden to provide more complex behavior, such as object lookups based on more than one URL kwarg.\n\n\nFor example:\n\n\ndef get_object(self):\n queryset = self.get_queryset()\n filter = {}\n for field in self.multiple_lookup_fields:\n filter[field] = self.kwargs[field]\n\n obj = get_object_or_404(queryset, **filter)\n self.check_object_permissions(self.request, obj)\n return obj\n\n\n\nNote that if your API doesn't include any object level permissions, you may optionally exclude the \nself.check_object_permissions\n, and simply return the object from the \nget_object_or_404\n lookup.\n\n\nfilter_queryset(self, queryset)\n\n\nGiven a queryset, filter it with whichever filter backends are in use, returning a new queryset. \n\n\nFor example: \n\n\ndef filter_queryset(self, queryset):\n filter_backends = (CategoryFilter,)\n\n if 'geo_route' in self.request.query_params:\n filter_backends = (GeoRouteFilter, CategoryFilter)\n elif 'geo_point' in self.request.query_params:\n filter_backends = (GeoPointFilter, CategoryFilter)\n\n for backend in list(filter_backends):\n queryset = backend().filter_queryset(self.request, queryset, view=self)\n\n return queryset\n\n\n\nget_serializer_class(self)\n\n\nReturns the class that should be used for the serializer. Defaults to returning the \nserializer_class\n attribute.\n\n\nMay be overridden to provide dynamic behavior, such as using different serializers for read and write operations, or providing different serializers to different types of users.\n\n\nFor example:\n\n\ndef get_serializer_class(self):\n if self.request.user.is_staff:\n return FullAccountSerializer\n return BasicAccountSerializer\n\n\n\nSave and deletion hooks\n:\n\n\nThe following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior.\n\n\n\n\nperform_create(self, serializer)\n - Called by \nCreateModelMixin\n when saving a new object instance.\n\n\nperform_update(self, serializer)\n - Called by \nUpdateModelMixin\n when saving an existing object instance.\n\n\nperform_destroy(self, instance)\n - Called by \nDestroyModelMixin\n when deleting an object instance.\n\n\n\n\nThese hooks are particularly useful for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument.\n\n\ndef perform_create(self, serializer):\n serializer.save(user=self.request.user)\n\n\n\nThese override points are also particularly useful for adding behavior that occurs before or after saving an object, such as emailing a confirmation, or logging the update.\n\n\ndef perform_update(self, serializer):\n instance = serializer.save()\n send_email_confirmation(user=self.request.user, modified=instance)\n\n\n\nYou can also use these hooks to provide additional validation, by raising a \nValidationError()\n. This can be useful if you need some validation logic to apply at the point of database save. For example:\n\n\ndef perform_create(self, serializer):\n queryset = SignupRequest.objects.filter(user=self.request.user)\n if queryset.exists():\n raise ValidationError('You have already signed up')\n serializer.save(user=self.request.user)\n\n\n\nNote\n: These methods replace the old-style version 2.x \npre_save\n, \npost_save\n, \npre_delete\n and \npost_delete\n methods, which are no longer available.\n\n\nOther methods\n:\n\n\nYou won't typically need to override the following methods, although you might need to call into them if you're writing custom views using \nGenericAPIView\n.\n\n\n\n\nget_serializer_context(self)\n - Returns a dictionary containing any extra context that should be supplied to the serializer. Defaults to including \n'request'\n, \n'view'\n and \n'format'\n keys.\n\n\nget_serializer(self, instance=None, data=None, many=False, partial=False)\n - Returns a serializer instance.\n\n\nget_paginated_response(self, data)\n - Returns a paginated style \nResponse\n object.\n\n\npaginate_queryset(self, queryset)\n - Paginate a queryset if required, either returning a page object, or \nNone\n if pagination is not configured for this view.\n\n\nfilter_queryset(self, queryset)\n - Given a queryset, filter it with whichever filter backends are in use, returning a new queryset.\n\n\n\n\n\n\nMixins\n\n\nThe mixin classes provide the actions that are used to provide the basic view behavior. Note that the mixin classes provide action methods rather than defining the handler methods, such as \n.get()\n and \n.post()\n, directly. This allows for more flexible composition of behavior.\n\n\nThe mixin classes can be imported from \nrest_framework.mixins\n.\n\n\nListModelMixin\n\n\nProvides a \n.list(request, *args, **kwargs)\n method, that implements listing a queryset.\n\n\nIf the queryset is populated, this returns a \n200 OK\n response, with a serialized representation of the queryset as the body of the response. The response data may optionally be paginated.\n\n\nCreateModelMixin\n\n\nProvides a \n.create(request, *args, **kwargs)\n method, that implements creating and saving a new model instance.\n\n\nIf an object is created this returns a \n201 Created\n response, with a serialized representation of the object as the body of the response. If the representation contains a key named \nurl\n, then the \nLocation\n header of the response will be populated with that value.\n\n\nIf the request data provided for creating the object was invalid, a \n400 Bad Request\n response will be returned, with the error details as the body of the response.\n\n\nRetrieveModelMixin\n\n\nProvides a \n.retrieve(request, *args, **kwargs)\n method, that implements returning an existing model instance in a response.\n\n\nIf an object can be retrieved this returns a \n200 OK\n response, with a serialized representation of the object as the body of the response. Otherwise it will return a \n404 Not Found\n.\n\n\nUpdateModelMixin\n\n\nProvides a \n.update(request, *args, **kwargs)\n method, that implements updating and saving an existing model instance.\n\n\nAlso provides a \n.partial_update(request, *args, **kwargs)\n method, which is similar to the \nupdate\n method, except that all fields for the update will be optional. This allows support for HTTP \nPATCH\n requests.\n\n\nIf an object is updated this returns a \n200 OK\n response, with a serialized representation of the object as the body of the response.\n\n\nIf an object is created, for example when making a \nDELETE\n request followed by a \nPUT\n request to the same URL, this returns a \n201 Created\n response, with a serialized representation of the object as the body of the response.\n\n\nIf the request data provided for updating the object was invalid, a \n400 Bad Request\n response will be returned, with the error details as the body of the response.\n\n\nDestroyModelMixin\n\n\nProvides a \n.destroy(request, *args, **kwargs)\n method, that implements deletion of an existing model instance.\n\n\nIf an object is deleted this returns a \n204 No Content\n response, otherwise it will return a \n404 Not Found\n.\n\n\n\n\nConcrete View Classes\n\n\nThe following classes are the concrete generic views. If you're using generic views this is normally the level you'll be working at unless you need heavily customized behavior.\n\n\nThe view classes can be imported from \nrest_framework.generics\n.\n\n\nCreateAPIView\n\n\nUsed for \ncreate-only\n endpoints.\n\n\nProvides a \npost\n method handler.\n\n\nExtends: \nGenericAPIView\n, \nCreateModelMixin\n\n\nListAPIView\n\n\nUsed for \nread-only\n endpoints to represent a \ncollection of model instances\n.\n\n\nProvides a \nget\n method handler.\n\n\nExtends: \nGenericAPIView\n, \nListModelMixin\n\n\nRetrieveAPIView\n\n\nUsed for \nread-only\n endpoints to represent a \nsingle model instance\n.\n\n\nProvides a \nget\n method handler.\n\n\nExtends: \nGenericAPIView\n, \nRetrieveModelMixin\n\n\nDestroyAPIView\n\n\nUsed for \ndelete-only\n endpoints for a \nsingle model instance\n.\n\n\nProvides a \ndelete\n method handler.\n\n\nExtends: \nGenericAPIView\n, \nDestroyModelMixin\n\n\nUpdateAPIView\n\n\nUsed for \nupdate-only\n endpoints for a \nsingle model instance\n.\n\n\nProvides \nput\n and \npatch\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nUpdateModelMixin\n\n\nListCreateAPIView\n\n\nUsed for \nread-write\n endpoints to represent a \ncollection of model instances\n.\n\n\nProvides \nget\n and \npost\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nListModelMixin\n, \nCreateModelMixin\n\n\nRetrieveUpdateAPIView\n\n\nUsed for \nread or update\n endpoints to represent a \nsingle model instance\n.\n\n\nProvides \nget\n, \nput\n and \npatch\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nRetrieveModelMixin\n, \nUpdateModelMixin\n\n\nRetrieveDestroyAPIView\n\n\nUsed for \nread or delete\n endpoints to represent a \nsingle model instance\n.\n\n\nProvides \nget\n and \ndelete\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nRetrieveModelMixin\n, \nDestroyModelMixin\n\n\nRetrieveUpdateDestroyAPIView\n\n\nUsed for \nread-write-delete\n endpoints to represent a \nsingle model instance\n.\n\n\nProvides \nget\n, \nput\n, \npatch\n and \ndelete\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nRetrieveModelMixin\n, \nUpdateModelMixin\n, \nDestroyModelMixin\n\n\n\n\nCustomizing the generic views\n\n\nOften you'll want to use the existing generic views, but use some slightly customized behavior. If you find yourself reusing some bit of customized behavior in multiple places, you might want to refactor the behavior into a common class that you can then just apply to any view or viewset as needed.\n\n\nCreating custom mixins\n\n\nFor example, if you need to lookup objects based on multiple fields in the URL conf, you could create a mixin class like the following:\n\n\nclass MultipleFieldLookupMixin(object):\n \"\"\"\n Apply this mixin to any view or viewset to get multiple field filtering\n based on a `lookup_fields` attribute, instead of the default single field filtering.\n \"\"\"\n def get_object(self):\n queryset = self.get_queryset() # Get the base queryset\n queryset = self.filter_queryset(queryset) # Apply any filter backends\n filter = {}\n for field in self.lookup_fields:\n filter[field] = self.kwargs[field]\n return get_object_or_404(queryset, **filter) # Lookup the object\n\n\n\nYou can then simply apply this mixin to a view or viewset anytime you need to apply the custom behavior.\n\n\nclass RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n lookup_fields = ('account', 'username')\n\n\n\nUsing custom mixins is a good option if you have custom behavior that needs to be used.\n\n\nCreating custom base classes\n\n\nIf you are using a mixin across multiple views, you can take this a step further and create your own set of base views that can then be used throughout your project. For example:\n\n\nclass BaseRetrieveView(MultipleFieldLookupMixin,\n generics.RetrieveAPIView):\n pass\n\nclass BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,\n generics.RetrieveUpdateDestroyAPIView):\n pass\n\n\n\nUsing custom base classes is a good option if you have custom behavior that consistently needs to be repeated across a large number of views throughout your project.\n\n\n\n\nPUT as create\n\n\nPrior to version 3.0 the REST framework mixins treated \nPUT\n as either an update or a create operation, depending on if the object already existed or not.\n\n\nAllowing \nPUT\n as create operations is problematic, as it necessarily exposes information about the existence or non-existence of objects. It's also not obvious that transparently allowing re-creating of previously deleted instances is necessarily a better default behavior than simply returning \n404\n responses.\n\n\nBoth styles \"\nPUT\n as 404\" and \"\nPUT\n as create\" can be valid in different circumstances, but from version 3.0 onwards we now use 404 behavior as the default, due to it being simpler and more obvious.\n\n\nIf you need to generic PUT-as-create behavior you may want to include something like \nthis \nAllowPUTAsCreateMixin\n class\n as a mixin to your views.\n\n\n\n\nThird party packages\n\n\nThe following third party packages provide additional generic view implementations.\n\n\nDjango REST Framework bulk\n\n\nThe \ndjango-rest-framework-bulk package\n implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.\n\n\nDjango Rest Multiple Models\n\n\nDjango Rest Multiple Models\n provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.", + "text": "Generic views\n\n\n\n\nDjango\u2019s generic views... were developed as a shortcut for common usage patterns... They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to repeat yourself.\n\n\n \nDjango Documentation\n\n\n\n\nOne of the key benefits of class-based views is the way they allow you to compose bits of reusable behavior. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns.\n\n\nThe generic views provided by REST framework allow you to quickly build API views that map closely to your database models.\n\n\nIf the generic views don't suit the needs of your API, you can drop down to using the regular \nAPIView\n class, or reuse the mixins and base classes used by the generic views to compose your own set of reusable generic views.\n\n\nExamples\n\n\nTypically when using the generic views, you'll override the view, and set several class attributes.\n\n\nfrom django.contrib.auth.models import User\nfrom myapp.serializers import UserSerializer\nfrom rest_framework import generics\nfrom rest_framework.permissions import IsAdminUser\n\nclass UserList(generics.ListCreateAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n permission_classes = (IsAdminUser,)\n\n\n\nFor more complex cases you might also want to override various methods on the view class. For example.\n\n\nclass UserList(generics.ListCreateAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n permission_classes = (IsAdminUser,)\n\n def list(self, request):\n # Note the use of `get_queryset()` instead of `self.queryset`\n queryset = self.get_queryset()\n serializer = UserSerializer(queryset, many=True)\n return Response(serializer.data)\n\n\n\nFor very simple cases you might want to pass through any class attributes using the \n.as_view()\n method. For example, your URLconf might include something like the following entry:\n\n\nurl(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')\n\n\n\n\n\nAPI Reference\n\n\nGenericAPIView\n\n\nThis class extends REST framework's \nAPIView\n class, adding commonly required behavior for standard list and detail views.\n\n\nEach of the concrete generic views provided is built by combining \nGenericAPIView\n, with one or more mixin classes.\n\n\nAttributes\n\n\nBasic settings\n:\n\n\nThe following attributes control the basic view behavior.\n\n\n\n\nqueryset\n - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the \nget_queryset()\n method. If you are overriding a view method, it is important that you call \nget_queryset()\n instead of accessing this property directly, as \nqueryset\n will get evaluated once, and those results will be cached for all subsequent requests.\n\n\nserializer_class\n - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the \nget_serializer_class()\n method.\n\n\nlookup_field\n - The model field that should be used to for performing object lookup of individual model instances. Defaults to \n'pk'\n. Note that when using hyperlinked APIs you'll need to ensure that \nboth\n the API views \nand\n the serializer classes set the lookup fields if you need to use a custom value.\n\n\nlookup_url_kwarg\n - The URL keyword argument that should be used for object lookup. The URL conf should include a keyword argument corresponding to this value. If unset this defaults to using the same value as \nlookup_field\n.\n\n\n\n\nPagination\n:\n\n\nThe following attributes are used to control pagination when used with list views.\n\n\n\n\npagination_class\n - The pagination class that should be used when paginating list results. Defaults to the same value as the \nDEFAULT_PAGINATION_CLASS\n setting, which is \n'rest_framework.pagination.PageNumberPagination'\n.\n\n\n\n\nFiltering\n:\n\n\n\n\nfilter_backends\n - A list of filter backend classes that should be used for filtering the queryset. Defaults to the same value as the \nDEFAULT_FILTER_BACKENDS\n setting.\n\n\n\n\nMethods\n\n\nBase methods\n:\n\n\nget_queryset(self)\n\n\nReturns the queryset that should be used for list views, and that should be used as the base for lookups in detail views. Defaults to returning the queryset specified by the \nqueryset\n attribute.\n\n\nThis method should always be used rather than accessing \nself.queryset\n directly, as \nself.queryset\n gets evaluated only once, and those results are cached for all subsequent requests.\n\n\nMay be overridden to provide dynamic behavior, such as returning a queryset, that is specific to the user making the request.\n\n\nFor example:\n\n\ndef get_queryset(self):\n user = self.request.user\n return user.accounts.all()\n\n\n\nget_object(self)\n\n\nReturns an object instance that should be used for detail views. Defaults to using the \nlookup_field\n parameter to filter the base queryset.\n\n\nMay be overridden to provide more complex behavior, such as object lookups based on more than one URL kwarg.\n\n\nFor example:\n\n\ndef get_object(self):\n queryset = self.get_queryset()\n filter = {}\n for field in self.multiple_lookup_fields:\n filter[field] = self.kwargs[field]\n\n obj = get_object_or_404(queryset, **filter)\n self.check_object_permissions(self.request, obj)\n return obj\n\n\n\nNote that if your API doesn't include any object level permissions, you may optionally exclude the \nself.check_object_permissions\n, and simply return the object from the \nget_object_or_404\n lookup.\n\n\nfilter_queryset(self, queryset)\n\n\nGiven a queryset, filter it with whichever filter backends are in use, returning a new queryset. \n\n\nFor example: \n\n\ndef filter_queryset(self, queryset):\n filter_backends = (CategoryFilter,)\n\n if 'geo_route' in self.request.query_params:\n filter_backends = (GeoRouteFilter, CategoryFilter)\n elif 'geo_point' in self.request.query_params:\n filter_backends = (GeoPointFilter, CategoryFilter)\n\n for backend in list(filter_backends):\n queryset = backend().filter_queryset(self.request, queryset, view=self)\n\n return queryset\n\n\n\nget_serializer_class(self)\n\n\nReturns the class that should be used for the serializer. Defaults to returning the \nserializer_class\n attribute.\n\n\nMay be overridden to provide dynamic behavior, such as using different serializers for read and write operations, or providing different serializers to different types of users.\n\n\nFor example:\n\n\ndef get_serializer_class(self):\n if self.request.user.is_staff:\n return FullAccountSerializer\n return BasicAccountSerializer\n\n\n\nSave and deletion hooks\n:\n\n\nThe following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior.\n\n\n\n\nperform_create(self, serializer)\n - Called by \nCreateModelMixin\n when saving a new object instance.\n\n\nperform_update(self, serializer)\n - Called by \nUpdateModelMixin\n when saving an existing object instance.\n\n\nperform_destroy(self, instance)\n - Called by \nDestroyModelMixin\n when deleting an object instance.\n\n\n\n\nThese hooks are particularly useful for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument.\n\n\ndef perform_create(self, serializer):\n serializer.save(user=self.request.user)\n\n\n\nThese override points are also particularly useful for adding behavior that occurs before or after saving an object, such as emailing a confirmation, or logging the update.\n\n\ndef perform_update(self, serializer):\n instance = serializer.save()\n send_email_confirmation(user=self.request.user, modified=instance)\n\n\n\nYou can also use these hooks to provide additional validation, by raising a \nValidationError()\n. This can be useful if you need some validation logic to apply at the point of database save. For example:\n\n\ndef perform_create(self, serializer):\n queryset = SignupRequest.objects.filter(user=self.request.user)\n if queryset.exists():\n raise ValidationError('You have already signed up')\n serializer.save(user=self.request.user)\n\n\n\nNote\n: These methods replace the old-style version 2.x \npre_save\n, \npost_save\n, \npre_delete\n and \npost_delete\n methods, which are no longer available.\n\n\nOther methods\n:\n\n\nYou won't typically need to override the following methods, although you might need to call into them if you're writing custom views using \nGenericAPIView\n.\n\n\n\n\nget_serializer_context(self)\n - Returns a dictionary containing any extra context that should be supplied to the serializer. Defaults to including \n'request'\n, \n'view'\n and \n'format'\n keys.\n\n\nget_serializer(self, instance=None, data=None, many=False, partial=False)\n - Returns a serializer instance.\n\n\nget_paginated_response(self, data)\n - Returns a paginated style \nResponse\n object.\n\n\npaginate_queryset(self, queryset)\n - Paginate a queryset if required, either returning a page object, or \nNone\n if pagination is not configured for this view.\n\n\nfilter_queryset(self, queryset)\n - Given a queryset, filter it with whichever filter backends are in use, returning a new queryset.\n\n\n\n\n\n\nMixins\n\n\nThe mixin classes provide the actions that are used to provide the basic view behavior. Note that the mixin classes provide action methods rather than defining the handler methods, such as \n.get()\n and \n.post()\n, directly. This allows for more flexible composition of behavior.\n\n\nThe mixin classes can be imported from \nrest_framework.mixins\n.\n\n\nListModelMixin\n\n\nProvides a \n.list(request, *args, **kwargs)\n method, that implements listing a queryset.\n\n\nIf the queryset is populated, this returns a \n200 OK\n response, with a serialized representation of the queryset as the body of the response. The response data may optionally be paginated.\n\n\nCreateModelMixin\n\n\nProvides a \n.create(request, *args, **kwargs)\n method, that implements creating and saving a new model instance.\n\n\nIf an object is created this returns a \n201 Created\n response, with a serialized representation of the object as the body of the response. If the representation contains a key named \nurl\n, then the \nLocation\n header of the response will be populated with that value.\n\n\nIf the request data provided for creating the object was invalid, a \n400 Bad Request\n response will be returned, with the error details as the body of the response.\n\n\nRetrieveModelMixin\n\n\nProvides a \n.retrieve(request, *args, **kwargs)\n method, that implements returning an existing model instance in a response.\n\n\nIf an object can be retrieved this returns a \n200 OK\n response, with a serialized representation of the object as the body of the response. Otherwise it will return a \n404 Not Found\n.\n\n\nUpdateModelMixin\n\n\nProvides a \n.update(request, *args, **kwargs)\n method, that implements updating and saving an existing model instance.\n\n\nAlso provides a \n.partial_update(request, *args, **kwargs)\n method, which is similar to the \nupdate\n method, except that all fields for the update will be optional. This allows support for HTTP \nPATCH\n requests.\n\n\nIf an object is updated this returns a \n200 OK\n response, with a serialized representation of the object as the body of the response.\n\n\nIf an object is created, for example when making a \nDELETE\n request followed by a \nPUT\n request to the same URL, this returns a \n201 Created\n response, with a serialized representation of the object as the body of the response.\n\n\nIf the request data provided for updating the object was invalid, a \n400 Bad Request\n response will be returned, with the error details as the body of the response.\n\n\nDestroyModelMixin\n\n\nProvides a \n.destroy(request, *args, **kwargs)\n method, that implements deletion of an existing model instance.\n\n\nIf an object is deleted this returns a \n204 No Content\n response, otherwise it will return a \n404 Not Found\n.\n\n\n\n\nConcrete View Classes\n\n\nThe following classes are the concrete generic views. If you're using generic views this is normally the level you'll be working at unless you need heavily customized behavior.\n\n\nThe view classes can be imported from \nrest_framework.generics\n.\n\n\nCreateAPIView\n\n\nUsed for \ncreate-only\n endpoints.\n\n\nProvides a \npost\n method handler.\n\n\nExtends: \nGenericAPIView\n, \nCreateModelMixin\n\n\nListAPIView\n\n\nUsed for \nread-only\n endpoints to represent a \ncollection of model instances\n.\n\n\nProvides a \nget\n method handler.\n\n\nExtends: \nGenericAPIView\n, \nListModelMixin\n\n\nRetrieveAPIView\n\n\nUsed for \nread-only\n endpoints to represent a \nsingle model instance\n.\n\n\nProvides a \nget\n method handler.\n\n\nExtends: \nGenericAPIView\n, \nRetrieveModelMixin\n\n\nDestroyAPIView\n\n\nUsed for \ndelete-only\n endpoints for a \nsingle model instance\n.\n\n\nProvides a \ndelete\n method handler.\n\n\nExtends: \nGenericAPIView\n, \nDestroyModelMixin\n\n\nUpdateAPIView\n\n\nUsed for \nupdate-only\n endpoints for a \nsingle model instance\n.\n\n\nProvides \nput\n and \npatch\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nUpdateModelMixin\n\n\nListCreateAPIView\n\n\nUsed for \nread-write\n endpoints to represent a \ncollection of model instances\n.\n\n\nProvides \nget\n and \npost\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nListModelMixin\n, \nCreateModelMixin\n\n\nRetrieveUpdateAPIView\n\n\nUsed for \nread or update\n endpoints to represent a \nsingle model instance\n.\n\n\nProvides \nget\n, \nput\n and \npatch\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nRetrieveModelMixin\n, \nUpdateModelMixin\n\n\nRetrieveDestroyAPIView\n\n\nUsed for \nread or delete\n endpoints to represent a \nsingle model instance\n.\n\n\nProvides \nget\n and \ndelete\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nRetrieveModelMixin\n, \nDestroyModelMixin\n\n\nRetrieveUpdateDestroyAPIView\n\n\nUsed for \nread-write-delete\n endpoints to represent a \nsingle model instance\n.\n\n\nProvides \nget\n, \nput\n, \npatch\n and \ndelete\n method handlers.\n\n\nExtends: \nGenericAPIView\n, \nRetrieveModelMixin\n, \nUpdateModelMixin\n, \nDestroyModelMixin\n\n\n\n\nCustomizing the generic views\n\n\nOften you'll want to use the existing generic views, but use some slightly customized behavior. If you find yourself reusing some bit of customized behavior in multiple places, you might want to refactor the behavior into a common class that you can then just apply to any view or viewset as needed.\n\n\nCreating custom mixins\n\n\nFor example, if you need to lookup objects based on multiple fields in the URL conf, you could create a mixin class like the following:\n\n\nclass MultipleFieldLookupMixin(object):\n \"\"\"\n Apply this mixin to any view or viewset to get multiple field filtering\n based on a `lookup_fields` attribute, instead of the default single field filtering.\n \"\"\"\n def get_object(self):\n queryset = self.get_queryset() # Get the base queryset\n queryset = self.filter_queryset(queryset) # Apply any filter backends\n filter = {}\n for field in self.lookup_fields:\n if self.kwargs[field]: # Ignore empty fields.\n filter[field] = self.kwargs[field]\n return get_object_or_404(queryset, **filter) # Lookup the object\n\n\n\nYou can then simply apply this mixin to a view or viewset anytime you need to apply the custom behavior.\n\n\nclass RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n lookup_fields = ('account', 'username')\n\n\n\nUsing custom mixins is a good option if you have custom behavior that needs to be used.\n\n\nCreating custom base classes\n\n\nIf you are using a mixin across multiple views, you can take this a step further and create your own set of base views that can then be used throughout your project. For example:\n\n\nclass BaseRetrieveView(MultipleFieldLookupMixin,\n generics.RetrieveAPIView):\n pass\n\nclass BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,\n generics.RetrieveUpdateDestroyAPIView):\n pass\n\n\n\nUsing custom base classes is a good option if you have custom behavior that consistently needs to be repeated across a large number of views throughout your project.\n\n\n\n\nPUT as create\n\n\nPrior to version 3.0 the REST framework mixins treated \nPUT\n as either an update or a create operation, depending on if the object already existed or not.\n\n\nAllowing \nPUT\n as create operations is problematic, as it necessarily exposes information about the existence or non-existence of objects. It's also not obvious that transparently allowing re-creating of previously deleted instances is necessarily a better default behavior than simply returning \n404\n responses.\n\n\nBoth styles \"\nPUT\n as 404\" and \"\nPUT\n as create\" can be valid in different circumstances, but from version 3.0 onwards we now use 404 behavior as the default, due to it being simpler and more obvious.\n\n\nIf you need to generic PUT-as-create behavior you may want to include something like \nthis \nAllowPUTAsCreateMixin\n class\n as a mixin to your views.\n\n\n\n\nThird party packages\n\n\nThe following third party packages provide additional generic view implementations.\n\n\nDjango REST Framework bulk\n\n\nThe \ndjango-rest-framework-bulk package\n implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.\n\n\nDjango Rest Multiple Models\n\n\nDjango Rest Multiple Models\n provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.", "title": "Generic views" }, { @@ -852,7 +852,7 @@ }, { "location": "/api-guide/generic-views/#creating-custom-mixins", - "text": "For example, if you need to lookup objects based on multiple fields in the URL conf, you could create a mixin class like the following: class MultipleFieldLookupMixin(object):\n \"\"\"\n Apply this mixin to any view or viewset to get multiple field filtering\n based on a `lookup_fields` attribute, instead of the default single field filtering.\n \"\"\"\n def get_object(self):\n queryset = self.get_queryset() # Get the base queryset\n queryset = self.filter_queryset(queryset) # Apply any filter backends\n filter = {}\n for field in self.lookup_fields:\n filter[field] = self.kwargs[field]\n return get_object_or_404(queryset, **filter) # Lookup the object You can then simply apply this mixin to a view or viewset anytime you need to apply the custom behavior. class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n lookup_fields = ('account', 'username') Using custom mixins is a good option if you have custom behavior that needs to be used.", + "text": "For example, if you need to lookup objects based on multiple fields in the URL conf, you could create a mixin class like the following: class MultipleFieldLookupMixin(object):\n \"\"\"\n Apply this mixin to any view or viewset to get multiple field filtering\n based on a `lookup_fields` attribute, instead of the default single field filtering.\n \"\"\"\n def get_object(self):\n queryset = self.get_queryset() # Get the base queryset\n queryset = self.filter_queryset(queryset) # Apply any filter backends\n filter = {}\n for field in self.lookup_fields:\n if self.kwargs[field]: # Ignore empty fields.\n filter[field] = self.kwargs[field]\n return get_object_or_404(queryset, **filter) # Lookup the object You can then simply apply this mixin to a view or viewset anytime you need to apply the custom behavior. class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):\n queryset = User.objects.all()\n serializer_class = UserSerializer\n lookup_fields = ('account', 'username') Using custom mixins is a good option if you have custom behavior that needs to be used.", "title": "Creating custom mixins" }, { @@ -1332,7 +1332,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 described below.\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\nInheritance of the 'Meta' class\n\n\nThe inner \nMeta\n class on serializers is not inherited from parent classes by default. This is the same behavior as with Django's \nModel\n and \nModelForm\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\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\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\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.", + "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\nInheritance of the 'Meta' class\n\n\nThe inner \nMeta\n class on serializers is not inherited from parent classes by default. This is the same behavior as with Django's \nModel\n and \nModelForm\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\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\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\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.", "title": "Serializers" }, { @@ -1452,7 +1452,7 @@ }, { "location": "/api-guide/serializers/#modelserializer", - "text": "Often you'll want serializer classes that map closely to Django model definitions. The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields. The ModelSerializer class is the same as a regular Serializer class, except that : It will automatically generate a set of fields for you, based on the model. It will automatically generate validators for the serializer, such as unique_together validators. It includes simple default implementations of .create() and .update() . Declaring a ModelSerializer looks like this: class AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created') By default, all the model fields on the class will be mapped to a corresponding serializer fields. Any relationships such as foreign keys on the model will be mapped to PrimaryKeyRelatedField . Reverse relationships are not included by default unless explicitly included as described below.", + "text": "Often you'll want serializer classes that map closely to Django model definitions. The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields. The ModelSerializer class is the same as a regular Serializer class, except that : It will automatically generate a set of fields for you, based on the model. It will automatically generate validators for the serializer, such as unique_together validators. It includes simple default implementations of .create() and .update() . Declaring a ModelSerializer looks like this: class AccountSerializer(serializers.ModelSerializer):\n class Meta:\n model = Account\n fields = ('id', 'account_name', 'users', 'created') By default, all the model fields on the class will be mapped to a corresponding serializer fields. Any relationships such as foreign keys on the model will be mapped to PrimaryKeyRelatedField . Reverse relationships are not included by default unless explicitly included as specified in the serializer relations documentation.", "title": "ModelSerializer" }, { @@ -2277,7 +2277,7 @@ }, { "location": "/api-guide/authentication/", - "text": "Authentication\n\n\n\n\nAuth needs to be pluggable.\n\n\n Jacob Kaplan-Moss, \n\"REST worst practices\"\n\n\n\n\nAuthentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The \npermission\n and \nthrottling\n policies can then use those credentials to determine if the request should be permitted.\n\n\nREST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes.\n\n\nAuthentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.\n\n\nThe \nrequest.user\n property will typically be set to an instance of the \ncontrib.auth\n package's \nUser\n class.\n\n\nThe \nrequest.auth\n property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.\n\n\n\n\nNote:\n Don't forget that \nauthentication by itself won't allow or disallow an incoming request\n, it simply identifies the credentials that the request was made with.\n\n\nFor information on how to setup the permission polices for your API please see the \npermissions documentation\n.\n\n\n\n\nHow authentication is determined\n\n\nThe authentication schemes are always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set \nrequest.user\n and \nrequest.auth\n using the return value of the first class that successfully authenticates.\n\n\nIf no class authenticates, \nrequest.user\n will be set to an instance of \ndjango.contrib.auth.models.AnonymousUser\n, and \nrequest.auth\n will be set to \nNone\n.\n\n\nThe value of \nrequest.user\n and \nrequest.auth\n for unauthenticated requests can be modified using the \nUNAUTHENTICATED_USER\n and \nUNAUTHENTICATED_TOKEN\n settings.\n\n\nSetting the authentication scheme\n\n\nThe default authentication schemes may be set globally, using the \nDEFAULT_AUTHENTICATION_CLASSES\n setting. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_AUTHENTICATION_CLASSES': (\n 'rest_framework.authentication.BasicAuthentication',\n 'rest_framework.authentication.SessionAuthentication',\n )\n}\n\n\n\nYou can also set the authentication scheme on a per-view or per-viewset basis,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.authentication import SessionAuthentication, BasicAuthentication\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n authentication_classes = (SessionAuthentication, BasicAuthentication)\n permission_classes = (IsAuthenticated,)\n\n def get(self, request, format=None):\n content = {\n 'user': unicode(request.user), # `django.contrib.auth.User` instance.\n 'auth': unicode(request.auth), # None\n }\n return Response(content)\n\n\n\nOr, if you're using the \n@api_view\n decorator with function based views.\n\n\n@api_view(['GET'])\n@authentication_classes((SessionAuthentication, BasicAuthentication))\n@permission_classes((IsAuthenticated,))\ndef example_view(request, format=None):\n content = {\n 'user': unicode(request.user), # `django.contrib.auth.User` instance.\n 'auth': unicode(request.auth), # None\n }\n return Response(content)\n\n\n\nUnauthorized and Forbidden responses\n\n\nWhen an unauthenticated request is denied permission there are two different error codes that may be appropriate.\n\n\n\n\nHTTP 401 Unauthorized\n\n\nHTTP 403 Permission Denied\n\n\n\n\nHTTP 401 responses must always include a \nWWW-Authenticate\n header, that instructs the client how to authenticate. HTTP 403 responses do not include the \nWWW-Authenticate\n header.\n\n\nThe kind of response that will be used depends on the authentication scheme. Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. \nThe first authentication class set on the view is used when determining the type of response\n.\n\n\nNote that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a \n403 Permission Denied\n response will always be used, regardless of the authentication scheme.\n\n\nApache mod_wsgi specific configuration\n\n\nNote that if deploying to \nApache using mod_wsgi\n, the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level.\n\n\nIf you are deploying to Apache, and using any non-session based authentication, you will need to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the \nWSGIPassAuthorization\n directive in the appropriate context and setting it to \n'On'\n.\n\n\n# this can go in either server config, virtual host, directory or .htaccess\nWSGIPassAuthorization On\n\n\n\n\n\nAPI Reference\n\n\nBasicAuthentication\n\n\nThis authentication scheme uses \nHTTP Basic Authentication\n, signed against a user's username and password. Basic authentication is generally only appropriate for testing.\n\n\nIf successfully authenticated, \nBasicAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be \nNone\n.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 401 Unauthorized\n response with an appropriate WWW-Authenticate header. For example:\n\n\nWWW-Authenticate: Basic realm=\"api\"\n\n\n\nNote:\n If you use \nBasicAuthentication\n in production you must ensure that your API is only available over \nhttps\n. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.\n\n\nTokenAuthentication\n\n\nThis authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.\n\n\nTo use the \nTokenAuthentication\n scheme you'll need to \nconfigure the authentication classes\n to include \nTokenAuthentication\n, and additionally include \nrest_framework.authtoken\n in your \nINSTALLED_APPS\n setting:\n\n\nINSTALLED_APPS = (\n ...\n 'rest_framework.authtoken'\n)\n\n\n\n\n\nNote:\n Make sure to run \nmanage.py migrate\n after changing your settings. The \nrest_framework.authtoken\n app provides Django database migrations.\n\n\n\n\nYou'll also need to create tokens for your users.\n\n\nfrom rest_framework.authtoken.models import Token\n\ntoken = Token.objects.create(user=...)\nprint token.key\n\n\n\nFor clients to authenticate, the token key should be included in the \nAuthorization\n HTTP header. The key should be prefixed by the string literal \"Token\", with whitespace separating the two strings. For example:\n\n\nAuthorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b\n\n\n\nNote:\n If you want to use a different keyword in the header, such as \nBearer\n, simply subclass \nTokenAuthentication\n and set the \nkeyword\n class variable.\n\n\nIf successfully authenticated, \nTokenAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be a \nrest_framework.authtoken.models.BasicToken\n instance.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 401 Unauthorized\n response with an appropriate WWW-Authenticate header. For example:\n\n\nWWW-Authenticate: Token\n\n\n\nThe \ncurl\n command line tool may be useful for testing token authenticated APIs. For example:\n\n\ncurl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'\n\n\n\n\n\nNote:\n If you use \nTokenAuthentication\n in production you must ensure that your API is only available over \nhttps\n.\n\n\n\n\nGenerating Tokens\n\n\nBy using signals\n\n\nIf you want every user to have an automatically generated Token, you can simply catch the User's \npost_save\n signal.\n\n\nfrom django.conf import settings\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\nfrom rest_framework.authtoken.models import Token\n\n@receiver(post_save, sender=settings.AUTH_USER_MODEL)\ndef create_auth_token(sender, instance=None, created=False, **kwargs):\n if created:\n Token.objects.create(user=instance)\n\n\n\nNote that you'll want to ensure you place this code snippet in an installed \nmodels.py\n module, or some other location that will be imported by Django on startup.\n\n\nIf you've already created some users, you can generate tokens for all existing users like this:\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework.authtoken.models import Token\n\nfor user in User.objects.all():\n Token.objects.get_or_create(user=user)\n\n\n\nBy exposing an api endpoint\n\n\nWhen using \nTokenAuthentication\n, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the \nobtain_auth_token\n view to your URLconf:\n\n\nfrom rest_framework.authtoken import views\nurlpatterns += [\n url(r'^api-token-auth/', views.obtain_auth_token)\n]\n\n\n\nNote that the URL part of the pattern can be whatever you want to use.\n\n\nThe \nobtain_auth_token\n view will return a JSON response when valid \nusername\n and \npassword\n fields are POSTed to the view using form data or JSON:\n\n\n{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }\n\n\n\nNote that the default \nobtain_auth_token\n view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the \nobtain_auth_token\n view, you can do so by overriding the \nObtainAuthToken\n view class, and using that in your url conf instead.\n\n\nBy default there are no permissions or throttling applied to the \nobtain_auth_token\n view. If you do wish to apply throttling you'll need to override the view class,\nand include them using the \nthrottle_classes\n attribute.\n\n\nWith Django admin\n\n\nIt is also possible to create Tokens manually through admin interface. In case you are using a large user base, we recommend that you monkey patch the \nTokenAdmin\n class to customize it to your needs, more specifically by declaring the \nuser\n field as \nraw_field\n.\n\n\nyour_app/admin.py\n:\n\n\nfrom rest_framework.authtoken.admin import TokenAdmin\n\nTokenAdmin.raw_id_fields = ('user',)\n\n\n\nSessionAuthentication\n\n\nThis authentication scheme uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website.\n\n\nIf successfully authenticated, \nSessionAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be \nNone\n.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 403 Forbidden\n response.\n\n\nIf you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any \"unsafe\" HTTP method calls, such as \nPUT\n, \nPATCH\n, \nPOST\n or \nDELETE\n requests. See the \nDjango CSRF documentation\n for more details.\n\n\nWarning\n: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.\n\n\nCSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.\n\n\nCustom authentication\n\n\nTo implement a custom authentication scheme, subclass \nBaseAuthentication\n and override the \n.authenticate(self, request)\n method. The method should return a two-tuple of \n(user, auth)\n if authentication succeeds, or \nNone\n otherwise.\n\n\nIn some circumstances instead of returning \nNone\n, you may want to raise an \nAuthenticationFailed\n exception from the \n.authenticate()\n method.\n\n\nTypically the approach you should take is:\n\n\n\n\nIf authentication is not attempted, return \nNone\n. Any other authentication schemes also in use will still be checked.\n\n\nIf authentication is attempted but fails, raise a \nAuthenticationFailed\n exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes.\n\n\n\n\nYou \nmay\n also override the \n.authenticate_header(self, request)\n method. If implemented, it should return a string that will be used as the value of the \nWWW-Authenticate\n header in a \nHTTP 401 Unauthorized\n response.\n\n\nIf the \n.authenticate_header()\n method is not overridden, the authentication scheme will return \nHTTP 403 Forbidden\n responses when an unauthenticated request is denied access.\n\n\nExample\n\n\nThe following example will authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'.\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework import authentication\nfrom rest_framework import exceptions\n\nclass ExampleAuthentication(authentication.BaseAuthentication):\n def authenticate(self, request):\n username = request.META.get('X_USERNAME')\n if not username:\n return None\n\n try:\n user = User.objects.get(username=username)\n except User.DoesNotExist:\n raise exceptions.AuthenticationFailed('No such user')\n\n return (user, None)\n\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nDjango OAuth Toolkit\n\n\nThe \nDjango OAuth Toolkit\n package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by \nEvonove\n and uses the excellent \nOAuthLib\n. The package is well documented, and well supported and is currently our \nrecommended package for OAuth 2.0 support\n.\n\n\nInstallation \n configuration\n\n\nInstall using \npip\n.\n\n\npip install django-oauth-toolkit\n\n\n\nAdd the package to your \nINSTALLED_APPS\n and modify your REST framework settings.\n\n\nINSTALLED_APPS = (\n ...\n 'oauth2_provider',\n)\n\nREST_FRAMEWORK = {\n 'DEFAULT_AUTHENTICATION_CLASSES': (\n 'oauth2_provider.ext.rest_framework.OAuth2Authentication',\n )\n}\n\n\n\nFor more details see the \nDjango REST framework - Getting started\n documentation.\n\n\nDjango REST framework OAuth\n\n\nThe \nDjango REST framework OAuth\n package provides both OAuth1 and OAuth2 support for REST framework.\n\n\nThis package was previously included directly in REST framework but is now supported and maintained as a third party package.\n\n\nInstallation \n configuration\n\n\nInstall the package using \npip\n.\n\n\npip install djangorestframework-oauth\n\n\n\nFor details on configuration and usage see the Django REST framework OAuth documentation for \nauthentication\n and \npermissions\n.\n\n\nDigest Authentication\n\n\nHTTP digest authentication is a widely implemented scheme that was intended to replace HTTP basic authentication, and which provides a simple encrypted authentication mechanism. \nJuan Riaza\n maintains the \ndjangorestframework-digestauth\n package which provides HTTP digest authentication support for REST framework.\n\n\nDjango OAuth2 Consumer\n\n\nThe \nDjango OAuth2 Consumer\n library from \nRediker Software\n is another package that provides \nOAuth 2.0 support for REST framework\n. The package includes token scoping permissions on tokens, which allows finer-grained access to your API.\n\n\nJSON Web Token Authentication\n\n\nJSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. \nBlimp\n maintains the \ndjangorestframework-jwt\n package which provides a JWT Authentication class as well as a mechanism for clients to obtain a JWT given the username and password.\n\n\nHawk HTTP Authentication\n\n\nThe \nHawkREST\n library builds on the \nMohawk\n library to let you work with \nHawk\n signed requests and responses in your API. \nHawk\n lets two parties securely communicate with each other using messages signed by a shared key. It is based on \nHTTP MAC access authentication\n (which was based on parts of \nOAuth 1.0\n).\n\n\nHTTP Signature Authentication\n\n\nHTTP Signature (currently a \nIETF draft\n) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to \nAmazon's HTTP Signature scheme\n, used by many of its services, it permits stateless, per-request authentication. \nElvio Toccalino\n maintains the \ndjangorestframework-httpsignature\n package which provides an easy to use HTTP Signature Authentication mechanism.\n\n\nDjoser\n\n\nDjoser\n library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and it uses token based authentication. This is a ready to use REST implementation of Django authentication system.\n\n\ndjango-rest-auth\n\n\nDjango-rest-auth\n library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.\n\n\ndjango-rest-framework-social-oauth2\n\n\nDjango-rest-framework-social-oauth2\n library provides an easy way to integrate social plugins (facebook, twitter, google, etc.) to your authentication system and an easy oauth2 setup. With this library, you will be able to authenticate users based on external tokens (e.g. facebook access token), convert these tokens to \"in-house\" oauth2 tokens and use and generate oauth2 tokens to authenticate your users.\n\n\ndjango-rest-knox\n\n\nDjango-rest-knox\n library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).", + "text": "Authentication\n\n\n\n\nAuth needs to be pluggable.\n\n\n Jacob Kaplan-Moss, \n\"REST worst practices\"\n\n\n\n\nAuthentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The \npermission\n and \nthrottling\n policies can then use those credentials to determine if the request should be permitted.\n\n\nREST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes.\n\n\nAuthentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.\n\n\nThe \nrequest.user\n property will typically be set to an instance of the \ncontrib.auth\n package's \nUser\n class.\n\n\nThe \nrequest.auth\n property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.\n\n\n\n\nNote:\n Don't forget that \nauthentication by itself won't allow or disallow an incoming request\n, it simply identifies the credentials that the request was made with.\n\n\nFor information on how to setup the permission polices for your API please see the \npermissions documentation\n.\n\n\n\n\nHow authentication is determined\n\n\nThe authentication schemes are always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set \nrequest.user\n and \nrequest.auth\n using the return value of the first class that successfully authenticates.\n\n\nIf no class authenticates, \nrequest.user\n will be set to an instance of \ndjango.contrib.auth.models.AnonymousUser\n, and \nrequest.auth\n will be set to \nNone\n.\n\n\nThe value of \nrequest.user\n and \nrequest.auth\n for unauthenticated requests can be modified using the \nUNAUTHENTICATED_USER\n and \nUNAUTHENTICATED_TOKEN\n settings.\n\n\nSetting the authentication scheme\n\n\nThe default authentication schemes may be set globally, using the \nDEFAULT_AUTHENTICATION_CLASSES\n setting. For example.\n\n\nREST_FRAMEWORK = {\n 'DEFAULT_AUTHENTICATION_CLASSES': (\n 'rest_framework.authentication.BasicAuthentication',\n 'rest_framework.authentication.SessionAuthentication',\n )\n}\n\n\n\nYou can also set the authentication scheme on a per-view or per-viewset basis,\nusing the \nAPIView\n class-based views.\n\n\nfrom rest_framework.authentication import SessionAuthentication, BasicAuthentication\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nclass ExampleView(APIView):\n authentication_classes = (SessionAuthentication, BasicAuthentication)\n permission_classes = (IsAuthenticated,)\n\n def get(self, request, format=None):\n content = {\n 'user': unicode(request.user), # `django.contrib.auth.User` instance.\n 'auth': unicode(request.auth), # None\n }\n return Response(content)\n\n\n\nOr, if you're using the \n@api_view\n decorator with function based views.\n\n\n@api_view(['GET'])\n@authentication_classes((SessionAuthentication, BasicAuthentication))\n@permission_classes((IsAuthenticated,))\ndef example_view(request, format=None):\n content = {\n 'user': unicode(request.user), # `django.contrib.auth.User` instance.\n 'auth': unicode(request.auth), # None\n }\n return Response(content)\n\n\n\nUnauthorized and Forbidden responses\n\n\nWhen an unauthenticated request is denied permission there are two different error codes that may be appropriate.\n\n\n\n\nHTTP 401 Unauthorized\n\n\nHTTP 403 Permission Denied\n\n\n\n\nHTTP 401 responses must always include a \nWWW-Authenticate\n header, that instructs the client how to authenticate. HTTP 403 responses do not include the \nWWW-Authenticate\n header.\n\n\nThe kind of response that will be used depends on the authentication scheme. Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. \nThe first authentication class set on the view is used when determining the type of response\n.\n\n\nNote that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a \n403 Permission Denied\n response will always be used, regardless of the authentication scheme.\n\n\nApache mod_wsgi specific configuration\n\n\nNote that if deploying to \nApache using mod_wsgi\n, the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level.\n\n\nIf you are deploying to Apache, and using any non-session based authentication, you will need to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the \nWSGIPassAuthorization\n directive in the appropriate context and setting it to \n'On'\n.\n\n\n# this can go in either server config, virtual host, directory or .htaccess\nWSGIPassAuthorization On\n\n\n\n\n\nAPI Reference\n\n\nBasicAuthentication\n\n\nThis authentication scheme uses \nHTTP Basic Authentication\n, signed against a user's username and password. Basic authentication is generally only appropriate for testing.\n\n\nIf successfully authenticated, \nBasicAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be \nNone\n.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 401 Unauthorized\n response with an appropriate WWW-Authenticate header. For example:\n\n\nWWW-Authenticate: Basic realm=\"api\"\n\n\n\nNote:\n If you use \nBasicAuthentication\n in production you must ensure that your API is only available over \nhttps\n. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.\n\n\nTokenAuthentication\n\n\nThis authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.\n\n\nTo use the \nTokenAuthentication\n scheme you'll need to \nconfigure the authentication classes\n to include \nTokenAuthentication\n, and additionally include \nrest_framework.authtoken\n in your \nINSTALLED_APPS\n setting:\n\n\nINSTALLED_APPS = (\n ...\n 'rest_framework.authtoken'\n)\n\n\n\n\n\nNote:\n Make sure to run \nmanage.py migrate\n after changing your settings. The \nrest_framework.authtoken\n app provides Django database migrations.\n\n\n\n\nYou'll also need to create tokens for your users.\n\n\nfrom rest_framework.authtoken.models import Token\n\ntoken = Token.objects.create(user=...)\nprint token.key\n\n\n\nFor clients to authenticate, the token key should be included in the \nAuthorization\n HTTP header. The key should be prefixed by the string literal \"Token\", with whitespace separating the two strings. For example:\n\n\nAuthorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b\n\n\n\nNote:\n If you want to use a different keyword in the header, such as \nBearer\n, simply subclass \nTokenAuthentication\n and set the \nkeyword\n class variable.\n\n\nIf successfully authenticated, \nTokenAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be a \nrest_framework.authtoken.models.Token\n instance.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 401 Unauthorized\n response with an appropriate WWW-Authenticate header. For example:\n\n\nWWW-Authenticate: Token\n\n\n\nThe \ncurl\n command line tool may be useful for testing token authenticated APIs. For example:\n\n\ncurl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'\n\n\n\n\n\nNote:\n If you use \nTokenAuthentication\n in production you must ensure that your API is only available over \nhttps\n.\n\n\n\n\nGenerating Tokens\n\n\nBy using signals\n\n\nIf you want every user to have an automatically generated Token, you can simply catch the User's \npost_save\n signal.\n\n\nfrom django.conf import settings\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\nfrom rest_framework.authtoken.models import Token\n\n@receiver(post_save, sender=settings.AUTH_USER_MODEL)\ndef create_auth_token(sender, instance=None, created=False, **kwargs):\n if created:\n Token.objects.create(user=instance)\n\n\n\nNote that you'll want to ensure you place this code snippet in an installed \nmodels.py\n module, or some other location that will be imported by Django on startup.\n\n\nIf you've already created some users, you can generate tokens for all existing users like this:\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework.authtoken.models import Token\n\nfor user in User.objects.all():\n Token.objects.get_or_create(user=user)\n\n\n\nBy exposing an api endpoint\n\n\nWhen using \nTokenAuthentication\n, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the \nobtain_auth_token\n view to your URLconf:\n\n\nfrom rest_framework.authtoken import views\nurlpatterns += [\n url(r'^api-token-auth/', views.obtain_auth_token)\n]\n\n\n\nNote that the URL part of the pattern can be whatever you want to use.\n\n\nThe \nobtain_auth_token\n view will return a JSON response when valid \nusername\n and \npassword\n fields are POSTed to the view using form data or JSON:\n\n\n{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }\n\n\n\nNote that the default \nobtain_auth_token\n view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the \nobtain_auth_token\n view, you can do so by overriding the \nObtainAuthToken\n view class, and using that in your url conf instead.\n\n\nBy default there are no permissions or throttling applied to the \nobtain_auth_token\n view. If you do wish to apply throttling you'll need to override the view class,\nand include them using the \nthrottle_classes\n attribute.\n\n\nWith Django admin\n\n\nIt is also possible to create Tokens manually through admin interface. In case you are using a large user base, we recommend that you monkey patch the \nTokenAdmin\n class to customize it to your needs, more specifically by declaring the \nuser\n field as \nraw_field\n.\n\n\nyour_app/admin.py\n:\n\n\nfrom rest_framework.authtoken.admin import TokenAdmin\n\nTokenAdmin.raw_id_fields = ('user',)\n\n\n\nSessionAuthentication\n\n\nThis authentication scheme uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website.\n\n\nIf successfully authenticated, \nSessionAuthentication\n provides the following credentials.\n\n\n\n\nrequest.user\n will be a Django \nUser\n instance.\n\n\nrequest.auth\n will be \nNone\n.\n\n\n\n\nUnauthenticated responses that are denied permission will result in an \nHTTP 403 Forbidden\n response.\n\n\nIf you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any \"unsafe\" HTTP method calls, such as \nPUT\n, \nPATCH\n, \nPOST\n or \nDELETE\n requests. See the \nDjango CSRF documentation\n for more details.\n\n\nWarning\n: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.\n\n\nCSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.\n\n\nCustom authentication\n\n\nTo implement a custom authentication scheme, subclass \nBaseAuthentication\n and override the \n.authenticate(self, request)\n method. The method should return a two-tuple of \n(user, auth)\n if authentication succeeds, or \nNone\n otherwise.\n\n\nIn some circumstances instead of returning \nNone\n, you may want to raise an \nAuthenticationFailed\n exception from the \n.authenticate()\n method.\n\n\nTypically the approach you should take is:\n\n\n\n\nIf authentication is not attempted, return \nNone\n. Any other authentication schemes also in use will still be checked.\n\n\nIf authentication is attempted but fails, raise a \nAuthenticationFailed\n exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes.\n\n\n\n\nYou \nmay\n also override the \n.authenticate_header(self, request)\n method. If implemented, it should return a string that will be used as the value of the \nWWW-Authenticate\n header in a \nHTTP 401 Unauthorized\n response.\n\n\nIf the \n.authenticate_header()\n method is not overridden, the authentication scheme will return \nHTTP 403 Forbidden\n responses when an unauthenticated request is denied access.\n\n\nExample\n\n\nThe following example will authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'.\n\n\nfrom django.contrib.auth.models import User\nfrom rest_framework import authentication\nfrom rest_framework import exceptions\n\nclass ExampleAuthentication(authentication.BaseAuthentication):\n def authenticate(self, request):\n username = request.META.get('X_USERNAME')\n if not username:\n return None\n\n try:\n user = User.objects.get(username=username)\n except User.DoesNotExist:\n raise exceptions.AuthenticationFailed('No such user')\n\n return (user, None)\n\n\n\n\n\nThird party packages\n\n\nThe following third party packages are also available.\n\n\nDjango OAuth Toolkit\n\n\nThe \nDjango OAuth Toolkit\n package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by \nEvonove\n and uses the excellent \nOAuthLib\n. The package is well documented, and well supported and is currently our \nrecommended package for OAuth 2.0 support\n.\n\n\nInstallation \n configuration\n\n\nInstall using \npip\n.\n\n\npip install django-oauth-toolkit\n\n\n\nAdd the package to your \nINSTALLED_APPS\n and modify your REST framework settings.\n\n\nINSTALLED_APPS = (\n ...\n 'oauth2_provider',\n)\n\nREST_FRAMEWORK = {\n 'DEFAULT_AUTHENTICATION_CLASSES': (\n 'oauth2_provider.ext.rest_framework.OAuth2Authentication',\n )\n}\n\n\n\nFor more details see the \nDjango REST framework - Getting started\n documentation.\n\n\nDjango REST framework OAuth\n\n\nThe \nDjango REST framework OAuth\n package provides both OAuth1 and OAuth2 support for REST framework.\n\n\nThis package was previously included directly in REST framework but is now supported and maintained as a third party package.\n\n\nInstallation \n configuration\n\n\nInstall the package using \npip\n.\n\n\npip install djangorestframework-oauth\n\n\n\nFor details on configuration and usage see the Django REST framework OAuth documentation for \nauthentication\n and \npermissions\n.\n\n\nDigest Authentication\n\n\nHTTP digest authentication is a widely implemented scheme that was intended to replace HTTP basic authentication, and which provides a simple encrypted authentication mechanism. \nJuan Riaza\n maintains the \ndjangorestframework-digestauth\n package which provides HTTP digest authentication support for REST framework.\n\n\nDjango OAuth2 Consumer\n\n\nThe \nDjango OAuth2 Consumer\n library from \nRediker Software\n is another package that provides \nOAuth 2.0 support for REST framework\n. The package includes token scoping permissions on tokens, which allows finer-grained access to your API.\n\n\nJSON Web Token Authentication\n\n\nJSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. \nBlimp\n maintains the \ndjangorestframework-jwt\n package which provides a JWT Authentication class as well as a mechanism for clients to obtain a JWT given the username and password.\n\n\nHawk HTTP Authentication\n\n\nThe \nHawkREST\n library builds on the \nMohawk\n library to let you work with \nHawk\n signed requests and responses in your API. \nHawk\n lets two parties securely communicate with each other using messages signed by a shared key. It is based on \nHTTP MAC access authentication\n (which was based on parts of \nOAuth 1.0\n).\n\n\nHTTP Signature Authentication\n\n\nHTTP Signature (currently a \nIETF draft\n) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to \nAmazon's HTTP Signature scheme\n, used by many of its services, it permits stateless, per-request authentication. \nElvio Toccalino\n maintains the \ndjangorestframework-httpsignature\n package which provides an easy to use HTTP Signature Authentication mechanism.\n\n\nDjoser\n\n\nDjoser\n library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and it uses token based authentication. This is a ready to use REST implementation of Django authentication system.\n\n\ndjango-rest-auth\n\n\nDjango-rest-auth\n library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.\n\n\ndjango-rest-framework-social-oauth2\n\n\nDjango-rest-framework-social-oauth2\n library provides an easy way to integrate social plugins (facebook, twitter, google, etc.) to your authentication system and an easy oauth2 setup. With this library, you will be able to authenticate users based on external tokens (e.g. facebook access token), convert these tokens to \"in-house\" oauth2 tokens and use and generate oauth2 tokens to authenticate your users.\n\n\ndjango-rest-knox\n\n\nDjango-rest-knox\n library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).", "title": "Authentication" }, { @@ -2317,7 +2317,7 @@ }, { "location": "/api-guide/authentication/#tokenauthentication", - "text": "This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients. To use the TokenAuthentication scheme you'll need to configure the authentication classes to include TokenAuthentication , and additionally include rest_framework.authtoken in your INSTALLED_APPS setting: INSTALLED_APPS = (\n ...\n 'rest_framework.authtoken'\n) Note: Make sure to run manage.py migrate after changing your settings. The rest_framework.authtoken app provides Django database migrations. You'll also need to create tokens for your users. from rest_framework.authtoken.models import Token\n\ntoken = Token.objects.create(user=...)\nprint token.key For clients to authenticate, the token key should be included in the Authorization HTTP header. The key should be prefixed by the string literal \"Token\", with whitespace separating the two strings. For example: Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b Note: If you want to use a different keyword in the header, such as Bearer , simply subclass TokenAuthentication and set the keyword class variable. If successfully authenticated, TokenAuthentication provides the following credentials. request.user will be a Django User instance. request.auth will be a rest_framework.authtoken.models.BasicToken instance. Unauthenticated responses that are denied permission will result in an HTTP 401 Unauthorized response with an appropriate WWW-Authenticate header. For example: WWW-Authenticate: Token The curl command line tool may be useful for testing token authenticated APIs. For example: curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' Note: If you use TokenAuthentication in production you must ensure that your API is only available over https .", + "text": "This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients. To use the TokenAuthentication scheme you'll need to configure the authentication classes to include TokenAuthentication , and additionally include rest_framework.authtoken in your INSTALLED_APPS setting: INSTALLED_APPS = (\n ...\n 'rest_framework.authtoken'\n) Note: Make sure to run manage.py migrate after changing your settings. The rest_framework.authtoken app provides Django database migrations. You'll also need to create tokens for your users. from rest_framework.authtoken.models import Token\n\ntoken = Token.objects.create(user=...)\nprint token.key For clients to authenticate, the token key should be included in the Authorization HTTP header. The key should be prefixed by the string literal \"Token\", with whitespace separating the two strings. For example: Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b Note: If you want to use a different keyword in the header, such as Bearer , simply subclass TokenAuthentication and set the keyword class variable. If successfully authenticated, TokenAuthentication provides the following credentials. request.user will be a Django User instance. request.auth will be a rest_framework.authtoken.models.Token instance. Unauthenticated responses that are denied permission will result in an HTTP 401 Unauthorized response with an appropriate WWW-Authenticate header. For example: WWW-Authenticate: Token The curl command line tool may be useful for testing token authenticated APIs. For example: curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' Note: If you use TokenAuthentication in production you must ensure that your API is only available over https .", "title": "TokenAuthentication" }, { @@ -2537,7 +2537,7 @@ }, { "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", + "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", "title": "Throttling" }, { @@ -2592,7 +2592,7 @@ }, { "location": "/api-guide/throttling/#example", - "text": "The following is an example of a rate throttle, that will randomly throttle 1 in every 10 requests. import random\n\nclass RandomRateThrottle(throttling.BaseThrottle):\n def allow_request(self, request, view):\n return random.randint(1, 10) == 1", + "text": "The following is an example of a rate throttle, that will randomly throttle 1 in every 10 requests. import random\n\nclass RandomRateThrottle(throttling.BaseThrottle):\n def allow_request(self, request, view):\n return random.randint(1, 10) != 1", "title": "Example" }, { @@ -5007,7 +5007,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.4.x series\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.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.", "title": "Release Notes" }, { @@ -5035,6 +5035,11 @@ "text": "", "title": "3.4.x series" }, + { + "location": "/topics/release-notes/#347", + "text": "Date : 21st September 2016 Fallback behavior for request parsing when request.POST already accessed. ( #3951 , #4500 ) Fix regression of RegexField . ( #4489 , #4490 , #2617 ) Missing comma in admin.html causing CSRF error. ( #4472 , #4473 ) Fix response rendering with empty context. ( #4495 ) Fix indentation regression in API listing. ( #4493 ) Fixed an issue where the incorrect value is set to ResolverMatch.func_name of api_view decorated view. ( #4465 , #4462 ) Fix APIClient.get() when path contains unicode arguments ( #4458 )", + "title": "3.4.7" + }, { "location": "/topics/release-notes/#346", "text": "Date : 23rd August 2016 Fix malformed Javascript in browsable API. ( #4435 ) Skip HiddenField from Schema fields. ( #4425 , #4429 ) Improve Create to show the original exception traceback. ( #3508 ) Fix AdminRenderer display of PK only related fields. ( #4419 , #4423 )", diff --git a/sitemap.xml b/sitemap.xml index afc4591c0..35ea74601 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -4,7 +4,7 @@ http://www.django-rest-framework.org// - 2016-08-25 + 2016-09-21 daily @@ -13,49 +13,49 @@ http://www.django-rest-framework.org//tutorial/quickstart/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//tutorial/1-serialization/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//tutorial/2-requests-and-responses/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//tutorial/3-class-based-views/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//tutorial/4-authentication-and-permissions/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//tutorial/5-relationships-and-hyperlinked-apis/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//tutorial/6-viewsets-and-routers/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//tutorial/7-schemas-and-client-libraries/ - 2016-08-25 + 2016-09-21 daily @@ -65,163 +65,163 @@ http://www.django-rest-framework.org//api-guide/requests/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/responses/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/views/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/generic-views/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/viewsets/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/routers/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/parsers/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/renderers/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/serializers/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/fields/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/relations/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/validators/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/authentication/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/permissions/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/throttling/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/filtering/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/pagination/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/versioning/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/content-negotiation/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/metadata/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/schemas/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/format-suffixes/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/reverse/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/exceptions/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/status-codes/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/testing/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//api-guide/settings/ - 2016-08-25 + 2016-09-21 daily @@ -231,121 +231,121 @@ http://www.django-rest-framework.org//topics/documenting-your-api/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/api-clients/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/internationalization/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/ajax-csrf-cors/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/html-and-forms/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/browser-enhancements/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/browsable-api/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/rest-hypermedia-hateoas/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/third-party-resources/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/contributing/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/project-management/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/3.0-announcement/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/3.1-announcement/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/3.2-announcement/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/3.3-announcement/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/3.4-announcement/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/kickstarter-announcement/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/mozilla-grant/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/funding/ - 2016-08-25 + 2016-09-21 daily http://www.django-rest-framework.org//topics/release-notes/ - 2016-08-25 + 2016-09-21 daily diff --git a/topics/release-notes/index.html b/topics/release-notes/index.html index dc5fcbc81..b3899394c 100644 --- a/topics/release-notes/index.html +++ b/topics/release-notes/index.html @@ -446,6 +446,17 @@

3.4.x series

+

3.4.7

+

Date: 21st September 2016

+

3.4.6

Date: 23rd August 2016