Latest docs build

This commit is contained in:
Tom Christie 2014-06-12 12:22:09 +01:00
parent 03ddd237c9
commit 106c8db6f5
13 changed files with 61 additions and 23 deletions

View File

@ -287,7 +287,7 @@ WSGIPassAuthorization On
<p><strong>Note:</strong> If you use <code>BasicAuthentication</code> in production you must ensure that your API is only available over <code>https</code>. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.</p>
<h2 id="tokenauthentication">TokenAuthentication</h2>
<p>This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.</p>
<p>To use the <code>TokenAuthentication</code> scheme, include <code>rest_framework.authtoken</code> in your <code>INSTALLED_APPS</code> setting:</p>
<p>To use the <code>TokenAuthentication</code> scheme you'll need to <a href="#setting-the-authentication-scheme">configure the authentication classes</a> to include <code>TokenAuthentication</code>, and additionally include <code>rest_framework.authtoken</code> in your <code>INSTALLED_APPS</code> setting:</p>
<pre class="prettyprint lang-py"><code>INSTALLED_APPS = (
...
'rest_framework.authtoken'

View File

@ -324,7 +324,8 @@ or <code>django.db.models.fields.TextField</code>.</p>
<p>Corresponds to <code>django.db.models.fields.SlugField</code>.</p>
<p><strong>Signature:</strong> <code>SlugField(max_length=50, min_length=None)</code></p>
<h2 id="choicefield">ChoiceField</h2>
<p>A field that can accept a value out of a limited set of choices.</p>
<p>A field that can accept a value out of a limited set of choices. Optionally takes a <code>blank_display_value</code> parameter that customizes the display value of an empty choice.</p>
<p><strong>Signature:</strong> <code>ChoiceField(choices=(), blank_display_value=None)</code></p>
<h2 id="emailfield">EmailField</h2>
<p>A text representation, validates the text to be a valid e-mail address.</p>
<p>Corresponds to <code>django.db.models.fields.EmailField</code></p>

View File

@ -214,7 +214,7 @@
from myapp.serializers import PurchaseSerializer
from rest_framework import generics
class PurchaseList(generics.ListAPIView)
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
@ -231,7 +231,7 @@ class PurchaseList(generics.ListAPIView)
<pre class="prettyprint lang-py"><code>url('^purchases/(?P&lt;username&gt;.+)/$', PurchaseList.as_view()),
</code></pre>
<p>You could then write a view that returned a purchase queryset filtered by the username portion of the URL:</p>
<pre class="prettyprint lang-py"><code>class PurchaseList(generics.ListAPIView)
<pre class="prettyprint lang-py"><code>class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
@ -245,7 +245,7 @@ class PurchaseList(generics.ListAPIView)
<h2 id="filtering-against-query-parameters">Filtering against query parameters</h2>
<p>A final example of filtering the initial queryset would be to determine the initial queryset based on query parameters in the url.</p>
<p>We can override <code>.get_queryset()</code> to deal with URLs such as <code>http://example.com/api/purchases?username=denvercoder9</code>, and filter the queryset only if the <code>username</code> parameter is included in the URL:</p>
<pre class="prettyprint lang-py"><code>class PurchaseList(generics.ListAPIView)
<pre class="prettyprint lang-py"><code>class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):

View File

@ -261,7 +261,7 @@ class UserList(generics.ListCreateAPIView):
</ul>
<p><strong>Shortcuts</strong>:</p>
<ul>
<li><code>model</code> - This shortcut may be used instead of setting either (or both) of the <code>queryset</code>/<code>serializer_class</code> attributes, although using the explicit style is generally preferred. If used instead of <code>serializer_class</code>, then then <code>DEFAULT_MODEL_SERIALIZER_CLASS</code> setting will determine the base serializer class. Note that <code>model</code> is only ever used for generating a default queryset or serializer class - the <code>queryset</code> and <code>serializer_class</code> attributes are always preferred if provided.</li>
<li><code>model</code> - This shortcut may be used instead of setting either (or both) of the <code>queryset</code>/<code>serializer_class</code> attributes, although using the explicit style is generally preferred. If used instead of <code>serializer_class</code>, then <code>DEFAULT_MODEL_SERIALIZER_CLASS</code> setting will determine the base serializer class. Note that <code>model</code> is only ever used for generating a default queryset or serializer class - the <code>queryset</code> and <code>serializer_class</code> attributes are always preferred if provided.</li>
</ul>
<p><strong>Pagination</strong>:</p>
<p>The following attributes are used to control pagination when used with list views.</p>
@ -350,7 +350,7 @@ class UserList(generics.ListCreateAPIView):
<p>You won't typically need to override the following methods, although you might need to call into them if you're writing custom views using <code>GenericAPIView</code>.</p>
<ul>
<li><code>get_serializer_context(self)</code> - Returns a dictionary containing any extra context that should be supplied to the serializer. Defaults to including <code>'request'</code>, <code>'view'</code> and <code>'format'</code> keys.</li>
<li><code>get_serializer(self, instance=None, data=None, files=None, many=False, partial=False)</code> - Returns a serializer instance.</li>
<li><code>get_serializer(self, instance=None, data=None, files=None, many=False, partial=False, allow_add_remove=False)</code> - Returns a serializer instance.</li>
<li><code>get_pagination_serializer(self, page)</code> - Returns a serializer instance to use with paginated data.</li>
<li><code>paginate_queryset(self, queryset)</code> - Paginate a queryset if required, either returning a page object, or <code>None</code> if pagination is not configured for this view.</li>
<li><code>filter_queryset(self, queryset)</code> - Given a queryset, filter it with whichever filter backends are in use, returning a new queryset.</li>

View File

@ -277,7 +277,8 @@ def user_list(request):
paginate_by_param = 'page_size'
max_paginate_by = 100
</code></pre>
<p>Note that using a <code>paginate_by</code> value of <code>None</code> will turn off pagination for the view.</p>
<p>Note that using a <code>paginate_by</code> value of <code>None</code> will turn off pagination for the view.
Note if you use the <code>PAGINATE_BY_PARAM</code> settings, you also have to set the <code>paginate_by_param</code> attribute in your view to <code>None</code> in order to turn off pagination for those requests that contain the <code>paginate_by_param</code> parameter.</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>
<hr />
<h1 id="custom-pagination-serializers">Custom pagination serializers</h1>

View File

@ -239,7 +239,7 @@ or if you override the <code>get_object</code> method on a generic view, then yo
<p>You can also set the authentication policy on a per-view, or per-viewset basis,
using the <code>APIView</code> class based views.</p>
<pre class="prettyprint lang-py"><code>from rest_framework.permissions import IsAuthenticated
from rest_framework.responses import Response
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):

View File

@ -177,6 +177,7 @@
<li><a href="#unicodejsonrenderer">UnicodeJSONRenderer</a></li>
<li><a href="#jsonprenderer">JSONPRenderer</a></li>
<li><a href="#yamlrenderer">YAMLRenderer</a></li>
<li><a href="#unicodeyamlrenderer">UnicodeYAMLRenderer</a></li>
<li><a href="#xmlrenderer">XMLRenderer</a></li>
<li><a href="#templatehtmlrenderer">TemplateHTMLRenderer</a></li>
<li><a href="#statichtmlrenderer">StaticHTMLRenderer</a></li>
@ -303,6 +304,18 @@ def user_count_view(request, format=None):
<h2 id="yamlrenderer">YAMLRenderer</h2>
<p>Renders the request data into <code>YAML</code>. </p>
<p>Requires the <code>pyyaml</code> package to be installed.</p>
<p>Note that non-ascii characters will be rendered using <code>\uXXXX</code> character escape. For example:</p>
<pre class="prettyprint lang-py"><code>unicode black star: "\u2605"
</code></pre>
<p><strong>.media_type</strong>: <code>application/yaml</code></p>
<p><strong>.format</strong>: <code>'.yaml'</code></p>
<p><strong>.charset</strong>: <code>utf-8</code></p>
<h2 id="unicodeyamlrenderer">UnicodeYAMLRenderer</h2>
<p>Renders the request data into <code>YAML</code>. </p>
<p>Requires the <code>pyyaml</code> package to be installed.</p>
<p>Note that non-ascii characters will not be character escaped. For example:</p>
<pre class="prettyprint lang-py"><code>unicode black star: ★
</code></pre>
<p><strong>.media_type</strong>: <code>application/yaml</code></p>
<p><strong>.format</strong>: <code>'.yaml'</code></p>
<p><strong>.charset</strong>: <code>utf-8</code></p>

View File

@ -186,6 +186,7 @@
<li><a href="#relational-fields">Relational fields</a></li>
<li class="main"><a href="#hyperlinkedmodelserializer">HyperlinkedModelSerializer</a></li>
<li><a href="#how-hyperlinked-views-are-determined">How hyperlinked views are determined</a></li>
<li><a href="#overriding-the-url-field-behavior">Overriding the URL field behavior</a></li>
<li class="main"><a href="#advanced-serializer-usage">Advanced serializer usage</a></li>
<li><a href="#dynamically-modifying-fields">Dynamically modifying fields</a></li>
<li><a href="#customising-the-default-fields">Customising the default fields</a></li>
@ -260,8 +261,8 @@ json
<h3 id="customizing-field-representation">Customizing field representation</h3>
<p>Sometimes when serializing objects, you may not want to represent everything exactly the way it is in your model.</p>
<p>If you need to customize the serialized value of a particular field, you can do this by creating a <code>transform_&lt;fieldname&gt;</code> method. For example if you needed to render some markdown from a text field:</p>
<pre class="prettyprint lang-py"><code>description = serializers.TextField()
description_html = serializers.TextField(source='description', read_only=True)
<pre class="prettyprint lang-py"><code>description = serializers.CharField()
description_html = serializers.CharField(source='description', read_only=True)
def transform_description_html(self, obj, value):
from django.contrib.markup.templatetags.markup import markdown
@ -565,7 +566,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
model = Account
fields = ('url', 'account_name', 'users', 'created')
</code></pre>
<h2 id="overiding-the-url-field-behavior">Overiding the URL field behavior</h2>
<h2 id="overriding-the-url-field-behavior">Overriding the URL field behavior</h2>
<p>The name of the URL field defaults to 'url'. You can override this globally, by using the <code>URL_FIELD_NAME</code> setting.</p>
<p>You can also override this on a per-serializer basis by using the <code>url_field_name</code> option on the serializer, like so:</p>
<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
@ -575,7 +576,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
url_field_name = 'account_url'
</code></pre>
<p><strong>Note</strong>: The generic view implementations normally generate a <code>Location</code> header in response to successful <code>POST</code> requests. Serializers using <code>url_field_name</code> option will not have this header automatically included by the view. If you need to do so you will ned to also override the view's <code>get_success_headers()</code> method.</p>
<p>You can also overide the URL field's view name and lookup field without overriding the field explicitly, by using the <code>view_name</code> and <code>lookup_field</code> options, like so:</p>
<p>You can also override the URL field's view name and lookup field without overriding the field explicitly, by using the <code>view_name</code> and <code>lookup_field</code> options, like so:</p>
<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Account

View File

@ -311,7 +311,7 @@ class UserViewSet(viewsets.ModelViewSet):
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>method</code> argument. For example:</p>
<p>The <code>@action</code> decorator will route <code>POST</code> requests by default, but may also accept other HTTP methods, by using the <code>methods</code> argument. For example:</p>
<pre class="prettyprint lang-py"><code> @action(methods=['POST', 'DELETE'])
def unset_password(self, request, pk=None):
...

View File

@ -225,6 +225,28 @@
</code></pre>
<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>
<ul>
<li><strong>Security fix</strong>: Escape request path when it is include as part of the login and logout links in the browsable API.</li>
<li><code>help_text</code> and <code>verbose_name</code> automatically set for related fields on <code>ModelSerializer</code>.</li>
<li>Fix nested serializers linked through a backward foreign key relation.</li>
<li>Fix bad links for the <code>BrowsableAPIRenderer</code> with <code>YAMLRenderer</code>.</li>
<li>Add <code>UnicodeYAMLRenderer</code> that extends <code>YAMLRenderer</code> with unicode.</li>
<li>Fix <code>parse_header</code> argument convertion.</li>
<li>Fix mediatype detection under Python 3.</li>
<li>Web browseable API now offers blank option on dropdown when the field is not required.</li>
<li><code>APIException</code> representation improved for logging purposes.</li>
<li>Allow source="*" within nested serializers.</li>
<li>Better support for custom oauth2 provider backends.</li>
<li>Fix field validation if it's optional and has no value.</li>
<li>Add <code>SEARCH_PARAM</code> and <code>ORDERING_PARAM</code>.</li>
<li>Fix <code>APIRequestFactory</code> to support arguments within the url string for GET.</li>
<li>Allow three transport modes for access tokens when accessing a protected resource.</li>
<li>Fix <code>QueryDict</code> encoding on request objects.</li>
<li>Ensure throttle keys do not contain spaces, as those are invalid if using <code>memcached</code>.</li>
<li>Support <code>blank_display_value</code> on <code>ChoiceField</code>.</li>
</ul>
<h3 id="2313">2.3.13</h3>
<p><strong>Date</strong>: 6th March 2014</p>
<ul>
@ -291,10 +313,10 @@
<li>Bugfix: <code>client.force_authenticate(None)</code> should also clear session info if it exists.</li>
<li>Bugfix: Client sending empty string instead of file now clears <code>FileField</code>.</li>
<li>Bugfix: Empty values on ChoiceFields with <code>required=False</code> now consistently return <code>None</code>.</li>
<li>Bugfix: Clients setting <code>page=0</code> now simply returns the default page size, instead of disabling pagination. [*]</li>
<li>Bugfix: Clients setting <code>page_size=0</code> now simply returns the default page size, instead of disabling pagination. [*]</li>
</ul>
<hr />
<p>[*] Note that the change in <code>page=0</code> behaviour fixes what is considered to be a bug in how clients can effect the pagination size. However if you were relying on this behavior you will need to add the following mixin to your list views in order to preserve the existing behavior.</p>
<p>[*] Note that the change in <code>page_size=0</code> behaviour fixes what is considered to be a bug in how clients can effect the pagination size. However if you were relying on this behavior you will need to add the following mixin to your list views in order to preserve the existing behavior.</p>
<pre class="prettyprint lang-py"><code>class DisablePaginationMixin(object):
def get_paginate_by(self, queryset=None):
if self.request.QUERY_PARAMS[self.paginate_by_param] == '0':

View File

@ -275,7 +275,7 @@ class Snippet(models.Model):
<pre class="prettyprint lang-py"><code>python manage.py syncdb
</code></pre>
<h2 id="creating-a-serializer-class">Creating a Serializer class</h2>
<p>The first thing we need to get started on our Web API is provide a way of serializing and deserializing the snippet instances into representations such as <code>json</code>. We can do this by declaring serializers that work very similar to Django's forms. Create a file in the <code>snippets</code> directory named <code>serializers.py</code> and add the following.</p>
<p>The first thing we need to get started on our Web API is to provide a way of serializing and deserializing the snippet instances into representations such as <code>json</code>. We can do this by declaring serializers that work very similar to Django's forms. Create a file in the <code>snippets</code> directory named <code>serializers.py</code> and add the following.</p>
<pre class="prettyprint lang-py"><code>from django.forms import widgets
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
@ -313,7 +313,7 @@ class SnippetSerializer(serializers.Serializer):
# Create new instance
return Snippet(**attrs)
</code></pre>
<p>The first part of serializer class defines the fields that get serialized/deserialized. The <code>restore_object</code> method defines how fully fledged instances get created when deserializing data.</p>
<p>The first part of the serializer class defines the fields that get serialized/deserialized. The <code>restore_object</code> method defines how fully fledged instances get created when deserializing data.</p>
<p>Notice that we can also use various attributes that would typically be used on form fields, such as <code>widget=widgets.Textarea</code>. These can be used to control how the serializer should render when displayed as an HTML form. This is particularly useful for controlling how the browsable API should be displayed, as we'll see later in the tutorial.</p>
<p>We can actually also save ourselves some time by using the <code>ModelSerializer</code> class, as we'll see later, but for now we'll keep our serializer definition explicit. </p>
<h2 id="working-with-serializers">Working with Serializers</h2>

View File

@ -228,10 +228,10 @@ from pygments import highlight
<p>When that's all done we'll need to update our database tables.
Normally we'd create a database migration in order to do that, but for the purposes of this tutorial, let's just delete the database and start again.</p>
<pre class="prettyprint lang-py"><code>rm tmp.db
python ./manage.py syncdb
python manage.py syncdb
</code></pre>
<p>You might also want to create a few different users, to use for testing the API. The quickest way to do this will be with the <code>createsuperuser</code> command.</p>
<pre class="prettyprint lang-py"><code>python ./manage.py createsuperuser
<pre class="prettyprint lang-py"><code>python manage.py createsuperuser
</code></pre>
<h2 id="adding-endpoints-for-our-user-models">Adding endpoints for our User models</h2>
<p>Now that we've got some users to work with, we'd better add representations of those users to our API. Creating a new serializer is easy. In <code>serializers.py</code> add:</p>

View File

@ -203,7 +203,7 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
</code></pre>
<p>Here we've used <code>ReadOnlyModelViewSet</code> class to automatically provide the default 'read-only' operations. We're still setting the <code>queryset</code> and <code>serializer_class</code> attributes exactly as we did when we were using regular views, but we no longer need to provide the same information to two separate classes.</p>
<p>Here we've used the <code>ReadOnlyModelViewSet</code> class to automatically provide the default 'read-only' operations. We're still setting the <code>queryset</code> and <code>serializer_class</code> attributes exactly as we did when we were using regular views, but we no longer need to provide the same information to two separate classes.</p>
<p>Next we're going to replace the <code>SnippetList</code>, <code>SnippetDetail</code> and <code>SnippetHighlight</code> view classes. We can remove the three views, and again replace them with a single class.</p>
<pre class="prettyprint lang-py"><code>from rest_framework.decorators import link
@ -258,7 +258,7 @@ user_detail = UserViewSet.as_view({
})
</code></pre>
<p>Notice how we're creating multiple views from each <code>ViewSet</code> class, by binding the http methods to the required action for each view.</p>
<p>Now that we've bound our resources into concrete views, that we can register the views with the URL conf as usual.</p>
<p>Now that we've bound our resources into concrete views, we can register the views with the URL conf as usual.</p>
<pre class="prettyprint lang-py"><code>urlpatterns = format_suffix_patterns(patterns('snippets.views',
url(r'^$', 'api_root'),
url(r'^snippets/$', snippet_list, name='snippet-list'),
@ -297,7 +297,7 @@ urlpatterns = patterns('',
<p>We've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views.</p>
<p>You can review the final <a href="https://github.com/tomchristie/rest-framework-tutorial">tutorial code</a> on GitHub, or try out a live example in <a href="http://restframework.herokuapp.com/">the sandbox</a>.</p>
<h2 id="onwards-and-upwards">Onwards and upwards</h2>
<p>We've reached the end of our tutorial. If you want to get more involved in the REST framework project, here's a few places you can start:</p>
<p>We've reached the end of our tutorial. If you want to get more involved in the REST framework project, here are a few places you can start:</p>
<ul>
<li>Contribute on <a href="https://github.com/tomchristie/django-rest-framework">GitHub</a> by reviewing and submitting issues, and making pull requests.</li>
<li>Join the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">REST framework discussion group</a>, and help build the community.</li>