Latest docs build

This commit is contained in:
Tom Christie 2012-10-19 20:00:35 +01:00
parent f817d4335a
commit 2a0d9b2e3c
16 changed files with 155 additions and 47 deletions

View File

@ -143,9 +143,9 @@
<p>If no class authenticates, <code>request.user</code> will be set to an instance of <code>django.contrib.auth.models.AnonymousUser</code>, and <code>request.auth</code> will be set to <code>None</code>.</p> <p>If no class authenticates, <code>request.user</code> will be set to an instance of <code>django.contrib.auth.models.AnonymousUser</code>, and <code>request.auth</code> will be set to <code>None</code>.</p>
<p>The value of <code>request.user</code> and <code>request.auth</code> for unauthenticated requests can be modified using the <code>UNAUTHENTICATED_USER</code> and <code>UNAUTHENTICATED_TOKEN</code> settings.</p> <p>The value of <code>request.user</code> and <code>request.auth</code> for unauthenticated requests can be modified using the <code>UNAUTHENTICATED_USER</code> and <code>UNAUTHENTICATED_TOKEN</code> settings.</p>
<h2 id="setting-the-authentication-policy">Setting the authentication policy</h2> <h2 id="setting-the-authentication-policy">Setting the authentication policy</h2>
<p>The default authentication policy may be set globally, using the <code>DEFAULT_AUTHENTICATION</code> setting. For example.</p> <p>The default authentication policy may be set globally, using the <code>DEFAULT_AUTHENTICATION_CLASSES</code> setting. For example.</p>
<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = { <pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION': ( 'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.UserBasicAuthentication', 'rest_framework.authentication.UserBasicAuthentication',
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
) )

View File

@ -113,6 +113,9 @@
<div id="table-of-contents"> <div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed"> <ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main"><a href="#content-negotiation">Content negotiation</a></li> <li class="main"><a href="#content-negotiation">Content negotiation</a></li>
<li><a href="#determining-the-accepted-renderer">Determining the accepted renderer</a></li>
<li class="main"><a href="#custom-content-negotiation">Custom content negotiation</a></li>
<li><a href="#example">Example</a></li>
</ul> </ul>
</div> </div>
@ -125,6 +128,47 @@
<p>HTTP has provisions for several mechanisms for "content negotiation" - the process of selecting the best representation for a given response when there are multiple representations available.</p> <p>HTTP has provisions for several mechanisms for "content negotiation" - the process of selecting the best representation for a given response when there are multiple representations available.</p>
<p>&mdash; <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html">RFC 2616</a>, Fielding et al.</p> <p>&mdash; <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html">RFC 2616</a>, Fielding et al.</p>
</blockquote> </blockquote>
<p>Content negotiation is the process of selecting one of multiple possible representations to return to a client, based on client or server preferences.</p>
<h2 id="determining-the-accepted-renderer">Determining the accepted renderer</h2>
<p>REST framework uses a simple style of content negotition to determine which media type should be returned to a client, based on the available renderers, the priorities of each of those renderers, and the client's <code>Accept:</code> header. The style used is partly client-driven, and partly server-driven.</p>
<ol>
<li>More specific media types are given preference to less specific media types.</li>
<li>If multiple media types have the same specificity, then preference is given to based on the ordering of the renderers configured for the given view.</li>
</ol>
<p>For example, given the following <code>Accept</code> header:</p>
<pre class="prettyprint lang-py"><code>application/json; indent=4, application/json, application/yaml, text/html, */*
</code></pre>
<p>The priorities for each of the given media types would be:</p>
<ul>
<li><code>application/json; indent=4</code></li>
<li><code>application/json</code>, <code>application/yaml</code> and <code>text/html</code></li>
<li><code>*/*</code></li>
</ul>
<p>If the requested view was only configured with renderers for <code>YAML</code> and <code>HTML</code>, then REST framework would select whichever renderer was listed first in the <code>renderer_classes</code> list or <code>DEFAULT_RENDERER_CLASSES</code> setting.</p>
<p>For more information on the <code>HTTP Accept</code> header, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">RFC 2616</a> </p>
<hr />
<p><strong>Note</strong>: "q" values are not taken into account by REST framework when determining preference. The use of "q" values negatively impacts caching, and in the author's opinion they are an unnecessary and overcomplicated approach to content negotiation.</p>
<p>This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.</p>
<hr />
<h1 id="custom-content-negotiation">Custom content negotiation</h1>
<p>It's unlikley that you'll want to provide a custom content negotiation scheme for REST framework, but you can do so if needed. To implement a custom content negotiation scheme override <code>BaseContentNegotiation</code>.</p>
<p>REST framework's content negotiation classes handle selection of both the approprate parser for the requesr, and the appropriate renderer for the response, so you should implement both the <code>.select_parser(request, parsers)</code> and <code>.select_renderer(request, renderers, format_suffix)</code> methods.</p>
<h2 id="example">Example</h2>
<p>The following is a custom content negotiation class which ignores the client
request when selecting the appropriate parser or renderer.</p>
<pre class="prettyprint lang-py"><code>class IgnoreClientContentNegotiation(BaseContentNegotiation):
def select_parser(self, request, parsers):
"""
Select the first parser in the `.parser_classes` list.
"""
return parsers[0]
def select_renderer(self, request, renderers, format_suffix):
"""
Select the first renderer in the `.renderer_classes` list.
"""
return renderers[0]
</code></pre>
</div><!--/span--> </div><!--/span-->
</div><!--/row--> </div><!--/row-->
</div><!--/.fluid-container--> </div><!--/.fluid-container-->

View File

@ -114,6 +114,7 @@
<ul class="nav nav-list side-nav well sidebar-nav-fixed"> <ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main"><a href="#exceptions">Exceptions</a></li> <li class="main"><a href="#exceptions">Exceptions</a></li>
<li><a href="#exception-handling-in-rest-framework-views">Exception handling in REST framework views</a></li> <li><a href="#exception-handling-in-rest-framework-views">Exception handling in REST framework views</a></li>
<li class="main"><a href="#api-reference">API Reference</a></li>
<li><a href="#apiexception">APIException</a></li> <li><a href="#apiexception">APIException</a></li>
<li><a href="#parseerror">ParseError</a></li> <li><a href="#parseerror">ParseError</a></li>
<li><a href="#permissiondenied">PermissionDenied</a></li> <li><a href="#permissiondenied">PermissionDenied</a></li>
@ -153,6 +154,8 @@ Content-Length: 42
{"detail": "Method 'DELETE' not allowed."} {"detail": "Method 'DELETE' not allowed."}
</code></pre> </code></pre>
<hr />
<h1 id="api-reference">API Reference</h1>
<h2 id="apiexception">APIException</h2> <h2 id="apiexception">APIException</h2>
<p><strong>Signature:</strong> <code>APIException(detail=None)</code></p> <p><strong>Signature:</strong> <code>APIException(detail=None)</code></p>
<p>The <strong>base class</strong> for all exceptions raised inside REST framework.</p> <p>The <strong>base class</strong> for all exceptions raised inside REST framework.</p>

View File

@ -113,6 +113,8 @@
<div id="table-of-contents"> <div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed"> <ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main"><a href="#format-suffixes">Format suffixes</a></li> <li class="main"><a href="#format-suffixes">Format suffixes</a></li>
<li><a href="#format_suffix_patterns">format_suffix_patterns</a></li>
<li><a href="#accept-headers-vs-format-suffixes">Accept headers vs. format suffixes</a></li>
</ul> </ul>
</div> </div>
@ -126,6 +128,42 @@
used all the time.</p> used all the time.</p>
<p>&mdash; Roy Fielding, <a href="http://tech.groups.yahoo.com/group/rest-discuss/message/5857">REST discuss mailing list</a></p> <p>&mdash; Roy Fielding, <a href="http://tech.groups.yahoo.com/group/rest-discuss/message/5857">REST discuss mailing list</a></p>
</blockquote> </blockquote>
<p>A common pattern for Web APIs is to use filename extensions on URLs to provide an endpoint for a given media type. For example, 'http://example.com/api/users.json' to serve a JSON representation. </p>
<p>Adding format-suffix patterns to each individual entry in the URLconf for your API is error-prone and non-DRY, so REST framework provides a shortcut to adding these patterns to your URLConf.</p>
<h2 id="format_suffix_patterns">format_suffix_patterns</h2>
<p><strong>Signature</strong>: format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None)</p>
<p>Returns a URL pattern list which includes format suffix patterns appended to each of the URL patterns provided.</p>
<p>Arguments:</p>
<ul>
<li><strong>urlpatterns</strong>: Required. A URL pattern list.</li>
<li><strong>suffix_required</strong>: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to <code>False</code>, meaning that suffixes are optional by default.</li>
<li><strong>allowed</strong>: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used. </li>
</ul>
<p>Example:</p>
<pre class="prettyprint lang-py"><code>from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = patterns('blog.views',
url(r'^/$', 'api_root'),
url(r'^comment/$', 'comment_root'),
url(r'^comment/(?P&lt;pk&gt;[0-9]+)/$', 'comment_instance')
)
urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
</code></pre>
<p>When using <code>format_suffix_patterns</code>, you must make sure to add the <code>'format'</code> keyword argument to the corresponding views. For example.</p>
<pre class="prettyprint lang-py"><code>@api_view(('GET',))
def api_root(request, format=None):
# do stuff...
</code></pre>
<p>The name of the kwarg used may be modified by using the <code>FORMAT_SUFFIX_KWARG</code> setting.</p>
<p>Also note that <code>format_suffix_patterns</code> does not support descending into <code>include</code> URL patterns.</p>
<hr />
<h2 id="accept-headers-vs-format-suffixes">Accept headers vs. format suffixes</h2>
<p>There seems to be a view among some of the Web community that filename extensions are not a RESTful pattern, and that <code>HTTP Accept</code> headers should always be used instead.<br />
</p>
<p>It is actually a misconception. For example, take the following quote from Roy Fielding discussing the relative merits of query parameter media-type indicators vs. file extension media-type indicators: </p>
<p>&ldquo;That's why I always prefer extensions. Neither choice has anything to do with REST.&rdquo; &mdash; Roy Fielding, <a href="http://tech.groups.yahoo.com/group/rest-discuss/message/14844">REST discuss mailing list</a></p>
<p>The quote does not mention Accept headers, but it does make it clear that format suffixes should be considered an acceptable pattern.</p>
</div><!--/span--> </div><!--/span-->
</div><!--/row--> </div><!--/row-->
</div><!--/.fluid-container--> </div><!--/.fluid-container-->

View File

@ -116,7 +116,8 @@
<li><a href="#paginating-basic-data">Paginating basic data</a></li> <li><a href="#paginating-basic-data">Paginating basic data</a></li>
<li><a href="#paginating-querysets">Paginating QuerySets</a></li> <li><a href="#paginating-querysets">Paginating QuerySets</a></li>
<li><a href="#pagination-in-the-generic-views">Pagination in the generic views</a></li> <li><a href="#pagination-in-the-generic-views">Pagination in the generic views</a></li>
<li><a href="#custom-pagination-serializers">Custom pagination serializers</a></li> <li class="main"><a href="#custom-pagination-serializers">Custom pagination serializers</a></li>
<li><a href="#example">Example</a></li>
</ul> </ul>
</div> </div>
@ -208,9 +209,11 @@ def user_list(request):
paginate_by = 10 paginate_by = 10
</code></pre> </code></pre>
<p>For more complex requirements such as serialization that differs depending on the requested media type you can override the <code>.get_paginate_by()</code> and <code>.get_pagination_serializer_class()</code> methods.</p> <p>For more complex requirements such as serialization that differs depending on the requested media type you can override the <code>.get_paginate_by()</code> and <code>.get_pagination_serializer_class()</code> methods.</p>
<h2 id="custom-pagination-serializers">Custom pagination serializers</h2> <hr />
<h1 id="custom-pagination-serializers">Custom pagination serializers</h1>
<p>To create a custom pagination serializer class you should override <code>pagination.BasePaginationSerializer</code> and set the fields that you want the serializer to return.</p> <p>To create a custom pagination serializer class you should override <code>pagination.BasePaginationSerializer</code> and set the fields that you want the serializer to return.</p>
<p>You can also override the name used for the object list field, by setting the <code>results_field</code> attribute, which defaults to <code>'results'</code>.</p> <p>You can also override the name used for the object list field, by setting the <code>results_field</code> attribute, which defaults to <code>'results'</code>.</p>
<h2 id="example">Example</h2>
<p>For example, to nest a pair of links labelled 'prev' and 'next', and set the name for the results field to 'objects', you might use something like this.</p> <p>For example, to nest a pair of links labelled 'prev' and 'next', and set the name for the results field to 'objects', you might use something like this.</p>
<pre class="prettyprint lang-py"><code>class LinksSerializer(serializers.Serializer): <pre class="prettyprint lang-py"><code>class LinksSerializer(serializers.Serializer):
next = pagination.NextURLField(source='*') next = pagination.NextURLField(source='*')

View File

@ -142,9 +142,9 @@ sending more complex data than simple forms</p>
<h2 id="how-the-parser-is-determined">How the parser is determined</h2> <h2 id="how-the-parser-is-determined">How the parser is determined</h2>
<p>The set of valid parsers for a view is always defined as a list of classes. When either <code>request.DATA</code> or <code>request.FILES</code> is accessed, REST framework will examine the <code>Content-Type</code> header on the incoming request, and determine which parser to use to parse the request content.</p> <p>The set of valid parsers for a view is always defined as a list of classes. When either <code>request.DATA</code> or <code>request.FILES</code> is accessed, REST framework will examine the <code>Content-Type</code> header on the incoming request, and determine which parser to use to parse the request content.</p>
<h2 id="setting-the-parsers">Setting the parsers</h2> <h2 id="setting-the-parsers">Setting the parsers</h2>
<p>The default set of parsers may be set globally, using the <code>DEFAULT_PARSERS</code> setting. For example, the following settings would allow requests with <code>YAML</code> content.</p> <p>The default set of parsers may be set globally, using the <code>DEFAULT_PARSER_CLASSES</code> setting. For example, the following settings would allow requests with <code>YAML</code> content.</p>
<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = { <pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
'DEFAULT_PARSERS': ( 'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.YAMLParser', 'rest_framework.parsers.YAMLParser',
) )
} }
@ -191,13 +191,17 @@ def example_view(request, format=None):
<p><strong>.media_type</strong>: <code>multipart/form-data</code></p> <p><strong>.media_type</strong>: <code>multipart/form-data</code></p>
<hr /> <hr />
<h1 id="custom-parsers">Custom parsers</h1> <h1 id="custom-parsers">Custom parsers</h1>
<p>To implement a custom parser, you should override <code>BaseParser</code>, set the <code>.media_type</code> property, and implement the <code>.parse_stream(self, stream, parser_context)</code> method.</p> <p>To implement a custom parser, you should override <code>BaseParser</code>, set the <code>.media_type</code> property, and implement the <code>.parse(self, stream, media_type, parser_context)</code> method.</p>
<p>The method should return the data that will be used to populate the <code>request.DATA</code> property.</p> <p>The method should return the data that will be used to populate the <code>request.DATA</code> property.</p>
<p>The arguments passed to <code>.parse_stream()</code> are:</p> <p>The arguments passed to <code>.parse()</code> are:</p>
<h3 id="stream">stream</h3> <h3 id="stream">stream</h3>
<p>A stream-like object representing the body of the request.</p> <p>A stream-like object representing the body of the request.</p>
<h3 id="media_type">media_type</h3>
<p>Optional. If provided, this is the media type of the incoming request content.</p>
<p>Depending on the request's <code>Content-Type:</code> header, this may be more specific than the renderer's <code>media_type</code> attribute, and may include media type parameters. For example <code>"text/plain; charset=utf-8"</code>.</p>
<h3 id="parser_context">parser_context</h3> <h3 id="parser_context">parser_context</h3>
<p>If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content. By default it includes the keys <code>'upload_handlers'</code> and <code>'meta'</code>, which contain the values of the <code>request.upload_handlers</code> and <code>request.meta</code> properties.</p> <p>Optional. If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content.</p>
<p>By default this will include the following keys: <code>view</code>, <code>request</code>, <code>args</code>, <code>kwargs</code>.</p>
<h2 id="example">Example</h2> <h2 id="example">Example</h2>
<p>The following is an example plaintext parser that will populate the <code>request.DATA</code> property with a string representing the body of the request. </p> <p>The following is an example plaintext parser that will populate the <code>request.DATA</code> property with a string representing the body of the request. </p>
<pre class="prettyprint lang-py"><code>class PlainTextParser(BaseParser): <pre class="prettyprint lang-py"><code>class PlainTextParser(BaseParser):
@ -207,21 +211,21 @@ Plain text parser.
media_type = 'text/plain' media_type = 'text/plain'
def parse_stream(self, stream, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
""" """
Simply return a string representing the body of the request. Simply return a string representing the body of the request.
""" """
return stream.read() return stream.read()
</code></pre> </code></pre>
<h2 id="uploading-file-content">Uploading file content</h2> <h2 id="uploading-file-content">Uploading file content</h2>
<p>If your custom parser needs to support file uploads, you may return a <code>DataAndFiles</code> object from the <code>.parse_stream()</code> method. <code>DataAndFiles</code> should be instantiated with two arguments. The first argument will be used to populate the <code>request.DATA</code> property, and the second argument will be used to populate the <code>request.FILES</code> property.</p> <p>If your custom parser needs to support file uploads, you may return a <code>DataAndFiles</code> object from the <code>.parse()</code> method. <code>DataAndFiles</code> should be instantiated with two arguments. The first argument will be used to populate the <code>request.DATA</code> property, and the second argument will be used to populate the <code>request.FILES</code> property.</p>
<p>For example:</p> <p>For example:</p>
<pre class="prettyprint lang-py"><code>class SimpleFileUploadParser(BaseParser): <pre class="prettyprint lang-py"><code>class SimpleFileUploadParser(BaseParser):
""" """
A naive raw file upload parser. A naive raw file upload parser.
""" """
def parse_stream(self, stream, parser_context): def parse(self, stream, media_type=None, parser_context=None):
content = stream.read() content = stream.read()
name = 'example.dat' name = 'example.dat'
content_type = 'application/octet-stream' content_type = 'application/octet-stream'

View File

@ -145,9 +145,9 @@ If any permission check fails an <code>exceptions.PermissionDenied</code> except
<p>REST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.</p> <p>REST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.</p>
<p>Object level permissions are run by REST framework's generic views when <code>.get_object()</code> is called. As with view level permissions, an <code>exceptions.PermissionDenied</code> exception will be raised if the user is not allowed to act on the given object.</p> <p>Object level permissions are run by REST framework's generic views when <code>.get_object()</code> is called. As with view level permissions, an <code>exceptions.PermissionDenied</code> exception will be raised if the user is not allowed to act on the given object.</p>
<h2 id="setting-the-permission-policy">Setting the permission policy</h2> <h2 id="setting-the-permission-policy">Setting the permission policy</h2>
<p>The default permission policy may be set globally, using the <code>DEFAULT_PERMISSIONS</code> setting. For example.</p> <p>The default permission policy may be set globally, using the <code>DEFAULT_PERMISSION_CLASSES</code> setting. For example.</p>
<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = { <pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
'DEFAULT_PERMISSIONS': ( 'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', 'rest_framework.permissions.IsAuthenticated',
) )
} }
@ -171,6 +171,7 @@ def example_view(request, format=None):
} }
return Response(content) return Response(content)
</code></pre> </code></pre>
<hr />
<h1 id="api-reference">API Reference</h1> <h1 id="api-reference">API Reference</h1>
<h2 id="isauthenticated">IsAuthenticated</h2> <h2 id="isauthenticated">IsAuthenticated</h2>
<p>The <code>IsAuthenticated</code> permission class will deny permission to any unauthenticated user, and allow permission otherwise.</p> <p>The <code>IsAuthenticated</code> permission class will deny permission to any unauthenticated user, and allow permission otherwise.</p>
@ -191,6 +192,7 @@ def example_view(request, format=None):
<p>The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a <code>view</code> model permission for <code>GET</code> requests.</p> <p>The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a <code>view</code> model permission for <code>GET</code> requests.</p>
<p>To use custom model permissions, override <code>DjangoModelPermissions</code> and set the <code>.perms_map</code> property. Refer to the source code for details.</p> <p>To use custom model permissions, override <code>DjangoModelPermissions</code> and set the <code>.perms_map</code> property. Refer to the source code for details.</p>
<p>The <code>DjangoModelPermissions</code> class also supports object-level permissions. Third-party authorization backends such as <a href="https://github.com/lukaszb/django-guardian">django-guardian</a> that provide object-level permissions should work just fine with <code>DjangoModelPermissions</code> without any custom configuration required.</p> <p>The <code>DjangoModelPermissions</code> class also supports object-level permissions. Third-party authorization backends such as <a href="https://github.com/lukaszb/django-guardian">django-guardian</a> that provide object-level permissions should work just fine with <code>DjangoModelPermissions</code> without any custom configuration required.</p>
<hr />
<h1 id="custom-permissions">Custom permissions</h1> <h1 id="custom-permissions">Custom permissions</h1>
<p>To implement a custom permission, override <code>BasePermission</code> and implement the <code>.has_permission(self, request, view, obj=None)</code> method.</p> <p>To implement a custom permission, override <code>BasePermission</code> and implement the <code>.has_permission(self, request, view, obj=None)</code> method.</p>
<p>The method should return <code>True</code> if the request should be granted access, and <code>False</code> otherwise.</p> <p>The method should return <code>True</code> if the request should be granted access, and <code>False</code> otherwise.</p>

View File

@ -146,9 +146,9 @@
<p>The basic process of content negotiation involves examining the request's <code>Accept</code> header, to determine which media types it expects in the response. Optionally, format suffixes on the URL may be used to explicitly request a particular representation. For example the URL <code>http://example.com/api/users_count.json</code> might be an endpoint that always returns JSON data.</p> <p>The basic process of content negotiation involves examining the request's <code>Accept</code> header, to determine which media types it expects in the response. Optionally, format suffixes on the URL may be used to explicitly request a particular representation. For example the URL <code>http://example.com/api/users_count.json</code> might be an endpoint that always returns JSON data.</p>
<p>For more information see the documentation on <a href="content-negotiation">content negotation</a>.</p> <p>For more information see the documentation on <a href="content-negotiation">content negotation</a>.</p>
<h2 id="setting-the-renderers">Setting the renderers</h2> <h2 id="setting-the-renderers">Setting the renderers</h2>
<p>The default set of renderers may be set globally, using the <code>DEFAULT_RENDERERS</code> setting. For example, the following settings would use <code>YAML</code> as the main media type and also include the self describing API.</p> <p>The default set of renderers may be set globally, using the <code>DEFAULT_RENDERER_CLASSES</code> setting. For example, the following settings would use <code>YAML</code> as the main media type and also include the self describing API.</p>
<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = { <pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
'DEFAULT_RENDERERS': ( 'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.YAMLRenderer', 'rest_framework.renderers.YAMLRenderer',
'rest_framework.renderers.BrowsableAPIRenderer', 'rest_framework.renderers.BrowsableAPIRenderer',
) )
@ -241,10 +241,11 @@ Unlike other renderers, the data passed to the <code>Response</code> does not ne
<h3 id="data"><code>data</code></h3> <h3 id="data"><code>data</code></h3>
<p>The request data, as set by the <code>Response()</code> instantiation.</p> <p>The request data, as set by the <code>Response()</code> instantiation.</p>
<h3 id="media_typenone"><code>media_type=None</code></h3> <h3 id="media_typenone"><code>media_type=None</code></h3>
<p>Optional. If provided, this is the accepted media type, as determined by the content negotiation stage. Depending on the client's <code>Accept:</code> header, this may be more specific than the renderer's <code>media_type</code> attribute, and may include media type parameters. For example <code>"application/json; nested=true"</code>.</p> <p>Optional. If provided, this is the accepted media type, as determined by the content negotiation stage.</p>
<p>Depending on the client's <code>Accept:</code> header, this may be more specific than the renderer's <code>media_type</code> attribute, and may include media type parameters. For example <code>"application/json; nested=true"</code>.</p>
<h3 id="renderer_contextnone"><code>renderer_context=None</code></h3> <h3 id="renderer_contextnone"><code>renderer_context=None</code></h3>
<p>Optional. If provided, this is a dictionary of contextual information provided by the view. <p>Optional. If provided, this is a dictionary of contextual information provided by the view.</p>
By default this will include the following keys: <code>view</code>, <code>request</code>, <code>response</code>, <code>args</code>, <code>kwargs</code>.</p> <p>By default this will include the following keys: <code>view</code>, <code>request</code>, <code>response</code>, <code>args</code>, <code>kwargs</code>.</p>
<h2 id="example">Example</h2> <h2 id="example">Example</h2>
<p>The following is an example plaintext renderer that will return a response with the <code>data</code> parameter as the content of the response.</p> <p>The following is an example plaintext renderer that will return a response with the <code>data</code> parameter as the content of the response.</p>
<pre class="prettyprint lang-py"><code>from django.utils.encoding import smart_unicode <pre class="prettyprint lang-py"><code>from django.utils.encoding import smart_unicode

View File

@ -157,7 +157,7 @@
<p><code>request.QUERY_PARAMS</code> is a more correcly named synonym for <code>request.GET</code>.</p> <p><code>request.QUERY_PARAMS</code> is a more correcly named synonym for <code>request.GET</code>.</p>
<p>For clarity inside your code, we recommend using <code>request.QUERY_PARAMS</code> instead of the usual <code>request.GET</code>, as <em>any</em> HTTP method type may include query parameters.</p> <p>For clarity inside your code, we recommend using <code>request.QUERY_PARAMS</code> instead of the usual <code>request.GET</code>, as <em>any</em> HTTP method type may include query parameters.</p>
<h2 id="parsers">.parsers</h2> <h2 id="parsers">.parsers</h2>
<p>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically to a list of <code>Parser</code> instances, based on the <code>parser_classes</code> set on the view or based on the <code>DEFAULT_PARSERS</code> setting.</p> <p>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically to a list of <code>Parser</code> instances, based on the <code>parser_classes</code> set on the view or based on the <code>DEFAULT_PARSER_CLASSES</code> setting.</p>
<p>You won't typically need to access this property.</p> <p>You won't typically need to access this property.</p>
<hr /> <hr />
<p><strong>Note:</strong> If a client sends malformed content, then accessing <code>request.DATA</code> or <code>request.FILES</code> may raise a <code>ParseError</code>. By default REST framework's <code>APIView</code> class or <code>@api_view</code> decorator will catch the error and return a <code>400 Bad Request</code> response.</p> <p><strong>Note:</strong> If a client sends malformed content, then accessing <code>request.DATA</code> or <code>request.FILES</code> may raise a <code>ParseError</code>. By default REST framework's <code>APIView</code> class or <code>@api_view</code> decorator will catch the error and return a <code>400 Bad Request</code> response.</p>

View File

@ -114,13 +114,14 @@
<ul class="nav nav-list side-nav well sidebar-nav-fixed"> <ul class="nav nav-list side-nav well sidebar-nav-fixed">
<li class="main"><a href="#settings">Settings</a></li> <li class="main"><a href="#settings">Settings</a></li>
<li><a href="#accessing-settings">Accessing settings</a></li> <li><a href="#accessing-settings">Accessing settings</a></li>
<li><a href="#default_renderers">DEFAULT_RENDERERS</a></li> <li class="main"><a href="#api-reference">API Reference</a></li>
<li><a href="#default_parsers">DEFAULT_PARSERS</a></li> <li><a href="#default_renderer_classes">DEFAULT_RENDERER_CLASSES</a></li>
<li><a href="#default_authentication">DEFAULT_AUTHENTICATION</a></li> <li><a href="#default_parser_classes">DEFAULT_PARSER_CLASSES</a></li>
<li><a href="#default_permissions">DEFAULT_PERMISSIONS</a></li> <li><a href="#default_authentication_classes">DEFAULT_AUTHENTICATION_CLASSES</a></li>
<li><a href="#default_throttles">DEFAULT_THROTTLES</a></li> <li><a href="#default_permission_classes">DEFAULT_PERMISSION_CLASSES</a></li>
<li><a href="#default_model_serializer">DEFAULT_MODEL_SERIALIZER</a></li> <li><a href="#default_throttle_classes">DEFAULT_THROTTLE_CLASSES</a></li>
<li><a href="#default_pagination_serializer">DEFAULT_PAGINATION_SERIALIZER</a></li> <li><a href="#default_model_serializer_class">DEFAULT_MODEL_SERIALIZER_CLASS</a></li>
<li><a href="#default_pagination_serializer_class">DEFAULT_PAGINATION_SERIALIZER_CLASS</a></li>
<li><a href="#format_suffix_kwarg">FORMAT_SUFFIX_KWARG</a></li> <li><a href="#format_suffix_kwarg">FORMAT_SUFFIX_KWARG</a></li>
<li><a href="#unauthenticated_user">UNAUTHENTICATED_USER</a></li> <li><a href="#unauthenticated_user">UNAUTHENTICATED_USER</a></li>
<li><a href="#unauthenticated_token">UNAUTHENTICATED_TOKEN</a></li> <li><a href="#unauthenticated_token">UNAUTHENTICATED_TOKEN</a></li>
@ -144,10 +145,10 @@
<p>Configuration for REST framework is all namespaced inside a single Django setting, named <code>REST_FRAMEWORK</code>.</p> <p>Configuration for REST framework is all namespaced inside a single Django setting, named <code>REST_FRAMEWORK</code>.</p>
<p>For example your project's <code>settings.py</code> file might include something like this:</p> <p>For example your project's <code>settings.py</code> file might include something like this:</p>
<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = { <pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
'DEFAULT_RENDERERS': ( 'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.YAMLRenderer', 'rest_framework.renderers.YAMLRenderer',
) )
'DEFAULT_PARSERS': ( 'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.YAMLParser', 'rest_framework.parsers.YAMLParser',
) )
} }
@ -157,10 +158,12 @@
you should use the <code>api_settings</code> object. For example.</p> you should use the <code>api_settings</code> object. For example.</p>
<pre class="prettyprint lang-py"><code>from rest_framework.settings import api_settings <pre class="prettyprint lang-py"><code>from rest_framework.settings import api_settings
print api_settings.DEFAULT_AUTHENTICATION print api_settings.DEFAULT_AUTHENTICATION_CLASSES
</code></pre> </code></pre>
<p>The <code>api_settings</code> object will check for any user-defined settings, and otherwise fallback to the default values. Any setting that uses string import paths to refer to a class will automatically import and return the referenced class, instead of the string literal.</p> <p>The <code>api_settings</code> object will check for any user-defined settings, and otherwise fallback to the default values. Any setting that uses string import paths to refer to a class will automatically import and return the referenced class, instead of the string literal.</p>
<h2 id="default_renderers">DEFAULT_RENDERERS</h2> <hr />
<h1 id="api-reference">API Reference</h1>
<h2 id="default_renderer_classes">DEFAULT_RENDERER_CLASSES</h2>
<p>A list or tuple of renderer classes, that determines the default set of renderers that may be used when returning a <code>Response</code> object.</p> <p>A list or tuple of renderer classes, that determines the default set of renderers that may be used when returning a <code>Response</code> object.</p>
<p>Default:</p> <p>Default:</p>
<pre class="prettyprint lang-py"><code>( <pre class="prettyprint lang-py"><code>(
@ -169,7 +172,7 @@ print api_settings.DEFAULT_AUTHENTICATION
'rest_framework.renderers.TemplateHTMLRenderer' 'rest_framework.renderers.TemplateHTMLRenderer'
) )
</code></pre> </code></pre>
<h2 id="default_parsers">DEFAULT_PARSERS</h2> <h2 id="default_parser_classes">DEFAULT_PARSER_CLASSES</h2>
<p>A list or tuple of parser classes, that determines the default set of parsers used when accessing the <code>request.DATA</code> property.</p> <p>A list or tuple of parser classes, that determines the default set of parsers used when accessing the <code>request.DATA</code> property.</p>
<p>Default:</p> <p>Default:</p>
<pre class="prettyprint lang-py"><code>( <pre class="prettyprint lang-py"><code>(
@ -177,7 +180,7 @@ print api_settings.DEFAULT_AUTHENTICATION
'rest_framework.parsers.FormParser' 'rest_framework.parsers.FormParser'
) )
</code></pre> </code></pre>
<h2 id="default_authentication">DEFAULT_AUTHENTICATION</h2> <h2 id="default_authentication_classes">DEFAULT_AUTHENTICATION_CLASSES</h2>
<p>A list or tuple of authentication classes, that determines the default set of authenticators used when accessing the <code>request.user</code> or <code>request.auth</code> properties.</p> <p>A list or tuple of authentication classes, that determines the default set of authenticators used when accessing the <code>request.user</code> or <code>request.auth</code> properties.</p>
<p>Default:</p> <p>Default:</p>
<pre class="prettyprint lang-py"><code>( <pre class="prettyprint lang-py"><code>(
@ -185,16 +188,16 @@ print api_settings.DEFAULT_AUTHENTICATION
'rest_framework.authentication.UserBasicAuthentication' 'rest_framework.authentication.UserBasicAuthentication'
) )
</code></pre> </code></pre>
<h2 id="default_permissions">DEFAULT_PERMISSIONS</h2> <h2 id="default_permission_classes">DEFAULT_PERMISSION_CLASSES</h2>
<p>A list or tuple of permission classes, that determines the default set of permissions checked at the start of a view.</p> <p>A list or tuple of permission classes, that determines the default set of permissions checked at the start of a view.</p>
<p>Default: <code>()</code></p> <p>Default: <code>()</code></p>
<h2 id="default_throttles">DEFAULT_THROTTLES</h2> <h2 id="default_throttle_classes">DEFAULT_THROTTLE_CLASSES</h2>
<p>A list or tuple of throttle classes, that determines the default set of throttles checked at the start of a view.</p> <p>A list or tuple of throttle classes, that determines the default set of throttles checked at the start of a view.</p>
<p>Default: <code>()</code></p> <p>Default: <code>()</code></p>
<h2 id="default_model_serializer">DEFAULT_MODEL_SERIALIZER</h2> <h2 id="default_model_serializer_class">DEFAULT_MODEL_SERIALIZER_CLASS</h2>
<p><strong>TODO</strong></p> <p><strong>TODO</strong></p>
<p>Default: <code>rest_framework.serializers.ModelSerializer</code></p> <p>Default: <code>rest_framework.serializers.ModelSerializer</code></p>
<h2 id="default_pagination_serializer">DEFAULT_PAGINATION_SERIALIZER</h2> <h2 id="default_pagination_serializer_class">DEFAULT_PAGINATION_SERIALIZER_CLASS</h2>
<p><strong>TODO</strong></p> <p><strong>TODO</strong></p>
<p>Default: <code>rest_framework.pagination.PaginationSerializer</code></p> <p>Default: <code>rest_framework.pagination.PaginationSerializer</code></p>
<h2 id="format_suffix_kwarg">FORMAT_SUFFIX_KWARG</h2> <h2 id="format_suffix_kwarg">FORMAT_SUFFIX_KWARG</h2>

