Commit ed93e13a by Tom Christie

Update documentation

parent 9defb5ee
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../permissions"> <a class="repo-link btn btn-inverse btn-small " rel="prev" href="../permissions">
Next <i class="icon-arrow-right icon-white"></i> Next <i class="icon-arrow-right icon-white"></i>
</a> </a>
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../relations"> <a class="repo-link btn btn-inverse btn-small " rel="next" href="../validators">
<i class="icon-arrow-left icon-white"></i> Previous <i class="icon-arrow-left icon-white"></i> Previous
</a> </a>
<a class="repo-link btn btn-inverse btn-small" href="#searchModal" data-toggle="modal"><i class="icon-search icon-white"></i> Search</a> <a class="repo-link btn btn-inverse btn-small" href="#searchModal" data-toggle="modal"><i class="icon-search icon-white"></i> Search</a>
...@@ -164,6 +164,10 @@ ...@@ -164,6 +164,10 @@
<a href="../relations">Serializer relations</a> <a href="../relations">Serializer relations</a>
</li> </li>
<li >
<a href="../validators">Validators</a>
</li>
<li class="active" > <li class="active" >
<a href=".">Authentication</a> <a href=".">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -761,7 +769,7 @@ class ExampleAuthentication(authentication.BaseAuthentication): ...@@ -761,7 +769,7 @@ class ExampleAuthentication(authentication.BaseAuthentication):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -466,7 +474,7 @@ class NoNegotiationView(APIView): ...@@ -466,7 +474,7 @@ class NoNegotiationView(APIView):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -389,6 +397,10 @@ ...@@ -389,6 +397,10 @@
<a href="#throttled">Throttled</a> <a href="#throttled">Throttled</a>
</li> </li>
<li>
<a href="#validationerror">ValidationError</a>
</li>
...@@ -484,7 +496,7 @@ class ServiceUnavailable(APIException): ...@@ -484,7 +496,7 @@ class ServiceUnavailable(APIException):
</code></pre> </code></pre>
<h2 id="parseerror">ParseError</h2> <h2 id="parseerror">ParseError</h2>
<p><strong>Signature:</strong> <code>ParseError(detail=None)</code></p> <p><strong>Signature:</strong> <code>ParseError(detail=None)</code></p>
<p>Raised if the request contains malformed data when accessing <code>request.DATA</code> or <code>request.FILES</code>.</p> <p>Raised if the request contains malformed data when accessing <code>request.data</code>.</p>
<p>By default this exception results in a response with the HTTP status code "400 Bad Request".</p> <p>By default this exception results in a response with the HTTP status code "400 Bad Request".</p>
<h2 id="authenticationfailed">AuthenticationFailed</h2> <h2 id="authenticationfailed">AuthenticationFailed</h2>
<p><strong>Signature:</strong> <code>AuthenticationFailed(detail=None)</code></p> <p><strong>Signature:</strong> <code>AuthenticationFailed(detail=None)</code></p>
...@@ -504,12 +516,25 @@ class ServiceUnavailable(APIException): ...@@ -504,12 +516,25 @@ class ServiceUnavailable(APIException):
<p>By default this exception results in a response with the HTTP status code "405 Method Not Allowed".</p> <p>By default this exception results in a response with the HTTP status code "405 Method Not Allowed".</p>
<h2 id="unsupportedmediatype">UnsupportedMediaType</h2> <h2 id="unsupportedmediatype">UnsupportedMediaType</h2>
<p><strong>Signature:</strong> <code>UnsupportedMediaType(media_type, detail=None)</code></p> <p><strong>Signature:</strong> <code>UnsupportedMediaType(media_type, detail=None)</code></p>
<p>Raised if there are no parsers that can handle the content type of the request data when accessing <code>request.DATA</code> or <code>request.FILES</code>.</p> <p>Raised if there are no parsers that can handle the content type of the request data when accessing <code>request.data</code>.</p>
<p>By default this exception results in a response with the HTTP status code "415 Unsupported Media Type".</p> <p>By default this exception results in a response with the HTTP status code "415 Unsupported Media Type".</p>
<h2 id="throttled">Throttled</h2> <h2 id="throttled">Throttled</h2>
<p><strong>Signature:</strong> <code>Throttled(wait=None, detail=None)</code></p> <p><strong>Signature:</strong> <code>Throttled(wait=None, detail=None)</code></p>
<p>Raised when an incoming request fails the throttling checks.</p> <p>Raised when an incoming request fails the throttling checks.</p>
<p>By default this exception results in a response with the HTTP status code "429 Too Many Requests".</p> <p>By default this exception results in a response with the HTTP status code "429 Too Many Requests".</p>
<h2 id="validationerror">ValidationError</h2>
<p><strong>Signature:</strong> <code>ValidationError(detail)</code></p>
<p>The <code>ValidationError</code> exception is slightly different from the other <code>APIException</code> classes:</p>
<ul>
<li>The <code>detail</code> argument is mandatory, not optional.</li>
<li>The <code>detail</code> argument may be a list or dictionary of error details, and may also be a nested data structure.</li>
<li>By convention you should import the serializers module and use a fully qualified <code>ValidationError</code> style, in order to differentiate it from Django's built-in validation error. For example. <code>raise serializers.ValidationError('This field must be an integer value.')</code></li>
</ul>
<p>The <code>ValidationError</code> class should be used for serializer and field validation, and by validator classes. It is also raised when calling <code>serializer.is_valid</code> with the <code>raise_exception</code> keyword argument:</p>
<pre><code>serializer.is_valid(raise_exception=True)
</code></pre>
<p>The generic views use the <code>raise_exception=True</code> flag, which means that you can override the style of validation error responses globally in your API. To do so, use a custom exception handler, as described above.</p>
<p>By default this exception results in a response with the HTTP status code "400 Bad Request".</p>
</div> </div>
<!--/span--> <!--/span-->
...@@ -524,7 +549,7 @@ class ServiceUnavailable(APIException): ...@@ -524,7 +549,7 @@ class ServiceUnavailable(APIException):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -756,7 +764,7 @@ class ProductFilter(django_filters.FilterSet): ...@@ -756,7 +764,7 @@ class ProductFilter(django_filters.FilterSet):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -432,7 +440,7 @@ def comment_list(request, format=None): ...@@ -432,7 +440,7 @@ def comment_list(request, format=None):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -488,12 +496,15 @@ ...@@ -488,12 +496,15 @@
<h1 id="generic-views">Generic views</h1> <hr />
<p><strong>Note</strong>: This is the documentation for the <strong>version 3.0</strong> of REST framework. Documentation for <a href="http://tomchristie.github.io/rest-framework-2-docs/">version 2.4</a> is also available.</p>
<hr />
<h1 id="generic-views">Generic views</h1>
<blockquote> <blockquote>
<p>Django’s generic views... were developed as a shortcut for common usage patterns... They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to repeat yourself.</p> <p>Django’s generic views... were developed as a shortcut for common usage patterns... They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to repeat yourself.</p>
<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/class-based-views/#base-vs-generic-views">Django Documentation</a></p> <p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/class-based-views/#base-vs-generic-views">Django Documentation</a></p>
</blockquote> </blockquote>
<p>One of the key benefits of class based views is the way they allow you to compose bits of reusable behaviour. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns.</p> <p>One of the key benefits of class based views is the way they allow you to compose bits of reusable behavior. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns.</p>
<p>The generic views provided by REST framework allow you to quickly build API views that map closely to your database models.</p> <p>The generic views provided by REST framework allow you to quickly build API views that map closely to your database models.</p>
<p>If the generic views don't suit the needs of your API, you can drop down to using the regular <code>APIView</code> class, or reuse the mixins and base classes used by the generic views to compose your own set of reusable generic views.</p> <p>If the generic views don't suit the needs of your API, you can drop down to using the regular <code>APIView</code> class, or reuse the mixins and base classes used by the generic views to compose your own set of reusable generic views.</p>
<h2 id="examples">Examples</h2> <h2 id="examples">Examples</h2>
...@@ -618,22 +629,23 @@ class UserList(generics.ListCreateAPIView): ...@@ -618,22 +629,23 @@ class UserList(generics.ListCreateAPIView):
return 20 return 20
return 100 return 100
</code></pre> </code></pre>
<p><strong>Save / deletion hooks</strong>:</p> <p><strong>Save and deletion hooks</strong>:</p>
<p>The following methods are provided as placeholder interfaces. They contain empty implementations and are not called directly by <code>GenericAPIView</code>, but they are overridden and used by some of the mixin classes.</p> <p>The following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior.</p>
<ul> <ul>
<li><code>pre_save(self, obj)</code> - A hook that is called before saving an object.</li> <li><code>perform_create(self, serializer)</code> - Called by <code>CreateModelMixin</code> when saving a new object instance.</li>
<li><code>post_save(self, obj, created=False)</code> - A hook that is called after saving an object.</li> <li><code>perform_update(self, serializer)</code> - Called by <code>UpdateModelMixin</code> when saving an existing object instance.</li>
<li><code>pre_delete(self, obj)</code> - A hook that is called before deleting an object.</li> <li><code>perform_destroy(self, instance)</code> - Called by <code>DestroyModelMixin</code> when deleting an object instance.</li>
<li><code>post_delete(self, obj)</code> - A hook that is called after deleting an object.</li>
</ul> </ul>
<p>The <code>pre_save</code> method in particular is a useful hook for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument.</p> <p>These hooks are particularly useful for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument.</p>
<pre><code>def pre_save(self, obj): <pre><code>def perform_create(self, serializer):
""" serializer.save(user=self.request.user)
Set the object's owner, based on the incoming request. </code></pre>
""" <p>These override points are also particularly useful for adding behavior that occurs before or after saving an object, such as emailing a confirmation, or logging the update.</p>
obj.owner = self.request.user <pre><code>def perform_update(self, serializer):
instance = serializer.save()
send_email_confirmation(user=self.request.user, modified=instance)
</code></pre> </code></pre>
<p>Remember that the <code>pre_save()</code> method is not called by <code>GenericAPIView</code> itself, but it is called by <code>create()</code> and <code>update()</code> methods on the <code>CreateModelMixin</code> and <code>UpdateModelMixin</code> classes.</p> <p><strong>Note</strong>: These methods replace the old-style version 2.x <code>pre_save</code>, <code>post_save</code>, <code>pre_delete</code> and <code>post_delete</code> methods, which are no longer available.</p>
<p><strong>Other methods</strong>:</p> <p><strong>Other methods</strong>:</p>
<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> <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> <ul>
...@@ -728,7 +740,7 @@ class UserList(generics.ListCreateAPIView): ...@@ -728,7 +740,7 @@ class UserList(generics.ListCreateAPIView):
serializer_class = UserSerializer serializer_class = UserSerializer
lookup_fields = ('account', 'username') lookup_fields = ('account', 'username')
</code></pre> </code></pre>
<p>Using custom mixins is a good option if you have custom behavior that needs to be used</p> <p>Using custom mixins is a good option if you have custom behavior that needs to be used.</p>
<h2 id="creating-custom-base-classes">Creating custom base classes</h2> <h2 id="creating-custom-base-classes">Creating custom base classes</h2>
<p>If you are using a mixin across multiple views, you can take this a step further and create your own set of base views that can then be used throughout your project. For example:</p> <p>If you are using a mixin across multiple views, you can take this a step further and create your own set of base views that can then be used throughout your project. For example:</p>
<pre><code>class BaseRetrieveView(MultipleFieldLookupMixin, <pre><code>class BaseRetrieveView(MultipleFieldLookupMixin,
...@@ -765,7 +777,7 @@ class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin, ...@@ -765,7 +777,7 @@ class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -540,7 +548,7 @@ class CustomPaginationSerializer(pagination.BasePaginationSerializer): ...@@ -540,7 +548,7 @@ class CustomPaginationSerializer(pagination.BasePaginationSerializer):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -449,7 +457,7 @@ sending more complex data than simple forms</p> ...@@ -449,7 +457,7 @@ sending more complex data than simple forms</p>
</blockquote> </blockquote>
<p>REST framework includes a number of built in Parser classes, that allow you to accept requests with various media types. There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts.</p> <p>REST framework includes a number of built in Parser classes, that allow you to accept requests with various media types. There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts.</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 <code>request.data</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>
<hr /> <hr />
<p><strong>Note</strong>: When developing client applications always remember to make sure you're setting the <code>Content-Type</code> header when sending data in an HTTP request.</p> <p><strong>Note</strong>: When developing client applications always remember to make sure you're setting the <code>Content-Type</code> header when sending data in an HTTP request.</p>
<p>If you don't set the content type, most clients will default to using <code>'application/x-www-form-urlencoded'</code>, which may not be what you wanted.</p> <p>If you don't set the content type, most clients will default to using <code>'application/x-www-form-urlencoded'</code>, which may not be what you wanted.</p>
...@@ -476,7 +484,7 @@ class ExampleView(APIView): ...@@ -476,7 +484,7 @@ class ExampleView(APIView):
parser_classes = (YAMLParser,) parser_classes = (YAMLParser,)
def post(self, request, format=None): def post(self, request, format=None):
return Response({'received data': request.DATA}) return Response({'received data': request.data})
</code></pre> </code></pre>
<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p> <p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
<pre><code>@api_view(['POST']) <pre><code>@api_view(['POST'])
...@@ -485,7 +493,7 @@ def example_view(request, format=None): ...@@ -485,7 +493,7 @@ def example_view(request, format=None):
""" """
A view that can accept POST requests with YAML content. A view that can accept POST requests with YAML content.
""" """
return Response({'received data': request.DATA}) return Response({'received data': request.data})
</code></pre> </code></pre>
<hr /> <hr />
<h1 id="api-reference">API Reference</h1> <h1 id="api-reference">API Reference</h1>
...@@ -503,15 +511,15 @@ def example_view(request, format=None): ...@@ -503,15 +511,15 @@ def example_view(request, format=None):
<p>Requires the <code>defusedxml</code> package to be installed.</p> <p>Requires the <code>defusedxml</code> package to be installed.</p>
<p><strong>.media_type</strong>: <code>application/xml</code></p> <p><strong>.media_type</strong>: <code>application/xml</code></p>
<h2 id="formparser">FormParser</h2> <h2 id="formparser">FormParser</h2>
<p>Parses HTML form content. <code>request.DATA</code> will be populated with a <code>QueryDict</code> of data, <code>request.FILES</code> will be populated with an empty <code>QueryDict</code> of data.</p> <p>Parses HTML form content. <code>request.data</code> will be populated with a <code>QueryDict</code> of data.</p>
<p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p> <p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p>
<p><strong>.media_type</strong>: <code>application/x-www-form-urlencoded</code></p> <p><strong>.media_type</strong>: <code>application/x-www-form-urlencoded</code></p>
<h2 id="multipartparser">MultiPartParser</h2> <h2 id="multipartparser">MultiPartParser</h2>
<p>Parses multipart HTML form content, which supports file uploads. Both <code>request.DATA</code> and <code>request.FILES</code> will be populated with a <code>QueryDict</code>.</p> <p>Parses multipart HTML form content, which supports file uploads. Both <code>request.data</code> will be populated with a <code>QueryDict</code>.</p>
<p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p> <p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p>
<p><strong>.media_type</strong>: <code>multipart/form-data</code></p> <p><strong>.media_type</strong>: <code>multipart/form-data</code></p>
<h2 id="fileuploadparser">FileUploadParser</h2> <h2 id="fileuploadparser">FileUploadParser</h2>
<p>Parses raw file upload content. The <code>request.DATA</code> property will be an empty <code>QueryDict</code>, and <code>request.FILES</code> will be a dictionary with a single key <code>'file'</code> containing the uploaded file.</p> <p>Parses raw file upload content. The <code>request.data</code> property will be a dictionary with a single key <code>'file'</code> containing the uploaded file.</p>
<p>If the view used with <code>FileUploadParser</code> is called with a <code>filename</code> URL keyword argument, then that argument will be used as the filename. If it is called without a <code>filename</code> URL keyword argument, then the client must set the filename in the <code>Content-Disposition</code> HTTP header. For example <code>Content-Disposition: attachment; filename=upload.jpg</code>.</p> <p>If the view used with <code>FileUploadParser</code> is called with a <code>filename</code> URL keyword argument, then that argument will be used as the filename. If it is called without a <code>filename</code> URL keyword argument, then the client must set the filename in the <code>Content-Disposition</code> HTTP header. For example <code>Content-Disposition: attachment; filename=upload.jpg</code>.</p>
<p><strong>.media_type</strong>: <code>*/*</code></p> <p><strong>.media_type</strong>: <code>*/*</code></p>
<h5 id="notes">Notes:</h5> <h5 id="notes">Notes:</h5>
...@@ -525,7 +533,7 @@ def example_view(request, format=None): ...@@ -525,7 +533,7 @@ def example_view(request, format=None):
parser_classes = (FileUploadParser,) parser_classes = (FileUploadParser,)
def put(self, request, filename, format=None): def put(self, request, filename, format=None):
file_obj = request.FILES['file'] file_obj = request.data['file']
# ... # ...
# do some staff with uploaded file # do some staff with uploaded file
# ... # ...
...@@ -534,7 +542,7 @@ def example_view(request, format=None): ...@@ -534,7 +542,7 @@ def example_view(request, format=None):
<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(self, stream, media_type, 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()</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>
...@@ -545,7 +553,7 @@ def example_view(request, format=None): ...@@ -545,7 +553,7 @@ def example_view(request, format=None):
<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>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> <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><code>class PlainTextParser(BaseParser): <pre><code>class PlainTextParser(BaseParser):
""" """
Plain text parser. Plain text parser.
...@@ -580,7 +588,7 @@ def parse(self, stream, media_type=None, parser_context=None): ...@@ -580,7 +588,7 @@ def parse(self, stream, media_type=None, parser_context=None):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -632,7 +640,7 @@ class BlacklistPermission(permissions.BasePermission): ...@@ -632,7 +640,7 @@ class BlacklistPermission(permissions.BasePermission):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -799,7 +807,7 @@ In this case you can underspecify the media types it should respond to, by using ...@@ -799,7 +807,7 @@ In this case you can underspecify the media types it should respond to, by using
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -350,15 +358,19 @@ ...@@ -350,15 +358,19 @@
<li> <li>
<a href="#data">.DATA</a> <a href="#data">.data</a>
</li> </li>
<li> <li>
<a href="#files">.FILES</a> <a href="#query_params">.query_params</a>
</li> </li>
<li> <li>
<a href="#query_params">.QUERY_PARAMS</a> <a href="#data-and-files">.DATA and .FILES</a>
</li>
<li>
<a href="#query_params_1">.QUERY_PARAMS</a>
</li> </li>
<li> <li>
...@@ -448,7 +460,10 @@ ...@@ -448,7 +460,10 @@
<h1 id="requests">Requests</h1> <hr />
<p><strong>Note</strong>: This is the documentation for the <strong>version 3.0</strong> of REST framework. Documentation for <a href="http://tomchristie.github.io/rest-framework-2-docs/">version 2.4</a> is also available.</p>
<hr />
<h1 id="requests">Requests</h1>
<blockquote> <blockquote>
<p>If you're doing REST-based web service stuff ... you should ignore request.POST.</p> <p>If you're doing REST-based web service stuff ... you should ignore request.POST.</p>
<p>&mdash; Malcom Tredinnick, <a href="https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion">Django developers group</a></p> <p>&mdash; Malcom Tredinnick, <a href="https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion">Django developers group</a></p>
...@@ -457,24 +472,26 @@ ...@@ -457,24 +472,26 @@
<hr /> <hr />
<h1 id="request-parsing">Request parsing</h1> <h1 id="request-parsing">Request parsing</h1>
<p>REST framework's Request objects provide flexible request parsing that allows you to treat requests with JSON data or other media types in the same way that you would normally deal with form data.</p> <p>REST framework's Request objects provide flexible request parsing that allows you to treat requests with JSON data or other media types in the same way that you would normally deal with form data.</p>
<h2 id="data">.DATA</h2> <h2 id="data">.data</h2>
<p><code>request.DATA</code> returns the parsed content of the request body. This is similar to the standard <code>request.POST</code> attribute except that:</p> <p><code>request.data</code> returns the parsed content of the request body. This is similar to the standard <code>request.POST</code> and <code>request.FILES</code> attributes except that:</p>
<ul> <ul>
<li>It includes all parsed content, including <em>file and non-file</em> inputs.</li>
<li>It supports parsing the content of HTTP methods other than <code>POST</code>, meaning that you can access the content of <code>PUT</code> and <code>PATCH</code> requests.</li> <li>It supports parsing the content of HTTP methods other than <code>POST</code>, meaning that you can access the content of <code>PUT</code> and <code>PATCH</code> requests.</li>
<li>It supports REST framework's flexible request parsing, rather than just supporting form data. For example you can handle incoming JSON data in the same way that you handle incoming form data.</li> <li>It supports REST framework's flexible request parsing, rather than just supporting form data. For example you can handle incoming JSON data in the same way that you handle incoming form data.</li>
</ul> </ul>
<p>For more details see the <a href="../parsers">parsers documentation</a>.</p> <p>For more details see the <a href="../parsers">parsers documentation</a>.</p>
<h2 id="files">.FILES</h2> <h2 id="query_params">.query_params</h2>
<p><code>request.FILES</code> returns any uploaded files that may be present in the content of the request body. This is the same as the standard <code>HttpRequest</code> behavior, except that the same flexible request parsing is used for <code>request.DATA</code>.</p> <p><code>request.query_params</code> is a more correctly named synonym for <code>request.GET</code>.</p>
<p>For more details see the <a href="../parsers">parsers documentation</a>.</p> <p>For clarity inside your code, we recommend using <code>request.query_params</code> instead of the Django's standard <code>request.GET</code>. Doing so will help keep your codebase more correct and obvious - any HTTP method type may include query parameters, not just <code>GET</code> requests.</p>
<h2 id="query_params">.QUERY_PARAMS</h2> <h2 id="data-and-files">.DATA and .FILES</h2>
<p><code>request.QUERY_PARAMS</code> is a more correctly named synonym for <code>request.GET</code>.</p> <p>The old-style version 2.x <code>request.data</code> and <code>request.FILES</code> attributes are still available, but are now pending deprecation in favor of the unified <code>request.data</code> attribute.</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="query_params_1">.QUERY_PARAMS</h2>
<p>The old-style version 2.x <code>request.QUERY_PARAMS</code> attribute is still available, but is now pending deprecation in favor of the more pythonic <code>request.query_params</code>.</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 set 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>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically set 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> 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>If a client sends a request with a content-type that cannot be parsed then a <code>UnsupportedMediaType</code> exception will be raised, which by default will be caught and return a <code>415 Unsupported Media Type</code> response.</p> <p>If a client sends a request with a content-type that cannot be parsed then a <code>UnsupportedMediaType</code> exception will be raised, which by default will be caught and return a <code>415 Unsupported Media Type</code> response.</p>
<hr /> <hr />
<h1 id="content-negotiation">Content negotiation</h1> <h1 id="content-negotiation">Content negotiation</h1>
...@@ -537,7 +554,7 @@ ...@@ -537,7 +554,7 @@
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -487,7 +495,7 @@ response['Cache-Control'] = 'no-cache' ...@@ -487,7 +495,7 @@ response['Cache-Control'] = 'no-cache'
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -420,7 +428,7 @@ class APIRootView(APIView): ...@@ -420,7 +428,7 @@ class APIRootView(APIView):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -635,7 +643,7 @@ app.router.register_model(MyModel) ...@@ -635,7 +643,7 @@ app.router.register_model(MyModel)
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -445,7 +453,7 @@ print api_settings.DEFAULT_AUTHENTICATION_CLASSES ...@@ -445,7 +453,7 @@ print api_settings.DEFAULT_AUTHENTICATION_CLASSES
) )
</code></pre> </code></pre>
<h4 id="default_parser_classes">DEFAULT_PARSER_CLASSES</h4> <h4 id="default_parser_classes">DEFAULT_PARSER_CLASSES</h4>
<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><code>( <pre><code>(
'rest_framework.parsers.JSONParser', 'rest_framework.parsers.JSONParser',
...@@ -677,7 +685,7 @@ If set to <code>None</code> then generic filtering is disabled.</p> ...@@ -677,7 +685,7 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -492,7 +500,7 @@ is_server_error() # 5xx ...@@ -492,7 +500,7 @@ is_server_error() # 5xx
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -654,7 +662,7 @@ self.assertEqual(response.content, '{"username": "lauren", "id": 4}') ...@@ -654,7 +662,7 @@ self.assertEqual(response.content, '{"username": "lauren", "id": 4}')
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -563,7 +571,7 @@ class UploadView(APIView): ...@@ -563,7 +571,7 @@ class UploadView(APIView):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -478,15 +486,22 @@ This method is used to enforce permissions and throttling, and perform content n ...@@ -478,15 +486,22 @@ This method is used to enforce permissions and throttling, and perform content n
</blockquote> </blockquote>
<p>REST framework also allows you to work with regular function based views. It provides a set of simple decorators that wrap your function based views to ensure they receive an instance of <code>Request</code> (rather than the usual Django <code>HttpRequest</code>) and allows them to return a <code>Response</code> (instead of a Django <code>HttpResponse</code>), and allow you to configure how the request is processed.</p> <p>REST framework also allows you to work with regular function based views. It provides a set of simple decorators that wrap your function based views to ensure they receive an instance of <code>Request</code> (rather than the usual Django <code>HttpRequest</code>) and allows them to return a <code>Response</code> (instead of a Django <code>HttpResponse</code>), and allow you to configure how the request is processed.</p>
<h2 id="api_view">@api_view()</h2> <h2 id="api_view">@api_view()</h2>
<p><strong>Signature:</strong> <code>@api_view(http_method_names)</code></p> <p><strong>Signature:</strong> <code>@api_view(http_method_names=['GET'])</code></p>
<p>The core of this functionality is the <code>api_view</code> decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data:</p> <p>The core of this functionality is the <code>api_view</code> decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data:</p>
<pre><code>from rest_framework.decorators import api_view <pre><code>from rest_framework.decorators import api_view
@api_view(['GET']) @api_view()
def hello_world(request): def hello_world(request):
return Response({"message": "Hello, world!"}) return Response({"message": "Hello, world!"})
</code></pre> </code></pre>
<p>This view will use the default renderers, parsers, authentication classes etc specified in the <a href="../settings">settings</a>.</p> <p>This view will use the default renderers, parsers, authentication classes etc specified in the <a href="../settings">settings</a>.</p>
<p>By default only <code>GET</code> methods will be accepted. Other methods will respond with "405 Method Not Allowed". To alter this behavior, specify which methods the view allows, like so:</p>
<pre><code>@api_view(['GET', 'POST'])
def hello_world(request):
if request.method == 'POST':
return Response({"message": "Got some data!", "data": request.data})
return Response({"message": "Hello, world!"})
</code></pre>
<h2 id="api-policy-decorators">API policy decorators</h2> <h2 id="api-policy-decorators">API policy decorators</h2>
<p>To override the default settings, REST framework provides a set of additional decorators which can be added to your views. These must come <em>after</em> (below) the <code>@api_view</code> decorator. For example, to create a view that uses a <a href="../throttling">throttle</a> to ensure it can only be called once per day by a particular user, use the <code>@throttle_classes</code> decorator, passing a list of throttle classes:</p> <p>To override the default settings, REST framework provides a set of additional decorators which can be added to your views. These must come <em>after</em> (below) the <code>@api_view</code> decorator. For example, to create a view that uses a <a href="../throttling">throttle</a> to ensure it can only be called once per day by a particular user, use the <code>@throttle_classes</code> decorator, passing a list of throttle classes:</p>
<pre><code>from rest_framework.decorators import api_view, throttle_classes <pre><code>from rest_framework.decorators import api_view, throttle_classes
...@@ -524,7 +539,7 @@ def view(request): ...@@ -524,7 +539,7 @@ def view(request):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../validators">Validators</a>
</li>
<li >
<a href="../authentication">Authentication</a> <a href="../authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -511,7 +519,7 @@ class UserViewSet(viewsets.ModelViewSet): ...@@ -511,7 +519,7 @@ class UserViewSet(viewsets.ModelViewSet):
@detail_route(methods=['post']) @detail_route(methods=['post'])
def set_password(self, request, pk=None): def set_password(self, request, pk=None):
user = self.get_object() user = self.get_object()
serializer = PasswordSerializer(data=request.DATA) serializer = PasswordSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
user.set_password(serializer.data['password']) user.set_password(serializer.data['password'])
user.save() user.save()
...@@ -615,7 +623,7 @@ class UserViewSet(viewsets.ModelViewSet): ...@@ -615,7 +623,7 @@ class UserViewSet(viewsets.ModelViewSet):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="api-guide/validators/">Validators</a>
</li>
<li >
<a href="api-guide/authentication/">Authentication</a> <a href="api-guide/authentication/">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="topics/3.0-announcement/">3.0 Announcement</a>
</li>
<li >
<a href="topics/kickstarter-announcement/">Kickstarter Announcement</a> <a href="topics/kickstarter-announcement/">Kickstarter Announcement</a>
</li> </li>
...@@ -453,7 +461,8 @@ ...@@ -453,7 +461,8 @@
</p> </p>
<hr /> <hr />
<p><strong>Note</strong>: The incoming 3.0 version has now been merged to the <code>master</code> branch on GitHub. For the source of the currently available PyPI version, please see the <code>2.4.4</code> tag.</p> <p><strong>Note</strong>: This is the documentation for the <strong>version 3.0</strong> of REST framework. Documentation for <a href="http://tomchristie.github.io/rest-framework-2-docs/">version 2.4</a> is also available.</p>
<p>For more details see the <a href="topics/3.0-announcement/">3.0 release notes</a>.</p>
<hr /> <hr />
<p> <p>
<h1 style="position: absolute; <h1 style="position: absolute;
...@@ -588,8 +597,8 @@ urlpatterns = [ ...@@ -588,8 +597,8 @@ urlpatterns = [
<li><a href="api-guide/renderers/">Renderers</a></li> <li><a href="api-guide/renderers/">Renderers</a></li>
<li><a href="api-guide/serializers/">Serializers</a></li> <li><a href="api-guide/serializers/">Serializers</a></li>
<li><a href="api-guide/fields/">Serializer fields</a></li> <li><a href="api-guide/fields/">Serializer fields</a></li>
<li><a href="api-guide/relations/">Serializer relations</a> <li><a href="api-guide/relations/">Serializer relations</a></li>
<!--* [Validators][validators]--></li> <li><a href="api-guide/validators/">Validators</a></li>
<li><a href="api-guide/authentication/">Authentication</a></li> <li><a href="api-guide/authentication/">Authentication</a></li>
<li><a href="api-guide/permissions/">Permissions</a></li> <li><a href="api-guide/permissions/">Permissions</a></li>
<li><a href="api-guide/throttling/">Throttling</a></li> <li><a href="api-guide/throttling/">Throttling</a></li>
...@@ -617,6 +626,7 @@ urlpatterns = [ ...@@ -617,6 +626,7 @@ urlpatterns = [
<li><a href="topics/2.2-announcement/">2.2 Announcement</a></li> <li><a href="topics/2.2-announcement/">2.2 Announcement</a></li>
<li><a href="topics/2.3-announcement/">2.3 Announcement</a></li> <li><a href="topics/2.3-announcement/">2.3 Announcement</a></li>
<li><a href="topics/2.4-announcement/">2.4 Announcement</a></li> <li><a href="topics/2.4-announcement/">2.4 Announcement</a></li>
<li><a href="topics/3.0-announcement/">3.0 Announcement</a></li>
<li><a href="topics/kickstarter-announcement/">Kickstarter Announcement</a></li> <li><a href="topics/kickstarter-announcement/">Kickstarter Announcement</a></li>
<li><a href="topics/release-notes/">Release Notes</a></li> <li><a href="topics/release-notes/">Release Notes</a></li>
<li><a href="topics/credits/">Credits</a></li> <li><a href="topics/credits/">Credits</a></li>
...@@ -668,7 +678,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p> ...@@ -668,7 +678,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -492,7 +500,7 @@ serializer.data ...@@ -492,7 +500,7 @@ serializer.data
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -629,7 +637,7 @@ urlpatterns = [ ...@@ -629,7 +637,7 @@ urlpatterns = [
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
<div class="navbar-inner"> <div class="navbar-inner">
<div class="container-fluid"> <div class="container-fluid">
<a class="repo-link btn btn-primary btn-small" href="https://github.com/tomchristie/django-rest-framework/tree/master">GitHub</a> <a class="repo-link btn btn-primary btn-small" href="https://github.com/tomchristie/django-rest-framework/tree/master">GitHub</a>
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../kickstarter-announcement"> <a class="repo-link btn btn-inverse btn-small " rel="prev" href="../3.0-announcement">
Next <i class="icon-arrow-right icon-white"></i> Next <i class="icon-arrow-right icon-white"></i>
</a> </a>
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../2.3-announcement"> <a class="repo-link btn btn-inverse btn-small " rel="next" href="../2.3-announcement">
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -515,7 +523,7 @@ The lowest supported version of Django is now 1.4.2.</p> ...@@ -515,7 +523,7 @@ The lowest supported version of Django is now 1.4.2.</p>
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -402,7 +410,7 @@ ...@@ -402,7 +410,7 @@
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -460,28 +468,18 @@ ...@@ -460,28 +468,18 @@
<p>You can override the <code>BrowsableAPIRenderer.get_context()</code> method to customise the context that gets passed to the template.</p> <p>You can override the <code>BrowsableAPIRenderer.get_context()</code> method to customise the context that gets passed to the template.</p>
<h4 id="not-using-basehtml">Not using base.html</h4> <h4 id="not-using-basehtml">Not using base.html</h4>
<p>For more advanced customization, such as not having a Bootstrap basis or tighter integration with the rest of your site, you can simply choose not to have <code>api.html</code> extend <code>base.html</code>. Then the page content and capabilities are entirely up to you.</p> <p>For more advanced customization, such as not having a Bootstrap basis or tighter integration with the rest of your site, you can simply choose not to have <code>api.html</code> extend <code>base.html</code>. Then the page content and capabilities are entirely up to you.</p>
<h4 id="autocompletion">Autocompletion</h4> <h4 id="handling-choicefield-with-large-numbers-of-items">Handling <code>ChoiceField</code> with large numbers of items.</h4>
<p>When a <code>ChoiceField</code> has too many items, rendering the widget containing all the options can become very slow, and cause the browsable API rendering to perform poorly. One solution is to replace the selector by an autocomplete widget, that only loads and renders a subset of the available options as needed.</p> <p>When a relationship or <code>ChoiceField</code> has too many items, rendering the widget containing all the options can become very slow, and cause the browsable API rendering to perform poorly.</p>
<p>There are <a href="https://www.djangopackages.com/grids/g/auto-complete/">a variety of packages for autocomplete widgets</a>, such as <a href="https://github.com/yourlabs/django-autocomplete-light">django-autocomplete-light</a>. To setup <code>django-autocomplete-light</code>, follow the <a href="http://django-autocomplete-light.readthedocs.org/en/latest/#install">installation documentation</a>, add the the following to the <code>api.html</code> template:</p> <p>The simplest option in this case is to replace the select input with a standard text input. For example:</p>
<pre><code>{% block script %} <pre><code> author = serializers.HyperlinkedRelatedField(
{{ block.super }} queryset=User.objects.all(),
{% include 'autocomplete_light/static.html' %} style={'base_template': 'input.html'}
{% endblock %} )
</code></pre> </code></pre>
<p>You can now add the <code>autocomplete_light.ChoiceWidget</code> widget to the serializer field.</p> <h4 id="autocomplete">Autocomplete</h4>
<pre><code>import autocomplete_light <p>An alternative, but more complex option would be to replace the input with an autocomplete widget, that only loads and renders a subset of the available options as needed. If you need to do this you'll need to do some work to build a custom autocomplete HTML template yourself.</p>
<p>There are <a href="https://www.djangopackages.com/grids/g/auto-complete/">a variety of packages for autocomplete widgets</a>, such as <a href="https://github.com/yourlabs/django-autocomplete-light">django-autocomplete-light</a>, that you may want to refer to. Note that you will not be able to simply include these components as standard widgets, but will need to write the HTML template explicitly. This is because REST framework 3.0 no longer supports the <code>widget</code> keyword argument since it now uses templated HTML generation.</p>
class BookSerializer(serializers.ModelSerializer): <p>Better support for autocomplete inputs is planned in future versions.</p>
author = serializers.ChoiceField(
widget=autocomplete_light.ChoiceWidget('AuthorAutocomplete')
)
class Meta:
model = Book
</code></pre>
<hr />
<p><img alt="Autocomplete" src="../../../img/autocomplete.png" /></p>
<p><em>Screenshot of the autocomplete-light widget</em></p>
<hr /> <hr />
</div> </div>
...@@ -497,7 +495,7 @@ class BookSerializer(serializers.ModelSerializer): ...@@ -497,7 +495,7 @@ class BookSerializer(serializers.ModelSerializer):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -445,7 +453,7 @@ as well as how to support content types other than form-encoded data.</p> ...@@ -445,7 +453,7 @@ as well as how to support content types other than form-encoded data.</p>
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -518,7 +526,6 @@ pip install -r requirements-test.txt ...@@ -518,7 +526,6 @@ pip install -r requirements-test.txt
<p>Some other tips:</p> <p>Some other tips:</p>
<ul> <ul>
<li>Keep paragraphs reasonably short.</li> <li>Keep paragraphs reasonably short.</li>
<li>Use double spacing after the end of sentences.</li>
<li>Don't use abbreviations such as 'e.g.' but instead use the long form, such as 'For example'.</li> <li>Don't use abbreviations such as 'e.g.' but instead use the long form, such as 'For example'.</li>
</ul> </ul>
<h2 id="markdown-style">Markdown style</h2> <h2 id="markdown-style">Markdown style</h2>
...@@ -566,7 +573,7 @@ More text... ...@@ -566,7 +573,7 @@ More text...
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -572,7 +580,7 @@ ...@@ -572,7 +580,7 @@
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -441,7 +449,7 @@ ...@@ -441,7 +449,7 @@
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../release-notes"> <a class="repo-link btn btn-inverse btn-small " rel="prev" href="../release-notes">
Next <i class="icon-arrow-right icon-white"></i> Next <i class="icon-arrow-right icon-white"></i>
</a> </a>
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../2.4-announcement"> <a class="repo-link btn btn-inverse btn-small " rel="next" href="../3.0-announcement">
<i class="icon-arrow-left icon-white"></i> Previous <i class="icon-arrow-left icon-white"></i> Previous
</a> </a>
<a class="repo-link btn btn-inverse btn-small" href="#searchModal" data-toggle="modal"><i class="icon-search icon-white"></i> Search</a> <a class="repo-link btn btn-inverse btn-small" href="#searchModal" data-toggle="modal"><i class="icon-search icon-white"></i> Search</a>
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -263,6 +267,10 @@ ...@@ -263,6 +267,10 @@
<a href="../2.4-announcement">2.4 Announcement</a> <a href="../2.4-announcement">2.4 Announcement</a>
</li> </li>
<li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li class="active" > <li class="active" >
<a href=".">Kickstarter Announcement</a> <a href=".">Kickstarter Announcement</a>
</li> </li>
...@@ -509,7 +517,7 @@ ...@@ -509,7 +517,7 @@
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -373,22 +381,6 @@ ...@@ -373,22 +381,6 @@
<a href="#20x-series">2.0.x series</a> <a href="#20x-series">2.0.x series</a>
</li> </li>
<li>
<a href="#04x-series">0.4.x series</a>
</li>
<li>
<a href="#03x-series">0.3.x series</a>
</li>
<li>
<a href="#02x-series">0.2.x series</a>
</li>
<li>
<a href="#01x-series">0.1.x series</a>
</li>
...@@ -790,7 +782,7 @@ ...@@ -790,7 +782,7 @@
<li>Bugfix: Validation errors instead of exceptions when related fields receive incorrect types.</li> <li>Bugfix: Validation errors instead of exceptions when related fields receive incorrect types.</li>
<li>Bugfix: Handle ObjectDoesNotExist exception when serializing null reverse one-to-one</li> <li>Bugfix: Handle ObjectDoesNotExist exception when serializing null reverse one-to-one</li>
</ul> </ul>
<p><strong>Note</strong>: Prior to 2.1.16, The Decimals would render in JSON using floating point if <code>simplejson</code> was installed, but otherwise render using string notation. Now that use of <code>simplejson</code> has been deprecated, Decimals will consistently render using string notation. See <a href="https://github.com/tomchristie/django-rest-framework/issues/582">#582</a> for more details.</p> <p><strong>Note</strong>: Prior to 2.1.16, The Decimals would render in JSON using floating point if <code>simplejson</code> was installed, but otherwise render using string notation. Now that use of <code>simplejson</code> has been deprecated, Decimals will consistently render using string notation. See <a href="../../ticket-582">ticket 582</a> for more details.</p>
<h3 id="2115">2.1.15</h3> <h3 id="2115">2.1.15</h3>
<p><strong>Date</strong>: 3rd Jan 2013</p> <p><strong>Date</strong>: 3rd Jan 2013</p>
<ul> <ul>
...@@ -936,124 +928,7 @@ ...@@ -936,124 +928,7 @@
<li><strong>Fix all of the things.</strong> (Well, almost.)</li> <li><strong>Fix all of the things.</strong> (Well, almost.)</li>
<li>For more information please see the <a href="../rest-framework-2-announcement">2.0 announcement</a>.</li> <li>For more information please see the <a href="../rest-framework-2-announcement">2.0 announcement</a>.</li>
</ul> </ul>
<hr /> <p>For older release notes, <a href="../../old-release-notes">please see the GitHub repo</a>.</p>
<h2 id="04x-series">0.4.x series</h2>
<h3 id="040">0.4.0</h3>
<ul>
<li>Supports Django 1.5.</li>
<li>Fixes issues with 'HEAD' method.</li>
<li>Allow views to specify template used by TemplateRenderer</li>
<li>More consistent error responses</li>
<li>Some serializer fixes</li>
<li>Fix internet explorer ajax behavior</li>
<li>Minor xml and yaml fixes</li>
<li>Improve setup (e.g. use staticfiles, not the defunct ADMIN_MEDIA_PREFIX)</li>
<li>Sensible absolute URL generation, not using hacky set_script_prefix</li>
</ul>
<hr />
<h2 id="03x-series">0.3.x series</h2>
<h3 id="033">0.3.3</h3>
<ul>
<li>Added DjangoModelPermissions class to support <code>django.contrib.auth</code> style permissions.</li>
<li>Use <code>staticfiles</code> for css files.</li>
<li>Easier to override. Won't conflict with customized admin styles (e.g. grappelli)</li>
<li>Templates are now nicely namespaced.</li>
<li>Allows easier overriding.</li>
<li>Drop implied 'pk' filter if last arg in urlconf is unnamed.</li>
<li>Too magical. Explicit is better than implicit.</li>
<li>Saner template variable auto-escaping.</li>
<li>Tidier setup.py</li>
<li>Updated for URLObject 2.0</li>
<li>Bugfixes:</li>
<li>Bug with PerUserThrottling when user contains unicode chars.</li>
</ul>
<h3 id="032">0.3.2</h3>
<ul>
<li>Bugfixes:</li>
<li>Fix 403 for POST and PUT from the UI with UserLoggedInAuthentication (#115)</li>
<li>serialize_model method in serializer.py may cause wrong value (#73)</li>
<li>Fix Error when clicking OPTIONS button (#146)</li>
<li>And many other fixes</li>
<li>Remove short status codes</li>
<li>Zen of Python: "There should be one-- and preferably only one --obvious way to do it."</li>
<li>get_name, get_description become methods on the view - makes them overridable.</li>
<li>Improved model mixin API - Hooks for build_query, get_instance_data, get_model, get_queryset, get_ordering</li>
</ul>
<h3 id="031">0.3.1</h3>
<ul>
<li>[not documented]</li>
</ul>
<h3 id="030">0.3.0</h3>
<ul>
<li>JSONP Support</li>
<li>Bugfixes, including support for latest markdown release</li>
</ul>
<hr />
<h2 id="02x-series">0.2.x series</h2>
<h3 id="024">0.2.4</h3>
<ul>
<li>Fix broken IsAdminUser permission.</li>
<li>OPTIONS support.</li>
<li>XMLParser.</li>
<li>Drop mentions of Blog, BitBucket.</li>
</ul>
<h3 id="023">0.2.3</h3>
<ul>
<li>Fix some throttling bugs.</li>
<li><code>X-Throttle</code> header on throttling.</li>
<li>Support for nesting resources on related models.</li>
</ul>
<h3 id="022">0.2.2</h3>
<ul>
<li>Throttling support complete.</li>
</ul>
<h3 id="021">0.2.1</h3>
<ul>
<li>Couple of simple bugfixes over 0.2.0</li>
</ul>
<h3 id="020">0.2.0</h3>
<ul>
<li>
<p>Big refactoring changes since 0.1.0, ask on the discussion group if anything isn't clear.
The public API has been massively cleaned up. Expect it to be fairly stable from here on in.</p>
</li>
<li>
<p><code>Resource</code> becomes decoupled into <code>View</code> and <code>Resource</code>, your views should now inherit from <code>View</code>, not <code>Resource</code>.</p>
</li>
<li>
<p>The handler functions on views <code>.get() .put() .post()</code> etc, no longer have the <code>content</code> and <code>auth</code> args.
Use <code>self.CONTENT</code> inside a view to access the deserialized, validated content.
Use <code>self.user</code> inside a view to access the authenticated user.</p>
</li>
<li>
<p><code>allowed_methods</code> and <code>anon_allowed_methods</code> are now defunct. if a method is defined, it's available.
The <code>permissions</code> attribute on a <code>View</code> is now used to provide generic permissions checking.
Use permission classes such as <code>FullAnonAccess</code>, <code>IsAuthenticated</code> or <code>IsUserOrIsAnonReadOnly</code> to set the permissions.</p>
</li>
<li>
<p>The <code>authenticators</code> class becomes <code>authentication</code>. Class names change to <code>Authentication</code>.</p>
</li>
<li>
<p>The <code>emitters</code> class becomes <code>renderers</code>. Class names change to <code>Renderers</code>.</p>
</li>
<li>
<p><code>ResponseException</code> becomes <code>ErrorResponse</code>.</p>
</li>
<li>
<p>The mixin classes have been nicely refactored, the basic mixins are now <code>RequestMixin</code>, <code>ResponseMixin</code>, <code>AuthMixin</code>, and <code>ResourceMixin</code>
You can reuse these mixin classes individually without using the <code>View</code> class.</p>
</li>
</ul>
<hr />
<h2 id="01x-series">0.1.x series</h2>
<h3 id="011">0.1.1</h3>
<ul>
<li>Final build before pulling in all the refactoring changes for 0.2, in case anyone needs to hang on to 0.1.</li>
</ul>
<h3 id="010">0.1.0</h3>
<ul>
<li>Initial release.</li>
</ul>
</div> </div>
<!--/span--> <!--/span-->
...@@ -1068,7 +943,7 @@ ...@@ -1068,7 +943,7 @@
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -452,7 +460,7 @@ ...@@ -452,7 +460,7 @@
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -368,11 +376,11 @@ ...@@ -368,11 +376,11 @@
<h1 id="rest-hypermedia-hateoas">REST, Hypermedia &amp; HATEOAS</h1> <h1 id="rest-hypermedia-hateoas">REST, Hypermedia &amp; HATEOAS</h1>
<blockquote> <blockquote>
<p>You keep using that word "REST". I do not think it means what you think it means.</p> <p>You keep using that word "REST". I do not think it means what you think it means.</p>
<p>&mdash; Mike Amundsen, <a href="http://vimeo.com/channels/restfest/page:2">REST fest 2012 keynote</a>.</p> <p>&mdash; Mike Amundsen, <a href="http://vimeo.com/channels/restfest/page:2">REST fest 2012 keynote</a>.</p>
</blockquote> </blockquote>
<p>First off, the disclaimer. The name "Django REST framework" was chosen simply to sure the project would be easily found by developers. Throughout the documentation we try to use the more simple and technically correct terminology of "Web APIs".</p> <p>First off, the disclaimer. The name "Django REST framework" was decided back in early 2011 and was chosen simply to sure the project would be easily found by developers. Throughout the documentation we try to use the more simple and technically correct terminology of "Web APIs".</p>
<p>If you are serious about designing a Hypermedia APIs, you should look to resources outside of this documentation to help inform your design choices.</p> <p>If you are serious about designing a Hypermedia API, you should look to resources outside of this documentation to help inform your design choices.</p>
<p>The following fall into the "required reading" category.</p> <p>The following fall into the "required reading" category.</p>
<ul> <ul>
<li>Roy Fielding's dissertation - <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">Architectural Styles and <li>Roy Fielding's dissertation - <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">Architectural Styles and
...@@ -390,7 +398,7 @@ the Design of Network-based Software Architectures</a>.</li> ...@@ -390,7 +398,7 @@ the Design of Network-based Software Architectures</a>.</li>
<p>It is self evident that REST framework makes it possible to build Hypermedia APIs. The browsable API that it offers is built on HTML - the hypermedia language of the web.</p> <p>It is self evident that REST framework makes it possible to build Hypermedia APIs. The browsable API that it offers is built on HTML - the hypermedia language of the web.</p>
<p>REST framework also includes <a href="../../api-guide/serializers">serialization</a> and <a href="../../api-guide/parsers">parser</a>/<a href="../../api-guide/renderers">renderer</a> components that make it easy to build appropriate media types, <a href="../../api-guide/fields">hyperlinked relations</a> for building well-connected systems, and great support for <a href="../../api-guide/content-negotiation">content negotiation</a>.</p> <p>REST framework also includes <a href="../../api-guide/serializers">serialization</a> and <a href="../../api-guide/parsers">parser</a>/<a href="../../api-guide/renderers">renderer</a> components that make it easy to build appropriate media types, <a href="../../api-guide/fields">hyperlinked relations</a> for building well-connected systems, and great support for <a href="../../api-guide/content-negotiation">content negotiation</a>.</p>
<h2 id="what-rest-framework-doesnt-provide">What REST framework doesn't provide.</h2> <h2 id="what-rest-framework-doesnt-provide">What REST framework doesn't provide.</h2>
<p>What REST framework doesn't do is give you is machine readable hypermedia formats such as <a href="http://stateless.co/hal_specification.html">HAL</a>, <a href="http://www.amundsen.com/media-types/collection/">Collection+JSON</a>, <a href="http://jsonapi.org/">JSON API</a> or HTML <a href="http://microformats.org/wiki/Main_Page">microformats</a> by default, or the ability to auto-magically create fully HATEOAS style APIs that include hypermedia-based form descriptions and semantically labelled hyperlinks. Doing so would involve making opinionated choices about API design that should really remain outside of the framework's scope.</p> <p>What REST framework doesn't do is give you is machine readable hypermedia formats such as <a href="http://stateless.co/hal_specification.html">HAL</a>, <a href="http://www.amundsen.com/media-types/collection/">Collection+JSON</a>, <a href="http://jsonapi.org/">JSON API</a> or HTML <a href="http://microformats.org/wiki/Main_Page">microformats</a> by default, or the ability to auto-magically create fully HATEOAS style APIs that include hypermedia-based form descriptions and semantically labelled hyperlinks. Doing so would involve making opinionated choices about API design that should really remain outside of the framework's scope.</p>
</div> </div>
<!--/span--> <!--/span-->
...@@ -405,7 +413,7 @@ the Design of Network-based Software Architectures</a>.</li> ...@@ -405,7 +413,7 @@ the Design of Network-based Software Architectures</a>.</li>
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../kickstarter-announcement">Kickstarter Announcement</a> <a href="../kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -373,9 +381,9 @@ ...@@ -373,9 +381,9 @@
<h1 id="third-party-resources">Third Party Resources</h1> <h1 id="third-party-resources">Third Party Resources</h1>
<h2 id="about-third-party-packages">About Third Party Packages</h2> <h2 id="about-third-party-packages">About Third Party Packages</h2>
<p>Third Party Packages allow developers to share code that extends the functionality of Django REST framework, in order to support additional use-cases.</p> <p>Third Party Packages allow developers to share code that extends the functionality of Django REST framework, in order to support additional use-cases.</p>
<p>We <strong>support</strong>, <strong>encourage</strong> and <strong>strongly favour</strong> the creation of Third Party Packages to encapsulate new behaviour rather than adding additional functionality directly to Django REST Framework.</p> <p>We <strong>support</strong>, <strong>encourage</strong> and <strong>strongly favor</strong> the creation of Third Party Packages to encapsulate new behavior rather than adding additional functionality directly to Django REST Framework.</p>
<p>We aim to make creating Third Party Packages as easy as possible, whilst keeping the <strong>simplicity</strong> of the core API and ensuring that <strong>maintenance</strong> of the main project remains under control. If a Third Party Package proves popular it is relatively easy to move it into the main project; removing features is much more problematic.</p> <p>We aim to make creating third party packages as easy as possible, whilst keeping a <strong>simple</strong> and <strong>well maintained</strong> core API. By promoting third party packages we ensure that the responsibility for a package remains with its author. If a package proves suitably popular it can always be considered for inclusion into the core REST framework.</p>
<p>If you have an idea for a new feature please consider how it may be packaged as a Third Party Package. We're always happy to dicuss ideas on the <a href="https://groups.google.com/forum/#!forum/django-rest-framework">Mailing List</a>.</p> <p>If you have an idea for a new feature please consider how it may be packaged as a Third Party Package. We're always happy to discuss ideas on the <a href="https://groups.google.com/forum/#!forum/django-rest-framework">Mailing List</a>.</p>
<h2 id="how-to-create-a-third-party-package">How to create a Third Party Package</h2> <h2 id="how-to-create-a-third-party-package">How to create a Third Party Package</h2>
<h3 id="creating-your-package">Creating your package</h3> <h3 id="creating-your-package">Creating your package</h3>
<p>You can use <a href="https://github.com/jpadilla/cookiecutter-django-rest-framework">this cookiecutter template</a> for creating reusable Django REST Framework packages quickly. Cookiecutter creates projects from project templates. While optional, this cookiecutter template includes best practices from Django REST framework and other packages, as well as a Travis CI configuration, Tox configuration, and a sane setup.py for easy PyPI registration/distribution.</p> <p>You can use <a href="https://github.com/jpadilla/cookiecutter-django-rest-framework">this cookiecutter template</a> for creating reusable Django REST Framework packages quickly. Cookiecutter creates projects from project templates. While optional, this cookiecutter template includes best practices from Django REST framework and other packages, as well as a Travis CI configuration, Tox configuration, and a sane setup.py for easy PyPI registration/distribution.</p>
...@@ -581,7 +589,7 @@ You probably want to also tag the version now: ...@@ -581,7 +589,7 @@ You probably want to also tag the version now:
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -703,7 +711,7 @@ Quit the server with CONTROL-C. ...@@ -703,7 +711,7 @@ Quit the server with CONTROL-C.
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -390,9 +398,9 @@ ...@@ -390,9 +398,9 @@
<p>From this point we're going to really start covering the core of REST framework. <p>From this point we're going to really start covering the core of REST framework.
Let's introduce a couple of essential building blocks.</p> Let's introduce a couple of essential building blocks.</p>
<h2 id="request-objects">Request objects</h2> <h2 id="request-objects">Request objects</h2>
<p>REST framework introduces a <code>Request</code> object that extends the regular <code>HttpRequest</code>, and provides more flexible request parsing. The core functionality of the <code>Request</code> object is the <code>request.DATA</code> attribute, which is similar to <code>request.POST</code>, but more useful for working with Web APIs.</p> <p>REST framework introduces a <code>Request</code> object that extends the regular <code>HttpRequest</code>, and provides more flexible request parsing. The core functionality of the <code>Request</code> object is the <code>request.data</code> attribute, which is similar to <code>request.POST</code>, but more useful for working with Web APIs.</p>
<pre><code>request.POST # Only handles form data. Only works for 'POST' method. <pre><code>request.POST # Only handles form data. Only works for 'POST' method.
request.DATA # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods. request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
</code></pre> </code></pre>
<h2 id="response-objects">Response objects</h2> <h2 id="response-objects">Response objects</h2>
<p>REST framework also introduces a <code>Response</code> object, which is a type of <code>TemplateResponse</code> that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.</p> <p>REST framework also introduces a <code>Response</code> object, which is a type of <code>TemplateResponse</code> that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.</p>
...@@ -407,7 +415,7 @@ request.DATA # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' met ...@@ -407,7 +415,7 @@ request.DATA # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' met
<li>The <code>APIView</code> class for working with class based views.</li> <li>The <code>APIView</code> class for working with class based views.</li>
</ol> </ol>
<p>These wrappers provide a few bits of functionality such as making sure you receive <code>Request</code> instances in your view, and adding context to <code>Response</code> objects so that content negotiation can be performed.</p> <p>These wrappers provide a few bits of functionality such as making sure you receive <code>Request</code> instances in your view, and adding context to <code>Response</code> objects so that content negotiation can be performed.</p>
<p>The wrappers also provide behaviour such as returning <code>405 Method Not Allowed</code> responses when appropriate, and handling any <code>ParseError</code> exception that occurs when accessing <code>request.DATA</code> with malformed input.</p> <p>The wrappers also provide behaviour such as returning <code>405 Method Not Allowed</code> responses when appropriate, and handling any <code>ParseError</code> exception that occurs when accessing <code>request.data</code> with malformed input.</p>
<h2 id="pulling-it-all-together">Pulling it all together</h2> <h2 id="pulling-it-all-together">Pulling it all together</h2>
<p>Okay, let's go ahead and start using these new components to write a few views.</p> <p>Okay, let's go ahead and start using these new components to write a few views.</p>
<p>We don't need our <code>JSONResponse</code> class in <code>views.py</code> anymore, so go ahead and delete that. Once that's done we can start refactoring our views slightly.</p> <p>We don't need our <code>JSONResponse</code> class in <code>views.py</code> anymore, so go ahead and delete that. Once that's done we can start refactoring our views slightly.</p>
...@@ -429,7 +437,7 @@ def snippet_list(request): ...@@ -429,7 +437,7 @@ def snippet_list(request):
return Response(serializer.data) return Response(serializer.data)
elif request.method == 'POST': elif request.method == 'POST':
serializer = SnippetSerializer(data=request.DATA) serializer = SnippetSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
...@@ -452,7 +460,7 @@ def snippet_detail(request, pk): ...@@ -452,7 +460,7 @@ def snippet_detail(request, pk):
return Response(serializer.data) return Response(serializer.data)
elif request.method == 'PUT': elif request.method == 'PUT':
serializer = SnippetSerializer(snippet, data=request.DATA) serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data) return Response(serializer.data)
...@@ -463,7 +471,7 @@ def snippet_detail(request, pk): ...@@ -463,7 +471,7 @@ def snippet_detail(request, pk):
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
</code></pre> </code></pre>
<p>This should all feel very familiar - it is not a lot different from working with regular Django views.</p> <p>This should all feel very familiar - it is not a lot different from working with regular Django views.</p>
<p>Notice that we're no longer explicitly tying our requests or responses to a given content type. <code>request.DATA</code> can handle incoming <code>json</code> requests, but it can also handle <code>yaml</code> and other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us.</p> <p>Notice that we're no longer explicitly tying our requests or responses to a given content type. <code>request.data</code> can handle incoming <code>json</code> requests, but it can also handle <code>yaml</code> and other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us.</p>
<h2 id="adding-optional-format-suffixes-to-our-urls">Adding optional format suffixes to our URLs</h2> <h2 id="adding-optional-format-suffixes-to-our-urls">Adding optional format suffixes to our URLs</h2>
<p>To take advantage of the fact that our responses are no longer hardwired to a single content type let's add support for format suffixes to our API endpoints. Using format suffixes gives us URLs that explicitly refer to a given format, and means our API will be able to handle URLs such as <a href="http://example.com/api/items/4.json">http://example.com/api/items/4.json</a>.</p> <p>To take advantage of the fact that our responses are no longer hardwired to a single content type let's add support for format suffixes to our API endpoints. Using format suffixes gives us URLs that explicitly refer to a given format, and means our API will be able to handle URLs such as <a href="http://example.com/api/items/4.json">http://example.com/api/items/4.json</a>.</p>
<p>Start by adding a <code>format</code> keyword argument to both of the views, like so.</p> <p>Start by adding a <code>format</code> keyword argument to both of the views, like so.</p>
...@@ -532,7 +540,7 @@ curl -X POST http://127.0.0.1:8000/snippets/ -d '{"code": "print 456"}' -H "Cont ...@@ -532,7 +540,7 @@ curl -X POST http://127.0.0.1:8000/snippets/ -d '{"code": "print 456"}' -H "Cont
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -388,7 +396,7 @@ class SnippetList(APIView): ...@@ -388,7 +396,7 @@ class SnippetList(APIView):
return Response(serializer.data) return Response(serializer.data)
def post(self, request, format=None): def post(self, request, format=None):
serializer = SnippetSerializer(data=request.DATA) serializer = SnippetSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
...@@ -412,7 +420,7 @@ class SnippetList(APIView): ...@@ -412,7 +420,7 @@ class SnippetList(APIView):
def put(self, request, pk, format=None): def put(self, request, pk, format=None):
snippet = self.get_object(pk) snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet, data=request.DATA) serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data) return Response(serializer.data)
...@@ -509,7 +517,7 @@ class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): ...@@ -509,7 +517,7 @@ class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -566,7 +574,7 @@ class IsOwnerOrReadOnly(permissions.BasePermission): ...@@ -566,7 +574,7 @@ class IsOwnerOrReadOnly(permissions.BasePermission):
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -519,7 +527,7 @@ urlpatterns += [ ...@@ -519,7 +527,7 @@ urlpatterns += [
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -509,7 +517,7 @@ urlpatterns = [ ...@@ -509,7 +517,7 @@ urlpatterns = [
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
...@@ -165,6 +165,10 @@ ...@@ -165,6 +165,10 @@
</li> </li>
<li > <li >
<a href="../../api-guide/validators">Validators</a>
</li>
<li >
<a href="../../api-guide/authentication">Authentication</a> <a href="../../api-guide/authentication">Authentication</a>
</li> </li>
...@@ -264,6 +268,10 @@ ...@@ -264,6 +268,10 @@
</li> </li>
<li > <li >
<a href="../../topics/3.0-announcement">3.0 Announcement</a>
</li>
<li >
<a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a> <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
</li> </li>
...@@ -530,7 +538,7 @@ REST_FRAMEWORK = { ...@@ -530,7 +538,7 @@ REST_FRAMEWORK = {
<!--/.wrapper --> <!--/.wrapper -->
<footer class="span12"> <footer class="span12">
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a> <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</a>
</p> </p>
</footer> </footer>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment