Latest docs update

This commit is contained in:
Tom Christie 2014-08-28 17:33:56 +01:00
parent 66f25af53a
commit 9ae5a48332
15 changed files with 262 additions and 124 deletions

View File

@ -307,7 +307,9 @@ WSGIPassAuthorization On
'rest_framework.authtoken'
)
</code></pre>
<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 <a href="#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 <a href="#schema-migrations">Schema migrations</a> below.</p>
<hr />
<p>You'll also need to create tokens for your users.</p>
<pre class="prettyprint lang-py"><code>from rest_framework.authtoken.models import Token
@ -362,7 +364,10 @@ for user in User.objects.all():
</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>
<h4 id="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 &gt;1.7) and South migrations (for Django versions &lt;1.7) that will create the authtoken table.</p>
<hr />
<p><strong>Note</strong>: From REST Framework v2.4.0 using South with Django &lt;1.7 requires upgrading South v1.0+</p>
<hr />
<p>If you're using a <a href="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>
<pre class="prettyprint lang-py"><code>class Migration:

View File

@ -213,6 +213,7 @@ a.fusion-poweredby {
<li><a href="#drf-compound-fields">DRF Compound Fields</a></li>
<li><a href="#drf-extra-fields">DRF Extra Fields</a></li>
<li><a href="#django-rest-framework-gis">django-rest-framework-gis</a></li>
<li><a href="#django-rest-framework-hstore">django-rest-framework-hstore</a></li>
<div class="promo">
@ -329,10 +330,11 @@ class UserSerializer(serializers.ModelSerializer):
<p>A Boolean representation.</p>
<p>Corresponds to <code>django.db.models.fields.BooleanField</code>.</p>
<h2 id="charfield">CharField</h2>
<p>A text representation, optionally validates the text to be shorter than <code>max_length</code> and longer than <code>min_length</code>.</p>
<p>A text representation, optionally validates the text to be shorter than <code>max_length</code> and longer than <code>min_length</code>.
If <code>allow_none</code> is <code>False</code> (default), <code>None</code> values will be converted to an empty string.</p>
<p>Corresponds to <code>django.db.models.fields.CharField</code>
or <code>django.db.models.fields.TextField</code>.</p>
<p><strong>Signature:</strong> <code>CharField(max_length=None, min_length=None)</code></p>
<p><strong>Signature:</strong> <code>CharField(max_length=None, min_length=None, allow_none=False)</code></p>
<h2 id="urlfield">URLField</h2>
<p>Corresponds to <code>django.db.models.fields.URLField</code>. Uses Django's <code>django.core.validators.URLValidator</code> for validation.</p>
<p><strong>Signature:</strong> <code>URLField(max_length=200, min_length=None)</code></p>
@ -461,6 +463,8 @@ class ColourField(serializers.WritableField):
<p>The <a href="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>
<h2 id="django-rest-framework-gis">django-rest-framework-gis</h2>
<p>The <a href="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>
<h2 id="django-rest-framework-hstore">django-rest-framework-hstore</h2>
<p>The <a href="https://github.com/djangonauts/django-rest-framework-hstore">django-rest-framework-hstore</a> package provides an <code>HStoreField</code> to support <a href="https://github.com/djangonauts/django-hstore">django-hstore</a> <code>DictionaryField</code> model field.</p>
</div><!--/span-->
</div><!--/row-->
</div><!--/.fluid-container-->

View File

@ -262,7 +262,7 @@ class UserList(generics.ListCreateAPIView):
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
</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>
<pre class="prettyprint lang-py"><code>url(r'^/users/', ListCreateAPIView.as_view(model=User), name='user-list')
</code></pre>
<hr />
@ -300,7 +300,7 @@ class UserList(generics.ListCreateAPIView):
<h4 id="get_querysetself"><code>get_queryset(self)</code></h4>
<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>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>For example:</p>
<pre class="prettyprint lang-py"><code>def get_queryset(self):
user = self.request.user
@ -308,7 +308,7 @@ class UserList(generics.ListCreateAPIView):
</code></pre>
<h4 id="get_objectself"><code>get_object(self)</code></h4>
<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>
<p>For example:</p>
<pre class="prettyprint lang-py"><code>def get_object(self):
queryset = self.get_queryset()
@ -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>
<h4 id="get_filter_backendsself"><code>get_filter_backends(self)</code></h4>
<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>For example:</p>
<pre class="prettyprint lang-py"><code>def get_filter_backends(self):
if "geo_route" in self.request.QUERY_PARAMS:
@ -335,7 +335,7 @@ class UserList(generics.ListCreateAPIView):
</code></pre>
<h4 id="get_serializer_classself"><code>get_serializer_class(self)</code></h4>
<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>For example:</p>
<pre class="prettyprint lang-py"><code>def get_serializer_class(self):
if self.request.user.is_staff:
@ -344,7 +344,7 @@ class UserList(generics.ListCreateAPIView):
</code></pre>
<h4 id="get_paginate_byself"><code>get_paginate_by(self)</code></h4>
<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>
<p>For example:</p>
<pre class="prettyprint lang-py"><code>def get_paginate_by(self):
if self.request.accepted_renderer.format == 'html':
@ -378,7 +378,7 @@ class UserList(generics.ListCreateAPIView):
</ul>
<hr />
<h1 id="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>
<h2 id="listmodelmixin">ListModelMixin</h2>
<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>

View File

@ -190,6 +190,7 @@ a.fusion-poweredby {
<li><a href="#simplerouter">SimpleRouter</a></li>
<li><a href="#defaultrouter">DefaultRouter</a></li>
<li class="main"><a href="#custom-routers">Custom Routers</a></li>
<li><a href="#customizing-dynamic-routes">Customizing dynamic routes</a></li>
<li><a href="#example">Example</a></li>
<li><a href="#advanced-custom-routers">Advanced custom routers</a></li>
<li class="main"><a href="#third-party-packages">Third Party Packages</a></li>
@ -247,32 +248,36 @@ urlpatterns = router.urls
<p>This means you'll need to explicitly set the <code>base_name</code> argument when registering the viewset, as it could not be automatically determined from the model name.</p>
<hr />
<h3 id="extra-link-and-actions">Extra link and actions</h3>
<p>Any methods on the viewset decorated with <code>@link</code> or <code>@action</code> will also be routed.
<p>Any methods on the viewset decorated with <code>@detail_route</code> or <code>@list_route</code> will also be routed.
For example, given a method like this on the <code>UserViewSet</code> class:</p>
<pre class="prettyprint lang-py"><code>from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import action
from rest_framework.decorators import detail_route
@action(permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
class UserViewSet(ModelViewSet):
...
@detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
</code></pre>
<p>The following URL pattern would additionally be generated:</p>
<ul>
<li>URL pattern: <code>^users/{pk}/set_password/$</code> Name: <code>'user-set-password'</code></li>
</ul>
<p>For more information see the viewset documentation on <a href="viewsets.html#marking-extra-actions-for-routing">marking extra actions for routing</a>.</p>
<h1 id="api-guide">API Guide</h1>
<h2 id="simplerouter">SimpleRouter</h2>
<p>This router includes routes for the standard set of <code>list</code>, <code>create</code>, <code>retrieve</code>, <code>update</code>, <code>partial_update</code> and <code>destroy</code> actions. The viewset can also mark additional methods to be routed, using the <code>@link</code> or <code>@action</code> decorators.</p>
<p>This router includes routes for the standard set of <code>list</code>, <code>create</code>, <code>retrieve</code>, <code>update</code>, <code>partial_update</code> and <code>destroy</code> actions. The viewset can also mark additional methods to be routed, using the <code>@detail_route</code> or <code>@list_route</code> decorators.</p>
<table border=1>
<tr><th>URL Style</th><th>HTTP Method</th><th>Action</th><th>URL Name</th></tr>
<tr><td rowspan=2>{prefix}/</td><td>GET</td><td>list</td><td rowspan=2>{basename}-list</td></tr></tr>
<tr><td>POST</td><td>create</td></tr>
<tr><td>{prefix}/{methodname}/</td><td>GET, or as specified by `methods` argument</td><td>`@list_route` decorated method</td><td>{basename}-{methodname}</td></tr>
<tr><td rowspan=4>{prefix}/{lookup}/</td><td>GET</td><td>retrieve</td><td rowspan=4>{basename}-detail</td></tr></tr>
<tr><td>PUT</td><td>update</td></tr>
<tr><td>PATCH</td><td>partial_update</td></tr>
<tr><td>DELETE</td><td>destroy</td></tr>
<tr><td rowspan=2>{prefix}/{lookup}/{methodname}/</td><td>GET</td><td>@link decorated method</td><td rowspan=2>{basename}-{methodname}</td></tr>
<tr><td>POST</td><td>@action decorated method</td></tr>
<tr><td>{prefix}/{lookup}/{methodname}/</td><td>GET, or as specified by `methods` argument</td><td>`@detail_route` decorated method</td><td>{basename}-{methodname}</td></tr>
</table>
<p>By default the URLs created by <code>SimpleRouter</code> are appended with a trailing slash.
@ -280,6 +285,11 @@ This behavior can be modified by setting the <code>trailing_slash</code> argumen
<pre class="prettyprint lang-py"><code>router = SimpleRouter(trailing_slash=False)
</code></pre>
<p>Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.</p>
<p>The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the <code>lookup_value_regex</code> attribute on the viewset. For example, you can limit the lookup to valid UUIDs:</p>
<pre class="prettyprint lang-py"><code>class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_id'
lookup_value_regex = '[0-9a-f]{32}'
</code></pre>
<h2 id="defaultrouter">DefaultRouter</h2>
<p>This router is similar to <code>SimpleRouter</code> as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional <code>.json</code> style format suffixes.</p>
<table border=1>
@ -287,12 +297,12 @@ This behavior can be modified by setting the <code>trailing_slash</code> argumen
<tr><td>[.format]</td><td>GET</td><td>automatically generated root view</td><td>api-root</td></tr></tr>
<tr><td rowspan=2>{prefix}/[.format]</td><td>GET</td><td>list</td><td rowspan=2>{basename}-list</td></tr></tr>
<tr><td>POST</td><td>create</td></tr>
<tr><td>{prefix}/{methodname}/[.format]</td><td>GET, or as specified by `methods` argument</td><td>`@list_route` decorated method</td><td>{basename}-{methodname}</td></tr>
<tr><td rowspan=4>{prefix}/{lookup}/[.format]</td><td>GET</td><td>retrieve</td><td rowspan=4>{basename}-detail</td></tr></tr>
<tr><td>PUT</td><td>update</td></tr>
<tr><td>PATCH</td><td>partial_update</td></tr>
<tr><td>DELETE</td><td>destroy</td></tr>
<tr><td rowspan=2>{prefix}/{lookup}/{methodname}/[.format]</td><td>GET</td><td>@link decorated method</td><td rowspan=2>{basename}-{methodname}</td></tr>
<tr><td>POST</td><td>@action decorated method</td></tr>
<tr><td>{prefix}/{lookup}/{methodname}/[.format]</td><td>GET, or as specified by `methods` argument</td><td>`@detail_route` decorated method</td><td>{basename}-{methodname}</td></tr>
</table>
<p>As with <code>SimpleRouter</code> the trailing slashes on the URL routes can be removed by setting the <code>trailing_slash</code> argument to <code>False</code> when instantiating the router.</p>
@ -314,26 +324,75 @@ This behavior can be modified by setting the <code>trailing_slash</code> argumen
<li><code>{basename}</code> - The base to use for the URL names that are created.</li>
</ul>
<p><strong>initkwargs</strong>: A dictionary of any additional arguments that should be passed when instantiating the view. Note that the <code>suffix</code> argument is reserved for identifying the viewset type, used when generating the view name and breadcrumb links.</p>
<h2 id="customizing-dynamic-routes">Customizing dynamic routes</h2>
<p>You can also customize how the <code>@list_route</code> and <code>@detail_route</code> decorators are routed.
To route either or both of these decorators, include a <code>DynamicListRoute</code> and/or <code>DynamicDetailRoute</code> named tuple in the <code>.routes</code> list.</p>
<p>The arguments to <code>DynamicListRoute</code> and <code>DynamicDetailRoute</code> are:</p>
<p><strong>url</strong>: A string representing the URL to be routed. May include the same format strings as <code>Route</code>, and additionally accepts the <code>{methodname}</code> and <code>{methodnamehyphen}</code> format strings.</p>
<p><strong>name</strong>: The name of the URL as used in <code>reverse</code> calls. May include the following format strings: <code>{basename}</code>, <code>{methodname}</code> and <code>{methodnamehyphen}</code>.</p>
<p><strong>initkwargs</strong>: A dictionary of any additional arguments that should be passed when instantiating the view.</p>
<h2 id="example">Example</h2>
<p>The following example will only route to the <code>list</code> and <code>retrieve</code> actions, and does not use the trailing slash convention.</p>
<pre class="prettyprint lang-py"><code>from rest_framework.routers import Route, SimpleRouter
<pre class="prettyprint lang-py"><code>from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter
class ReadOnlyRouter(SimpleRouter):
class CustomReadOnlyRouter(SimpleRouter):
"""
A router for read-only APIs, which doesn't use trailing slashes.
"""
routes = [
Route(url=r'^{prefix}$',
mapping={'get': 'list'},
name='{basename}-list',
initkwargs={'suffix': 'List'}),
Route(url=r'^{prefix}/{lookup}$',
mapping={'get': 'retrieve'},
name='{basename}-detail',
initkwargs={'suffix': 'Detail'})
Route(
url=r'^{prefix}$',
mapping={'get': 'list'},
name='{basename}-list',
initkwargs={'suffix': 'List'}
),
Route(
url=r'^{prefix}/{lookup}$',
mapping={'get': 'retrieve'},
name='{basename}-detail',
initkwargs={'suffix': 'Detail'}
),
DynamicDetailRoute(
url=r'^{prefix}/{lookup}/{methodnamehyphen}$',
name='{basename}-{methodnamehyphen}',
initkwargs={}
)
]
</code></pre>
<p>The <code>SimpleRouter</code> class provides another example of setting the <code>.routes</code> attribute.</p>
<p>Let's take a look at the routes our <code>CustomReadOnlyRouter</code> would generate for a simple viewset.</p>
<p><code>views.py</code>:</p>
<pre class="prettyprint lang-py"><code>class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
A viewset that provides the standard actions
"""
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_field = 'username'
@detail_route()
def group_names(self, request):
"""
Returns a list of all the group names that the given
user belongs to.
"""
user = self.get_object()
groups = user.groups.all()
return Response([group.name for group in groups])
</code></pre>
<p><code>urls.py</code>:</p>
<pre class="prettyprint lang-py"><code>router = CustomReadOnlyRouter()
router.register('users', UserViewSet)
urlpatterns = router.urls
</code></pre>
<p>The following mappings would be generated...</p>
<table border=1>
<tr><th>URL</th><th>HTTP Method</th><th>Action</th><th>URL Name</th></tr>
<tr><td>/users</td><td>GET</td><td>list</td><td>user-list</td></tr>
<tr><td>/users/{username}</td><td>GET</td><td>retrieve</td><td>user-detail</td></tr>
<tr><td>/users/{username}/group-names</td><td>GET</td><td>group_names</td><td>user-group-names</td></tr>
</table>
<p>For another example of setting the <code>.routes</code> attribute, see the source code for the <code>SimpleRouter</code> class.</p>
<h2 id="advanced-custom-routers">Advanced custom routers</h2>
<p>If you want to provide totally custom behavior, you can override <code>BaseRouter</code> and override the <code>get_urls(self)</code> method. The method should inspect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the <code>self.registry</code> attribute. </p>
<p>You may also want to override the <code>get_default_base_name(self, viewset)</code> method, or else always explicitly set the <code>base_name</code> argument when registering your viewsets with the router.</p>

View File

@ -209,6 +209,7 @@ a.fusion-poweredby {
<li class="main"><a href="#third-party-packages">Third party packages</a></li>
<li><a href="#mongoenginemodelserializer">MongoengineModelSerializer</a></li>
<li><a href="#geofeaturemodelserializer">GeoFeatureModelSerializer</a></li>
<li><a href="#hstoreserializer">HStoreSerializer</a></li>
<div class="promo">
@ -672,6 +673,8 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<p>The <a href="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>
<h2 id="geofeaturemodelserializer">GeoFeatureModelSerializer</h2>
<p>The <a href="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>
<h2 id="hstoreserializer">HStoreSerializer</h2>
<p>The <a href="https://github.com/djangonauts/django-rest-framework-hstore">django-rest-framework-hstore</a> package provides an <code>HStoreSerializer</code> to support <a href="https://github.com/djangonauts/django-hstore">django-hstore</a> <code>DictionaryField</code> model field and its <code>schema-mode</code> feature.</p>
</div><!--/span-->
</div><!--/row-->
</div><!--/.fluid-container-->

View File

@ -434,6 +434,9 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<h4 id="format_suffix_kwarg">FORMAT_SUFFIX_KWARG</h4>
<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>
<h4 id="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>
<p>Default: <code>None</code></p>
</div><!--/span-->
</div><!--/row-->
</div><!--/.fluid-container-->

View File

@ -229,7 +229,7 @@ If any throttle check fails an <code>exceptions.Throttled</code> exception will
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
}
</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>
@ -257,6 +257,11 @@ def example_view(request, format=None):
}
return Response(content)
</code></pre>
<h2 id="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 <a href="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 <a href="http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster">found here</a>.</p>
<h2 id="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 <a href="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 <a href="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>

View File

@ -186,7 +186,7 @@ a.fusion-poweredby {
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main"><a href="#viewsets">ViewSets</a></li>
<li><a href="#example">Example</a></li>
<li><a href="#marking-extra-methods-for-routing">Marking extra methods for routing</a></li>
<li><a href="#marking-extra-actions-for-routing">Marking extra actions for routing</a></li>
<li class="main"><a href="#api-reference">API Reference</a></li>
<li><a href="#viewset">ViewSet</a></li>
<li><a href="#genericviewset">GenericViewSet</a></li>
@ -263,7 +263,7 @@ urlpatterns = router.urls
<li>By using routers, we no longer need to deal with wiring up the URL conf ourselves.</li>
</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>
<h2 id="marking-extra-methods-for-routing">Marking extra methods for routing</h2>
<h2 id="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>
<pre class="prettyprint lang-py"><code>class UserViewSet(viewsets.ViewSet):
"""
@ -292,12 +292,13 @@ urlpatterns = router.urls
def destroy(self, request, pk=None):
pass
</code></pre>
<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>
<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
from rest_framework import viewsets
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 myapp.serializers import UserSerializer, PasswordSerializer
@ -308,7 +309,7 @@ class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
@action()
@detail_route(methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.DATA)
@ -319,14 +320,21 @@ class UserViewSet(viewsets.ModelViewSet):
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
@list_route()
def recent_users(self, request):
recent_users = User.objects.all().order('-last_login')
page = self.paginate_queryset(recent_users)
serializer = self.get_pagination_serializer(page)
return Response(serializer.data)
</code></pre>
<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>
<pre class="prettyprint lang-py"><code> @action(permission_classes=[IsAdminOrIsSelf])
<p>The decorators can additionally take extra arguments that will be set for the routed view only. For example...</p>
<pre class="prettyprint lang-py"><code> @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
</code></pre>
<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>
<pre class="prettyprint lang-py"><code> @action(methods=['POST', 'DELETE'])
<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>
<pre class="prettyprint lang-py"><code> @detail_route(methods=['post', 'delete'])
def unset_password(self, request, pk=None):
...
</code></pre>

BIN
img/sponsors/2-wusawork.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -252,7 +252,7 @@ a.fusion-poweredby {
<p>REST framework requires the following:</p>
<ul>
<li>Python (2.6.5+, 2.7, 3.2, 3.3)</li>
<li>Django (1.3, 1.4, 1.5, 1.6)</li>
<li>Django (1.4.2+, 1.5, 1.6, 1.7)</li>
</ul>
<p>The following packages are optional:</p>
<ul>
@ -389,16 +389,9 @@ urlpatterns = patterns('',
<li><a href="topics/credits">Credits</a></li>
</ul>
<h2 id="development">Development</h2>
<p>If you want to work on REST framework itself, clone the repository, then...</p>
<p>Build the docs:</p>
<pre class="prettyprint lang-py"><code>./mkdocs.py
</code></pre>
<p>Run the tests:</p>
<pre class="prettyprint lang-py"><code>./rest_framework/runtests/runtests.py
</code></pre>
<p>To run the tests against all supported configurations, first install <a href="http://testrun.org/tox/latest/">the tox testing tool</a> globally, using <code>pip install tox</code>, then simply run <code>tox</code>:</p>
<pre class="prettyprint lang-py"><code>tox
</code></pre>
<p>See the <a href="topics/contributing">Contribution guidelines</a> for information on how to clone
the repository, run the test suite and contribute changes back to REST
Framework.</p>
<h2 id="support">Support</h2>
<p>For support please see the <a href="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 <a href="https://botbot.me/freenode/restframework/">the IRC archives</a>, or raise a question on <a href="http://stackoverflow.com/">Stack Overflow</a>, making sure to include the <a href="http://stackoverflow.com/questions/tagged/django-rest-framework">'django-rest-framework'</a> tag.</p>
<p><a href="http://dabapps.com/services/build/api-development/">Paid support is available</a> from <a href="http://dabapps.com">DabApps</a>, and can include work on REST framework core, or support with building your REST framework API. Please <a href="http://dabapps.com/contact/">contact DabApps</a> if you'd like to discuss commercial support options.</p>

View File

@ -3,17 +3,17 @@
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>REST framework 2.4 announcement - Django REST framework</title>
<link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="canonical" href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/2.4-accouncement.html"/>
<link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="canonical" href="http://www.django-rest-framework.org/topics/2.4-accouncement"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Django, API, REST, REST framework 2.4 announcement">
<meta name="author" content="Tom Christie">
<!-- Le styles -->
<link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//css/prettify.css" rel="stylesheet">
<link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//css/bootstrap.css" rel="stylesheet">
<link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//css/bootstrap-responsive.css" rel="stylesheet">
<link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//css/default.css" rel="stylesheet">
<link href="http://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
<link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
<link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
<link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
@ -65,65 +65,65 @@ a.fusion-poweredby {
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="file:///Users/tomchristie/GitHub/django-rest-framework/html/index.html">Django REST framework</a>
<a class="brand" href="http://www.django-rest-framework.org">Django REST framework</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html/index.html">Home</a></li>
<li><a href="http://www.django-rest-framework.org">Home</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/quickstart.html">Quickstart</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/1-serialization.html">1 - Serialization</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/3-class-based-views.html">3 - Class based views</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
<li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
<li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
<li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
<li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
<li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
<li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
<li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/requests.html">Requests</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/responses.html">Responses</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/views.html">Views</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/generic-views.html">Generic views</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/viewsets.html">Viewsets</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/routers.html">Routers</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/parsers.html">Parsers</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/renderers.html">Renderers</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/serializers.html">Serializers</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/fields.html">Serializer fields</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/relations.html">Serializer relations</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/authentication.html">Authentication</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/permissions.html">Permissions</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/throttling.html">Throttling</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/filtering.html">Filtering</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/pagination.html">Pagination</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/content-negotiation.html">Content negotiation</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/format-suffixes.html">Format suffixes</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/reverse.html">Returning URLs</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/exceptions.html">Exceptions</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/status-codes.html">Status codes</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/testing.html">Testing</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/settings.html">Settings</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
<li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/documenting-your-api.html">Documenting your API</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/browser-enhancements.html">Browser enhancements</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/browsable-api.html">The Browsable API</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/contributing.html">Contributing to REST framework</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/2.2-announcement.html">2.2 Announcement</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/2.3-announcement.html">2.3 Announcement</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/kickstarter-announcement.html">Kickstarter Announcement</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/release-notes.html">Release Notes</a></li>
<li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/credits.html">Credits</a></li>
<li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
<li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
<li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
<li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
<li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
<li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
<li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
<li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
<li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
<li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
<li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
<li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
</ul>
</li>
</ul>
@ -189,6 +189,7 @@ a.fusion-poweredby {
<li><a href="#django-17-support">Django 1.7 support</a></li>
<li><a href="#updated-test-runner">Updated test runner</a></li>
<li><a href="#improved-viewset-routing">Improved viewset routing</a></li>
<li><a href="#throttle-behavior">Throttle behavior</a></li>
<li><a href="#other-features">Other features</a></li>
<li><a href="#deprecations">Deprecations</a></li>
<li><a href="#labels-and-milestones">Labels and milestones</a></li>
@ -246,7 +247,7 @@ The lowest supported version of Django is now 1.4.2.</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>
<h2 id="improved-viewset-routing">Improved viewset routing</h2>
<p>The <code>@action</code> and <code>@link</code> decorators were inflexible in that they only allowed additional routes to be added against instance style URLs, not against list style URLs.</p>
<p>The <code>@action</code> and <code>@link</code> decorators have now been moved to pending deprecation, and the <code>@list_route</code> and <code>@detail_route</code> decroators have been introduced.</p>
<p>The <code>@action</code> and <code>@link</code> decorators have now been moved to pending deprecation, and the <code>@list_route</code> and <code>@detail_route</code> decorators have been introduced.</p>
<p>Here's an example of using the new decorators. Firstly we have a detail-type route named "set_password" that acts on a single instance, and takes a <code>pk</code> argument in the URL. Secondly we have a list-type route named "recent_users" that acts on a queryset, and does not take any arguments in the URL.</p>
<pre class="prettyprint lang-py"><code>class UserViewSet(viewsets.ModelViewSet):
"""
@ -274,11 +275,20 @@ The lowest supported version of Django is now 1.4.2.</p>
serializer = self.get_pagination_serializer(page)
return Response(serializer.data)
</code></pre>
<p>For more details, see the <a href="../api-guide/viewsets.html">viewsets documentation</a>.</p>
<p>For more details, see the <a href="../api-guide/viewsets">viewsets documentation</a>.</p>
<h2 id="throttle-behavior">Throttle behavior</h2>
<p>There's one bugfix in 2.4 that's worth calling out, as it will <em>invalidate existing throttle caches</em> when you upgrade.</p>
<p>We've now fixed a typo on the <code>cache_format</code> attribute. Previously this was named <code>"throtte_%(scope)s_%(ident)s"</code>, it is now <code>"throttle_%(scope)s_%(ident)s"</code>.</p>
<p>If you're concerned about the invalidation you have two options.</p>
<ul>
<li>Manually pre-populate your cache with the fixed version.</li>
<li>Set the <code>cache_format</code> attribute on your throttle class in order to retain the previous incorrect spelling.</li>
</ul>
<h2 id="other-features">Other features</h2>
<p>There are also a number of other features and bugfixes as <a href="./topics/release-notes/#240">listed in the release notes</a>. In particular these include:</p>
<p><a href="../api-guide/settings/#view-names-and-descriptions">Customizable view name and description functions</a> for use with the browsable API, by using the <code>VIEW_NAME_FUNCTION</code> and <code>VIEW_DESCRIPTION_FUNCTION</code> settings.</p>
<p>Smarter <a href="../api-guide/throttling/#how-clients-are-identified">client IP identification for throttling</a>, with the addition of the <code>NUM_PROXIES</code> setting.</p>
<p>Added the standardized <code>Retry-After</code> header to throttled responses, as per <a href="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.</p>
<h2 id="deprecations">Deprecations</h2>
<p>All API changes in 2.3 that previously raised <code>PendingDeprecationWarning</code> will now raise a <code>DeprecationWarning</code>, which is loud by default.</p>
<p>All API changes in 2.3 that previously raised <code>DeprecationWarning</code> have now been removed entirely.</p>
@ -289,7 +299,7 @@ The lowest supported version of Django is now 1.4.2.</p>
<p>We've also <a href="https://github.com/tomchristie/django-rest-framework/milestones">started using milestones</a> in order to track tickets against particular releases.</p>
<hr />
<p><img alt="Labels and milestones" src="../img/labels-and-milestones.png" /></p>
<p><strong>Above</strong>: <em>Overview of our use of labels and milestones in GitHub.</em></p>
<p><strong>Above</strong>: <em>Overview of our current use of labels and milestones in GitHub.</em></p>
<hr />
<p>We hope both of these changes will help make the management process more clear and obvious and help keep tickets well-organised and relevant.</p>
<h2 id="next-steps">Next steps</h2>
@ -310,9 +320,9 @@ The lowest supported version of Django is now 1.4.2.</p>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="file:///Users/tomchristie/GitHub/django-rest-framework/html//js/jquery-1.8.1-min.js"></script>
<script src="file:///Users/tomchristie/GitHub/django-rest-framework/html//js/prettify-1.0.js"></script>
<script src="file:///Users/tomchristie/GitHub/django-rest-framework/html//js/bootstrap-2.1.1-min.js"></script>
<script src="http://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
<script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
<script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
<script>
//$('.side-nav').scrollspy()

View File

@ -255,11 +255,35 @@ a.fusion-poweredby {
virtualenv env
source env/bin/activate
pip install -r requirements.txt
pip install -r optionals.txt
pip install -r requirements-test.txt
# Run the tests
rest_framework/runtests/runtests.py
./runtests.py
</code></pre>
<h3 id="test-options">Test options</h3>
<p>Run using a more concise output style.</p>
<pre class="prettyprint lang-py"><code>./runtests -q
</code></pre>
<p>Run the tests using a more concise output style, no coverage, no flake8.</p>
<pre class="prettyprint lang-py"><code>./runtests --fast
</code></pre>
<p>Don't run the flake8 code linting.</p>
<pre class="prettyprint lang-py"><code>./runtests --nolint
</code></pre>
<p>Only run the flake8 code linting, don't run the tests.</p>
<pre class="prettyprint lang-py"><code>./runtests --lintonly
</code></pre>
<p>Run the tests for a given test case.</p>
<pre class="prettyprint lang-py"><code>./runtests MyTestCase
</code></pre>
<p>Run the tests for a given test method.</p>
<pre class="prettyprint lang-py"><code>./runtests MyTestCase.test_this_method
</code></pre>
<p>Shorter form to run the tests for a given test method.</p>
<pre class="prettyprint lang-py"><code>./runtests test_this_method
</code></pre>
<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>
<h3 id="running-against-multiple-environments">Running against multiple environments</h3>
<p>You can also use the excellent <a href="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>
<pre class="prettyprint lang-py"><code>tox
</code></pre>

View File

@ -262,7 +262,7 @@ a.fusion-poweredby {
<li><a href="https://opbeat.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-opbeat.png);">Opbeat</a></li>
<li><a href="https://koordinates.com" rel="nofollow" style="background-image:url(../img/sponsors/2-koordinates.png);">Koordinates</a></li>
<li><a href="http://pulsecode.ca" rel="nofollow" style="background-image:url(../img/sponsors/2-pulsecode.png);">Pulsecode Inc.</a></li>
<li><a href="http://singinghorsestudio.com" rel="nofollow" style="background-image:url(../img/sponsors/2-singing-horse.png);">Singing Horse Studio. Ltd.</a></li>
<li><a href="http://singinghorsestudio.com" rel="nofollow" style="background-image:url(../img/sponsors/2-singing-horse.png);">Singing Horse Studio Ltd.</a></li>
<li><a href="https://www.heroku.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-heroku.png);">Heroku</a></li>
<li><a href="https://www.galileo-press.de/" rel="nofollow" style="background-image:url(../img/sponsors/2-galileo_press.png);">Galileo Press</a></li>
<li><a href="http://www.securitycompass.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-security_compass.png);">Security Compass</a></li>
@ -272,12 +272,10 @@ a.fusion-poweredby {
<li><a href="http://crypticocorp.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-cryptico.png);">Cryptico Corp</a></li>
<li><a href="http://www.nexthub.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-nexthub.png);">NextHub</a></li>
<li><a href="https://www.compile.com/" rel="nofollow" style="background-image:url(../img/sponsors/2-compile.png);">Compile</a></li>
<li><a href="http://wusawork.org" rel="nofollow" style="background-image:url(../img/sponsors/2-wusawork.png);>WusaWork</a></li>
<li><a href="http://envisionlinux.org/blog" rel="nofollow">Envision Linux</a></li>
</ul>
<div style="clear: both; padding-bottom: 40px;"></div>
<p><strong>Individual backers</strong>: Simon Haugk.</p>
<hr />
<h3 id="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&nbsp;you to individuals who have choosen to privately support the project at this level.</p>
@ -321,7 +319,7 @@ a.fusion-poweredby {
<div style="clear: both; padding-bottom: 40px;"></div>
<p><strong>Individual backers</strong>: Paul Hallet, <a href="http://www.paulwhippconsulting.com/">Paul Whipp</a>, Dylan Roy, Jannis Leidel, <a href="https://linovia.com/en/">Xavier Ordoquy</a>, <a href="http://spielmannsolutions.com/">Johannes Spielmann</a>, <a href="http://brooklynhacker.com/">Rob Spectre</a>, <a href="http://chrisheisel.com/">Chris Heisel</a>, Marwan Alsabbagh, Haris Ali, Tuomas Toivonen.</p>
<p><strong>Individual backers</strong>: Paul Hallett, <a href="http://www.paulwhippconsulting.com/">Paul Whipp</a>, Dylan Roy, Jannis Leidel, <a href="https://linovia.com/en/">Xavier Ordoquy</a>, <a href="http://spielmannsolutions.com/">Johannes Spielmann</a>, <a href="http://brooklynhacker.com/">Rob Spectre</a>, <a href="http://chrisheisel.com/">Chris Heisel</a>, Marwan Alsabbagh, Haris Ali, Tuomas Toivonen.</p>
<hr />
<h3 id="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>

View File

@ -188,6 +188,7 @@ a.fusion-poweredby {
<li><a href="#versioning">Versioning</a></li>
<li><a href="#deprecation-policy">Deprecation policy</a></li>
<li><a href="#upgrading">Upgrading</a></li>
<li><a href="#24x-series">2.4.x series</a></li>
<li><a href="#23x-series">2.3.x series</a></li>
<li><a href="#22x-series">2.2.x series</a></li>
<li><a href="#21x-series">2.1.x series</a></li>
@ -238,6 +239,31 @@ a.fusion-poweredby {
<pre class="prettyprint lang-py"><code>pip freeze | grep djangorestframework
</code></pre>
<hr />
<h2 id="24x-series">2.4.x series</h2>
<h3 id="240">2.4.0</h3>
<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 <a href="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: Always uppercase <code>X-Http-Method-Override</code> methods.</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 />
<h2 id="23x-series">2.3.x series</h2>
<h3 id="2314">2.3.14</h3>
<p><strong>Date</strong>: 12th June 2014</p>
@ -356,9 +382,9 @@ a.fusion-poweredby {
<li>Added <code>trailing_slash</code> option to routers.</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>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>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: Fix <code>ScopedRateThrottle</code>.</li>
</ul>
@ -395,7 +421,7 @@ a.fusion-poweredby {
<li>Added SearchFilter</li>
<li>Added OrderingFilter</li>
<li>Added GenericViewSet</li>
<li>Bugfix: Multiple <code>@action</code> and <code>@link</code> methods now allowed on viewsets. </li>
<li>Bugfix: Multiple <code>@action</code> and <code>@link</code> methods now allowed on viewsets.</li>
<li>Bugfix: Fix API Root view issue with DjangoModelPermissions</li>
</ul>
<h3 id="232">2.3.2</h3>
@ -440,7 +466,7 @@ a.fusion-poweredby {
<li>Long HTTP headers in browsable API are broken in multiple lines when possible.</li>
<li>Bugfix: Fix regression with DjangoFilterBackend not worthing correctly with single object views.</li>
<li>Bugfix: OAuth should fail hard when invalid token used.</li>
<li>Bugfix: Fix serializer potentially returning <code>None</code> object for models that define <code>__bool__</code> or <code>__len__</code>. </li>
<li>Bugfix: Fix serializer potentially returning <code>None</code> object for models that define <code>__bool__</code> or <code>__len__</code>.</li>
</ul>
<h3 id="225">2.2.5</h3>
<p><strong>Date</strong>: 26th March 2013</p>

View File

@ -219,7 +219,7 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet):
</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>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>
<pre class="prettyprint lang-py"><code>from rest_framework.decorators import link
<pre class="prettyprint lang-py"><code>from rest_framework.decorators import detail_route
class SnippetViewSet(viewsets.ModelViewSet):
"""
@ -233,7 +233,7 @@ class SnippetViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
@link(renderer_classes=[renderers.StaticHTMLRenderer])
@detail_route(renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
@ -242,8 +242,8 @@ class SnippetViewSet(viewsets.ModelViewSet):
obj.owner = self.request.user
</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>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>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>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>@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>
<h2 id="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.
To see what's going on under the hood let's first explicitly create a set of views from our ViewSets.</p>