View File

@ -142,9 +142,9 @@
<p>Before running the main body of the view each throttle in the list is checked. <p>Before running the main body of the view each throttle in the list is checked.
If any throttle check fails an <code>exceptions.Throttled</code> exception will be raised, and the main body of the view will not run.</p> If any throttle check fails an <code>exceptions.Throttled</code> exception will be raised, and the main body of the view will not run.</p>
<h2 id="setting-the-throttling-policy">Setting the throttling policy</h2> <h2 id="setting-the-throttling-policy">Setting the throttling policy</h2>
<p>The default throttling policy may be set globally, using the <code>DEFAULT_THROTTLES</code> and <code>DEFAULT_THROTTLE_RATES</code> settings. For example.</p> <p>The default throttling policy may be set globally, using the <code>DEFAULT_THROTTLE_CLASSES</code> and <code>DEFAULT_THROTTLE_RATES</code> settings. For example.</p>
<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = { <pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
'DEFAULT_THROTTLES': ( 'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttles.AnonThrottle', 'rest_framework.throttles.AnonThrottle',
'rest_framework.throttles.UserThrottle', 'rest_framework.throttles.UserThrottle',
) )
@ -174,6 +174,7 @@ def example_view(request, format=None):
} }
return Response(content) return Response(content)
</code></pre> </code></pre>
<hr />
<h1 id="api-reference">API Reference</h1> <h1 id="api-reference">API Reference</h1>
<h2 id="anonratethrottle">AnonRateThrottle</h2> <h2 id="anonratethrottle">AnonRateThrottle</h2>
<p>The <code>AnonThrottle</code> will only ever throttle unauthenticated users. The IP address of the incoming request is used to generate a unique key to throttle against.</p> <p>The <code>AnonThrottle</code> will only ever throttle unauthenticated users. The IP address of the incoming request is used to generate a unique key to throttle against.</p>
@ -200,7 +201,7 @@ class SustainedRateThrottle(UserRateThrottle):
</code></pre> </code></pre>
<p>...and the following settings.</p> <p>...and the following settings.</p>
<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = { <pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
'DEFAULT_THROTTLES': ( 'DEFAULT_THROTTLE_CLASSES': (
'example.throttles.BurstRateThrottle', 'example.throttles.BurstRateThrottle',
'example.throttles.SustainedRateThrottle', 'example.throttles.SustainedRateThrottle',
) )
@ -229,7 +230,7 @@ class UploadView(APIView):
</code></pre> </code></pre>
<p>...and the following settings.</p> <p>...and the following settings.</p>
<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = { <pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
'DEFAULT_THROTTLES': ( 'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttles.ScopedRateThrottle', 'rest_framework.throttles.ScopedRateThrottle',
) )
'DEFAULT_THROTTLE_RATES': { 'DEFAULT_THROTTLE_RATES': {
@ -239,6 +240,7 @@ class UploadView(APIView):
} }
</code></pre> </code></pre>
<p>User requests to either <code>ContactListView</code> or <code>ContactDetailView</code> would be restricted to a total of 1000 requests per-day. User requests to <code>UploadView</code> would be restricted to 20 requests per day.</p> <p>User requests to either <code>ContactListView</code> or <code>ContactDetailView</code> would be restricted to a total of 1000 requests per-day. User requests to <code>UploadView</code> would be restricted to 20 requests per day.</p>
<hr />
<h1 id="custom-throttles">Custom throttles</h1> <h1 id="custom-throttles">Custom throttles</h1>
<p>To create a custom throttle, override <code>BaseThrottle</code> and implement <code>.allow_request(request, view)</code>. The method should return <code>True</code> if the request should be allowed, and <code>False</code> otherwise.</p> <p>To create a custom throttle, override <code>BaseThrottle</code> and implement <code>.allow_request(request, view)</code>. The method should return <code>True</code> if the request should be allowed, and <code>False</code> otherwise.</p>
<p>Optionally you may also override the <code>.wait()</code> method. If implemented, <code>.wait()</code> should return a recomended number of seconds to wait before attempting the next request, or <code>None</code>. The <code>.wait()</code> method will only be called if <code>.allow_request()</code> has previously returned <code>False</code>.</p> <p>Optionally you may also override the <code>.wait()</code> method. If implemented, <code>.wait()</code> should return a recomended number of seconds to wait before attempting the next request, or <code>None</code>. The <code>.wait()</code> method will only be called if <code>.allow_request()</code> has previously returned <code>False</code>.</p>

View File

@ -154,8 +154,8 @@
""" """
Return a list of all users. Return a list of all users.
""" """
users = [user.username for user in User.objects.all()] usernames = [user.username for user in User.objects.all()]
return Response(users) return Response(usernames)
</code></pre> </code></pre>
<h2 id="api-policy-attributes">API policy attributes</h2> <h2 id="api-policy-attributes">API policy attributes</h2>
<p>The following attributes control the pluggable aspects of API views.</p> <p>The following attributes control the pluggable aspects of API views.</p>

View File

@ -88,6 +88,10 @@ pre {
font-weight: bold; font-weight: bold;
} }
.nav-list a {
overflow: hidden;
}
/* Set the table of contents to static so it flows back into the content when /* Set the table of contents to static so it flows back into the content when
viewed on tablets and smaller. */ viewed on tablets and smaller. */
@media (max-width: 767px) { @media (max-width: 767px) {

View File

@ -169,6 +169,7 @@
<li>Mattbo - <a href="https://github.com/mattbo">mattbo</a></li> <li>Mattbo - <a href="https://github.com/mattbo">mattbo</a></li>
<li>Max Hurl - <a href="https://github.com/maximilianhurl">maximilianhurl</a></li> <li>Max Hurl - <a href="https://github.com/maximilianhurl">maximilianhurl</a></li>
<li>Tomi Pajunen - <a href="https://github.com/eofs">eofs</a></li> <li>Tomi Pajunen - <a href="https://github.com/eofs">eofs</a></li>
<li>Rob Dobson - <a href="https://github.com/rdobson">rdobson</a></li>
</ul> </ul>
<p>Many thanks to everyone who's contributed to the project.</p> <p>Many thanks to everyone who's contributed to the project.</p>
<h2 id="additional-thanks">Additional thanks</h2> <h2 id="additional-thanks">Additional thanks</h2>

View File

@ -238,12 +238,15 @@ serializer.data
# {'id': 1, 'email': u'leila@example.com', 'content': u'nothing to say', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774, tzinfo=&lt;UTC&gt;)} # {'id': 1, 'email': u'leila@example.com', 'content': u'nothing to say', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774, tzinfo=&lt;UTC&gt;)}
</code></pre> </code></pre>
<p>At this point we've translated the model instance into python native datatypes. To finalise the serialization process we render the data into <code>json</code>.</p> <p>At this point we've translated the model instance into python native datatypes. To finalise the serialization process we render the data into <code>json</code>.</p>
<pre class="prettyprint lang-py"><code>stream = JSONRenderer().render(serializer.data) <pre class="prettyprint lang-py"><code>content = JSONRenderer().render(serializer.data)
stream content
# '{"id": 1, "email": "leila@example.com", "content": "nothing to say", "created": "2012-08-22T16:20:09.822"}' # '{"id": 1, "email": "leila@example.com", "content": "nothing to say", "created": "2012-08-22T16:20:09.822"}'
</code></pre> </code></pre>
<p>Deserialization is similar. First we parse a stream into python native datatypes... </p> <p>Deserialization is similar. First we parse a stream into python native datatypes... </p>
<pre class="prettyprint lang-py"><code>data = JSONParser().parse(stream) <pre class="prettyprint lang-py"><code>import StringIO
stream = StringIO.StringIO(content)
data = JSONParser().parse(stream)
</code></pre> </code></pre>
<p>...then we restore those native datatypes into to a fully populated object instance.</p> <p>...then we restore those native datatypes into to a fully populated object instance.</p>
<pre class="prettyprint lang-py"><code>serializer = CommentSerializer(data) <pre class="prettyprint lang-py"><code>serializer = CommentSerializer(data)

View File

@ -225,7 +225,7 @@ urlpatterns += patterns('',
) )
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PERMISSIONS': ('rest_framework.permissions.IsAdminUser',), 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
'PAGINATE_BY': 10 'PAGINATE_BY': 10
} }
</code></pre> </code></pre>