<p>Make sure to run <code>manage.py syncdb</code> after changing your settings. The <code>authtoken</code> database tables are managed by south (see <ahref="#schema-migrations">Schema migrations</a> below).</p>
<hr/>
<p><strong>Note:</strong> Make sure to run <code>manage.py syncdb</code> after changing your settings. The <code>rest_framework.authtoken</code> app provides both Django (from v1.7) and South database migrations. See <ahref="#schema-migrations">Schema migrations</a> below.</p>
<hr/>
<p>You'll also need to create tokens for your users.</p>
<p>You'll also need to create tokens for your users.</p>
@@ -362,7 +364,10 @@ for user in User.objects.all():
...
@@ -362,7 +364,10 @@ for user in User.objects.all():
</code></pre>
</code></pre>
<p>Note that the default <code>obtain_auth_token</code> 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 <code>obtain_auth_token</code> view, you can do so by overriding the <code>ObtainAuthToken</code> view class, and using that in your url conf instead.</p>
<p>Note that the default <code>obtain_auth_token</code> 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 <code>obtain_auth_token</code> view, you can do so by overriding the <code>ObtainAuthToken</code> view class, and using that in your url conf instead.</p>
<h4id="schema-migrations">Schema migrations</h4>
<h4id="schema-migrations">Schema migrations</h4>
<p>The <code>rest_framework.authtoken</code> app includes a south migration that will create the authtoken table.</p>
<p>The <code>rest_framework.authtoken</code> app includes both Django native migrations (for Django versions >1.7) and South migrations (for Django versions <1.7) that will create the authtoken table.</p>
<hr/>
<p><strong>Note</strong>: From REST Framework v2.4.0 using South with Django <1.7 requires upgrading South v1.0+</p>
<hr/>
<p>If you're using a <ahref="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model">custom user model</a> you'll need to make sure that any initial migration that creates the user table runs before the authtoken table is created.</p>
<p>If you're using a <ahref="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model">custom user model</a> you'll need to make sure that any initial migration that creates the user table runs before the authtoken table is created.</p>
<p>You can do so by inserting a <code>needed_by</code> attribute in your user migration:</p>
<p>You can do so by inserting a <code>needed_by</code> attribute in your user migration:</p>
@@ -461,6 +463,8 @@ class ColourField(serializers.WritableField):
...
@@ -461,6 +463,8 @@ class ColourField(serializers.WritableField):
<p>The <ahref="https://github.com/Hipo/drf-extra-fields">drf-extra-fields</a> package provides extra serializer fields for REST framework, including <code>Base64ImageField</code> and <code>PointField</code> classes.</p>
<p>The <ahref="https://github.com/Hipo/drf-extra-fields">drf-extra-fields</a> package provides extra serializer fields for REST framework, including <code>Base64ImageField</code> and <code>PointField</code> classes.</p>
<p>The <ahref="https://github.com/djangonauts/django-rest-framework-gis">django-rest-framework-gis</a> package provides geographic addons for django rest framework like a <code>GeometryField</code> field and a GeoJSON serializer.</p>
<p>The <ahref="https://github.com/djangonauts/django-rest-framework-gis">django-rest-framework-gis</a> package provides geographic addons for django rest framework like a <code>GeometryField</code> field and a GeoJSON serializer.</p>
<p>The <ahref="https://github.com/djangonauts/django-rest-framework-hstore">django-rest-framework-hstore</a> package provides an <code>HStoreField</code> to support <ahref="https://github.com/djangonauts/django-hstore">django-hstore</a><code>DictionaryField</code> model field.</p>
@@ -262,7 +262,7 @@ class UserList(generics.ListCreateAPIView):
...
@@ -262,7 +262,7 @@ class UserList(generics.ListCreateAPIView):
serializer = UserSerializer(queryset, many=True)
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
return Response(serializer.data)
</code></pre>
</code></pre>
<p>For very simple cases you might want to pass through any class attributes using the <code>.as_view()</code> method. For example, your URLconf might include something the following entry.</p>
<p>For very simple cases you might want to pass through any class attributes using the <code>.as_view()</code> method. For example, your URLconf might include something like the following entry:</p>
<p>Returns 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 <code>queryset</code> attribute, or the default queryset for the model if the <code>model</code> shortcut is being used.</p>
<p>Returns 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 <code>queryset</code> attribute, or the default queryset for the model if the <code>model</code> shortcut is being used.</p>
<p>This method should always be used rather than accessing <code>self.queryset</code> directly, as <code>self.queryset</code> gets evaluated only once, and those results are cached for all subsequent requests.</p>
<p>This method should always be used rather than accessing <code>self.queryset</code> directly, as <code>self.queryset</code> gets evaluated only once, and those results are cached for all subsequent requests.</p>
<p>May be overridden to provide dynamic behavior such as returning a queryset that is specific to the user making the request.</p>
<p>May be overridden to provide dynamic behavior, such as returning a queryset, that is specific to the user making the request.</p>
<p>Returns an object instance that should be used for detail views. Defaults to using the <code>lookup_field</code> parameter to filter the base queryset.</p>
<p>Returns an object instance that should be used for detail views. Defaults to using the <code>lookup_field</code> parameter to filter the base queryset.</p>
<p>May be overridden to provide more complex behavior such as object lookups based on more than one URL kwarg.</p>
<p>May be overridden to provide more complex behavior, such as object lookups based on more than one URL kwarg.</p>
@@ -323,7 +323,7 @@ class UserList(generics.ListCreateAPIView):
...
@@ -323,7 +323,7 @@ class UserList(generics.ListCreateAPIView):
<p>Note that if your API doesn't include any object level permissions, you may optionally exclude the <code>self.check_object_permissions</code>, and simply return the object from the <code>get_object_or_404</code> lookup.</p>
<p>Note that if your API doesn't include any object level permissions, you may optionally exclude the <code>self.check_object_permissions</code>, and simply return the object from the <code>get_object_or_404</code> lookup.</p>
<p>Returns the classes that should be used to filter the queryset. Defaults to returning the <code>filter_backends</code> attribute.</p>
<p>Returns the classes that should be used to filter the queryset. Defaults to returning the <code>filter_backends</code> attribute.</p>
<p>May be override to provide more complex behavior with filters, as using different (or even exlusive) lists of filter_backends depending on different criteria.</p>
<p>May be overridden to provide more complex behavior with filters, such as using different (or even exlusive) lists of filter_backends depending on different criteria.</p>
<p>Returns the class that should be used for the serializer. Defaults to returning the <code>serializer_class</code> attribute, or dynamically generating a serializer class if the <code>model</code> shortcut is being used.</p>
<p>Returns the class that should be used for the serializer. Defaults to returning the <code>serializer_class</code> attribute, or dynamically generating a serializer class if the <code>model</code> shortcut is being used.</p>
<p>May be override to provide dynamic behavior such as using different serializers for read and write operations, or providing different serializers to different types of users.</p>
<p>May 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.</p>
<p>Returns the page size to use with pagination. By default this uses the <code>paginate_by</code> attribute, and may be overridden by the client if the <code>paginate_by_param</code> attribute is set.</p>
<p>Returns the page size to use with pagination. By default this uses the <code>paginate_by</code> attribute, and may be overridden by the client if the <code>paginate_by_param</code> attribute is set.</p>
<p>You may want to override this method to provide more complex behavior such as modifying page sizes based on the media type of the response.</p>
<p>You may want to override this method to provide more complex behavior, such as modifying page sizes based on the media type of the response.</p>
if self.request.accepted_renderer.format == 'html':
if self.request.accepted_renderer.format == 'html':
...
@@ -378,7 +378,7 @@ class UserList(generics.ListCreateAPIView):
...
@@ -378,7 +378,7 @@ class UserList(generics.ListCreateAPIView):
</ul>
</ul>
<hr/>
<hr/>
<h1id="mixins">Mixins</h1>
<h1id="mixins">Mixins</h1>
<p>The 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 <code>.get()</code> and <code>.post()</code> directly. This allows for more flexible composition of behavior.</p>
<p>The 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 <code>.get()</code> and <code>.post()</code>, directly. This allows for more flexible composition of behavior.</p>
<h2id="listmodelmixin">ListModelMixin</h2>
<h2id="listmodelmixin">ListModelMixin</h2>
<p>Provides a <code>.list(request, *args, **kwargs)</code> method, that implements listing a queryset.</p>
<p>Provides a <code>.list(request, *args, **kwargs)</code> method, that implements listing a queryset.</p>
<p>If the queryset is populated, this returns a <code>200 OK</code> response, with a serialized representation of the queryset as the body of the response. The response data may optionally be paginated.</p>
<p>If the queryset is populated, this returns a <code>200 OK</code> response, with a serialized representation of the queryset as the body of the response. The response data may optionally be paginated.</p>
@@ -672,6 +673,8 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
...
@@ -672,6 +673,8 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<p>The <ahref="https://github.com/umutbozkurt/django-rest-framework-mongoengine">django-rest-framework-mongoengine</a> package provides a <code>MongoEngineModelSerializer</code> serializer class that supports using MongoDB as the storage layer for Django REST framework.</p>
<p>The <ahref="https://github.com/umutbozkurt/django-rest-framework-mongoengine">django-rest-framework-mongoengine</a> package provides a <code>MongoEngineModelSerializer</code> serializer class that supports using MongoDB as the storage layer for Django REST framework.</p>
<p>The <ahref="https://github.com/djangonauts/django-rest-framework-gis">django-rest-framework-gis</a> package provides a <code>GeoFeatureModelSerializer</code> serializer class that supports GeoJSON both for read and write operations.</p>
<p>The <ahref="https://github.com/djangonauts/django-rest-framework-gis">django-rest-framework-gis</a> package provides a <code>GeoFeatureModelSerializer</code> serializer class that supports GeoJSON both for read and write operations.</p>
<h2id="hstoreserializer">HStoreSerializer</h2>
<p>The <ahref="https://github.com/djangonauts/django-rest-framework-hstore">django-rest-framework-hstore</a> package provides an <code>HStoreSerializer</code> to support <ahref="https://github.com/djangonauts/django-hstore">django-hstore</a><code>DictionaryField</code> model field and its <code>schema-mode</code> feature.</p>
<p>The name of a parameter in the URL conf that may be used to provide a format suffix.</p>
<p>The name of a parameter in the URL conf that may be used to provide a format suffix.</p>
<p>Default: <code>'format'</code></p>
<p>Default: <code>'format'</code></p>
<h4id="num_proxies">NUM_PROXIES</h4>
<p>An integer of 0 or more, that may be used to specify the number of application proxies that the API runs behind. This allows throttling to more accurately identify client IP addresses. If set to <code>None</code> then less strict IP matching will be used by the throttle classes.</p>
@@ -229,7 +229,7 @@ If any throttle check fails an <code>exceptions.Throttled</code> exception will
...
@@ -229,7 +229,7 @@ If any throttle check fails an <code>exceptions.Throttled</code> exception will
'DEFAULT_THROTTLE_RATES': {
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'anon': '100/day',
'user': '1000/day'
'user': '1000/day'
}
}
}
}
</code></pre>
</code></pre>
<p>The rate descriptions used in <code>DEFAULT_THROTTLE_RATES</code> may include <code>second</code>, <code>minute</code>, <code>hour</code> or <code>day</code> as the throttle period.</p>
<p>The rate descriptions used in <code>DEFAULT_THROTTLE_RATES</code> may include <code>second</code>, <code>minute</code>, <code>hour</code> or <code>day</code> as the throttle period.</p>
<h2id="how-clients-are-identified">How clients are identified</h2>
<p>The <code>X-Forwarded-For</code> and <code>Remote-Addr</code> HTTP headers are used to uniquely identify client IP addresses for throttling. If the <code>X-Forwarded-For</code> header is present then it will be used, otherwise the value of the <code>Remote-Addr</code> header will be used.</p>
<p>If 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 <code>NUM_PROXIES</code> 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 <code>X-Forwarded-For</code> header, once any application proxy IP addresses have first been excluded. If set to zero, then the <code>Remote-Addr</code> header will always be used as the identifying IP address.</p>
<p>It is important to understand that if you configure the <code>NUM_PROXIES</code> setting, then all clients behind a unique <ahref="http://en.wikipedia.org/wiki/Network_address_translation">NAT'd</a> gateway will be treated as a single client.</p>
<p>Further context on how the <code>X-Forwarded-For</code> header works, and identifing a remote client IP can be <ahref="http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster">found here</a>.</p>
<h2id="setting-up-the-cache">Setting up the cache</h2>
<h2id="setting-up-the-cache">Setting up the cache</h2>
<p>The throttle classes provided by REST framework use Django's cache backend. You should make sure that you've set appropriate <ahref="https://docs.djangoproject.com/en/dev/ref/settings/#caches">cache settings</a>. The default value of <code>LocMemCache</code> backend should be okay for simple setups. See Django's <ahref="https://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache">cache documentation</a> for more details.</p>
<p>The throttle classes provided by REST framework use Django's cache backend. You should make sure that you've set appropriate <ahref="https://docs.djangoproject.com/en/dev/ref/settings/#caches">cache settings</a>. The default value of <code>LocMemCache</code> backend should be okay for simple setups. See Django's <ahref="https://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache">cache documentation</a> for more details.</p>
<p>If you need to use a cache other than <code>'default'</code>, you can do so by creating a custom throttle class and setting the <code>cache</code> attribute. For example:</p>
<p>If you need to use a cache other than <code>'default'</code>, you can do so by creating a custom throttle class and setting the <code>cache</code> attribute. For example:</p>
<li>By using routers, we no longer need to deal with wiring up the URL conf ourselves.</li>
<li>By using routers, we no longer need to deal with wiring up the URL conf ourselves.</li>
</ul>
</ul>
<p>Both of these come with a trade-off. Using regular views and URL confs is more explicit and gives you more control. ViewSets are helpful if you want to get up and running quickly, or when you have a large API and you want to enforce a consistent URL configuration throughout.</p>
<p>Both of these come with a trade-off. Using regular views and URL confs is more explicit and gives you more control. ViewSets are helpful if you want to get up and running quickly, or when you have a large API and you want to enforce a consistent URL configuration throughout.</p>
<h2id="marking-extra-methods-for-routing">Marking extra methods for routing</h2>
<h2id="marking-extra-actions-for-routing">Marking extra actions for routing</h2>
<p>The default routers included with REST framework will provide routes for a standard set of create/retrieve/update/destroy style operations, as shown below:</p>
<p>The default routers included with REST framework will provide routes for a standard set of create/retrieve/update/destroy style operations, as shown below:</p>
<p>If you have ad-hoc methods that you need to be routed to, you can mark them as requiring routing using the <code>@link</code> or <code>@action</code> decorators. The <code>@link</code> decorator will route <code>GET</code> requests, and the <code>@action</code> decorator will route <code>POST</code> requests.</p>
<p>If you have ad-hoc methods that you need to be routed to, you can mark them as requiring routing using the <code>@detail_route</code> or <code>@list_route</code> decorators.</p>
<p>The <code>@detail_route</code> decorator contains <code>pk</code> in its URL pattern and is intended for methods which require a single instance. The <code>@list_route</code> decorator is intended for methods which operate on a list of objects.</p>
<p>For example:</p>
<p>For example:</p>
<preclass="prettyprint lang-py"><code>from django.contrib.auth.models import User
<preclass="prettyprint lang-py"><code>from django.contrib.auth.models import User
from rest_framework import viewsets
from rest_framework import status
from rest_framework import status
from rest_framework.decorators import action
from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializer
from myapp.serializers import UserSerializer, PasswordSerializer
...
@@ -308,7 +309,7 @@ class UserViewSet(viewsets.ModelViewSet):
...
@@ -308,7 +309,7 @@ class UserViewSet(viewsets.ModelViewSet):
<p>The <code>@action</code> and <code>@link</code>decorators can additionally take extra arguments that will be set for the routed view only. For example...</p>
<p>The decorators can additionally take extra arguments that will be set for the routed view only. For example...</p>
<p>The<code>@action</code> decorator will route <code>POST</code> requests by default, but may also accept other HTTP methods, by using the <code>methods</code> argument. For example:</p>
<p>Theses decorators will route <code>GET</code> requests by default, but may also accept other HTTP methods, by using the <code>methods</code> argument. For example:</p>
<p>To run the tests against all supported configurations, first install <ahref="http://testrun.org/tox/latest/">the tox testing tool</a> globally, using <code>pip install tox</code>, then simply run <code>tox</code>:</p>
<preclass="prettyprint lang-py"><code>tox
</code></pre>
<h2id="support">Support</h2>
<h2id="support">Support</h2>
<p>For support please see the <ahref="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">REST framework discussion group</a>, try the <code>#restframework</code> channel on <code>irc.freenode.net</code>, search <ahref="https://botbot.me/freenode/restframework/">the IRC archives</a>, or raise a question on <ahref="http://stackoverflow.com/">Stack Overflow</a>, making sure to include the <ahref="http://stackoverflow.com/questions/tagged/django-rest-framework">'django-rest-framework'</a> tag.</p>
<p>For support please see the <ahref="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">REST framework discussion group</a>, try the <code>#restframework</code> channel on <code>irc.freenode.net</code>, search <ahref="https://botbot.me/freenode/restframework/">the IRC archives</a>, or raise a question on <ahref="http://stackoverflow.com/">Stack Overflow</a>, making sure to include the <ahref="http://stackoverflow.com/questions/tagged/django-rest-framework">'django-rest-framework'</a> tag.</p>
<p><ahref="http://dabapps.com/services/build/api-development/">Paid support is available</a> from <ahref="http://dabapps.com">DabApps</a>, and can include work on REST framework core, or support with building your REST framework API. Please <ahref="http://dabapps.com/contact/">contact DabApps</a> if you'd like to discuss commercial support options.</p>
<p><ahref="http://dabapps.com/services/build/api-development/">Paid support is available</a> from <ahref="http://dabapps.com">DabApps</a>, and can include work on REST framework core, or support with building your REST framework API. Please <ahref="http://dabapps.com/contact/">contact DabApps</a> if you'd like to discuss commercial support options.</p>
<p>Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.</p>
<h3id="running-against-multiple-environments">Running against multiple environments</h3>
<p>You can also use the excellent <ahref="http://tox.readthedocs.org/en/latest/">tox</a> testing tool to run the tests against all supported versions of Python and Django. Install <code>tox</code> globally, and then simply run:</p>
<p>You can also use the excellent <ahref="http://tox.readthedocs.org/en/latest/">tox</a> testing tool to run the tests against all supported versions of Python and Django. Install <code>tox</code> globally, and then simply run:</p>
<li><ahref="http://singinghorsestudio.com"rel="nofollow"style="background-image:url(../img/sponsors/2-singing-horse.png);">Singing Horse Studio Ltd.</a></li>
<p><strong>Individual backers</strong>: Simon Haugk.</p>
<hr/>
<hr/>
<h3id="silver-sponsors">Silver sponsors</h3>
<h3id="silver-sponsors">Silver sponsors</h3>
<p>The serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank you to individuals who have choosen to privately support the project at this level.</p>
<p>The serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank you to individuals who have choosen to privately support the project at this level.</p>
<p><strong>Individual backers</strong>: Paul Hallet, <ahref="http://www.paulwhippconsulting.com/">Paul Whipp</a>, Dylan Roy, Jannis Leidel, <ahref="https://linovia.com/en/">Xavier Ordoquy</a>, <ahref="http://spielmannsolutions.com/">Johannes Spielmann</a>, <ahref="http://brooklynhacker.com/">Rob Spectre</a>, <ahref="http://chrisheisel.com/">Chris Heisel</a>, Marwan Alsabbagh, Haris Ali, Tuomas Toivonen.</p>
<p><strong>Individual backers</strong>: Paul Hallett, <ahref="http://www.paulwhippconsulting.com/">Paul Whipp</a>, Dylan Roy, Jannis Leidel, <ahref="https://linovia.com/en/">Xavier Ordoquy</a>, <ahref="http://spielmannsolutions.com/">Johannes Spielmann</a>, <ahref="http://brooklynhacker.com/">Rob Spectre</a>, <ahref="http://chrisheisel.com/">Chris Heisel</a>, Marwan Alsabbagh, Haris Ali, Tuomas Toivonen.</p>
<hr/>
<hr/>
<h3id="advocates">Advocates</h3>
<h3id="advocates">Advocates</h3>
<p>The following individuals made a significant financial contribution to the development of Django REST framework 3, for which I can only offer a huge, warm and sincere thank you!</p>
<p>The following individuals made a significant financial contribution to the development of Django REST framework 3, for which I can only offer a huge, warm and sincere thank you!</p>
<p><strong>Django version requirements</strong>: The lowest supported version of Django is now 1.4.2.</p>
<p><strong>South version requirements</strong>: This note applies to any users using the optional <code>authtoken</code> application, which includes an associated database migration. You must now <em>either</em> upgrade your <code>south</code> package to version 1.0, <em>or</em> instead use the built-in migration support available with Django 1.7.</p>
<ul>
<li>Added compatibility with Django 1.7's database migration support.</li>
<li>New test runner, using <code>py.test</code>.</li>
<li><code>@detail_route</code> and <code>@list_route</code> decorators replace <code>@action</code> and <code>@link</code>.</li>
<li>Support customizable view name and description functions, using the <code>VIEW_NAME_FUNCTION</code> and <code>VIEW_DESCRIPTION_FUNCTION</code> settings.</li>
<li>Added <code>NUM_PROXIES</code> setting for smarter client IP identification.</li>
<li>Added <code>MAX_PAGINATE_BY</code> setting and <code>max_paginate_by</code> generic view attribute.</li>
<li>Added <code>Retry-After</code> header to throttled responses, as per <ahref="http://tools.ietf.org/html/rfc6585">RFC 6585</a>. This should now be used in preference to the custom <code>X-Trottle-Wait-Seconds</code> header which will be fully deprecated in 3.0.</li>
<li>Added <code>cache</code> attribute to throttles to allow overriding of default cache.</li>
<li>Added <code>lookup_value_regex</code> attribute to routers, to allow the URL argument matching to be constrainted by the user.</li>
<li>Added <code>allow_none</code> option to <code>CharField</code>.</li>
<li>Support Django's standard <code>status_code</code> class attribute on responses.</li>
<li>More intuitive behavior on the test client, as <code>client.logout()</code> now also removes any credentials that have been set.</li>
<li>Bugfix: <code>?page_size=0</code> query parameter now falls back to default page size for view, instead of always turning pagination off.</li>
<li>Bugfix: Copy <code>filter_backends</code> list before returning it, in order to prevent view code from mutating the class attribute itself.</li>
<li>Bugfix: Set the <code>.action</code> attribute on viewsets when introspected by <code>OPTIONS</code> for testing permissions on the view.</li>
<li>Bugfix: Ensure <code>ValueError</code> raised during deserialization results in a error list rather than a single error. This is now consistent with other validation errors.</li>
<li>Bugfix: Fix <code>cache_format</code> typo on throttle classes, was <code>"throtte_%(scope)s_%(ident)s"</code>. Note that this will invalidate existing throttle caches.</li>
</ul>
<hr/>
<h2id="23x-series">2.3.x series</h2>
<h2id="23x-series">2.3.x series</h2>
<h3id="2314">2.3.14</h3>
<h3id="2314">2.3.14</h3>
<p><strong>Date</strong>: 12th June 2014</p>
<p><strong>Date</strong>: 12th June 2014</p>
...
@@ -356,9 +382,9 @@ a.fusion-poweredby {
...
@@ -356,9 +382,9 @@ a.fusion-poweredby {
<li>Added <code>trailing_slash</code> option to routers.</li>
<li>Added <code>trailing_slash</code> option to routers.</li>
<li>Include support for <code>HttpStreamingResponse</code>.</li>
<li>Include support for <code>HttpStreamingResponse</code>.</li>
<li>Support wider range of default serializer validation when used with custom model fields.</li>
<li>Support wider range of default serializer validation when used with custom model fields.</li>
<li>UTF-8 Support for browsable API descriptions.</li>
<li>UTF-8 Support for browsable API descriptions.</li>
<li>OAuth2 provider uses timezone aware datetimes when supported.</li>
<li>OAuth2 provider uses timezone aware datetimes when supported.</li>
<li>Bugfix: Return error correctly when OAuth non-existent consumer occurs.</li>
<li>Bugfix: Return error correctly when OAuth non-existent consumer occurs.</li>
<li>Bugfix: Allow <code>FileUploadParser</code> to correctly filename if provided as URL kwarg.</li>
<li>Bugfix: Allow <code>FileUploadParser</code> to correctly filename if provided as URL kwarg.</li>
@@ -219,7 +219,7 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet):
...
@@ -219,7 +219,7 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet):
</code></pre>
</code></pre>
<p>Here we've used the <code>ReadOnlyModelViewSet</code> class to automatically provide the default 'read-only' operations. We're still setting the <code>queryset</code> and <code>serializer_class</code> attributes exactly as we did when we were using regular views, but we no longer need to provide the same information to two separate classes.</p>
<p>Here we've used the <code>ReadOnlyModelViewSet</code> class to automatically provide the default 'read-only' operations. We're still setting the <code>queryset</code> and <code>serializer_class</code> attributes exactly as we did when we were using regular views, but we no longer need to provide the same information to two separate classes.</p>
<p>Next we're going to replace the <code>SnippetList</code>, <code>SnippetDetail</code> and <code>SnippetHighlight</code> view classes. We can remove the three views, and again replace them with a single class.</p>
<p>Next we're going to replace the <code>SnippetList</code>, <code>SnippetDetail</code> and <code>SnippetHighlight</code> view classes. We can remove the three views, and again replace them with a single class.</p>
<preclass="prettyprint lang-py"><code>from rest_framework.decorators import link
@@ -242,8 +242,8 @@ class SnippetViewSet(viewsets.ModelViewSet):
...
@@ -242,8 +242,8 @@ class SnippetViewSet(viewsets.ModelViewSet):
obj.owner = self.request.user
obj.owner = self.request.user
</code></pre>
</code></pre>
<p>This time we've used the <code>ModelViewSet</code> class in order to get the complete set of default read and write operations.</p>
<p>This time we've used the <code>ModelViewSet</code> class in order to get the complete set of default read and write operations.</p>
<p>Notice that we've also used the <code>@link</code> decorator to create a custom action, named <code>highlight</code>. This decorator can be used to add any custom endpoints that don't fit into the standard <code>create</code>/<code>update</code>/<code>delete</code> style.</p>
<p>Notice that we've also used the <code>@detail_route</code> decorator to create a custom action, named <code>highlight</code>. This decorator can be used to add any custom endpoints that don't fit into the standard <code>create</code>/<code>update</code>/<code>delete</code> style.</p>
<p>Custom actions which use the <code>@link</code> decorator will respond to <code>GET</code> requests. We could have instead used the <code>@action</code> decorator if we wanted an action that responded to <code>POST</code> requests.</p>
<p>Custom actions which use the <code>@detail_route</code> decorator will respond to <code>GET</code> requests. We can use the <code>methods</code> argument if we wanted an action that responded to <code>POST</code> requests.</p>
<h2id="binding-viewsets-to-urls-explicitly">Binding ViewSets to URLs explicitly</h2>
<h2id="binding-viewsets-to-urls-explicitly">Binding ViewSets to URLs explicitly</h2>
<p>The handler methods only get bound to the actions when we define the URLConf.
<p>The handler methods only get bound to the actions when we define the URLConf.
To see what's going on under the hood let's first explicitly create a set of views from our ViewSets.</p>
To see what's going on under the hood let's first explicitly create a set of views from our ViewSets.</p>