aboutsummaryrefslogtreecommitdiffstats
path: root/topics
diff options
context:
space:
mode:
Diffstat (limited to 'topics')
-rw-r--r--topics/2.2-announcement.html350
-rw-r--r--topics/2.3-announcement.html443
-rw-r--r--topics/ajax-csrf-cors.html263
-rw-r--r--topics/browsable-api.html357
-rw-r--r--topics/browser-enhancements.html297
-rw-r--r--topics/contributing.html351
-rw-r--r--topics/credits.html432
-rw-r--r--topics/documenting-your-api.html302
-rw-r--r--topics/release-notes.html771
-rw-r--r--topics/rest-framework-2-announcement.html298
-rw-r--r--topics/rest-hypermedia-hateoas.html266
-rw-r--r--topics/writable-nested-serializers.html274
12 files changed, 4404 insertions, 0 deletions
diff --git a/topics/2.2-announcement.html b/topics/2.2-announcement.html
new file mode 100644
index 00000000..fbd04e29
--- /dev/null
+++ b/topics/2.2-announcement.html
@@ -0,0 +1,350 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - REST framework 2.2 announcement</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, REST framework 2.2 announcement">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="2.2-announcement-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/2.3-announcement.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/rest-framework-2-announcement.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#rest-framework-22-announcement">REST framework 2.2 announcement</a></li>
+<li><a href="#python-3-support">Python 3 support</a></li>
+<li><a href="#deprecation-policy">Deprecation policy</a></li>
+<li><a href="#community">Community</a></li>
+<li><a href="#api-changes">API changes</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="rest-framework-22-announcement">REST framework 2.2 announcement</h1>
+<p>The 2.2 release represents an important point for REST framework, with the addition of Python 3 support, and the introduction of an official deprecation policy.</p>
+<h2 id="python-3-support">Python 3 support</h2>
+<p>Thanks to some fantastic work from <a href="https://github.com/xordoquy">Xavier Ordoquy</a>, Django REST framework 2.2 now supports Python 3. You'll need to be running Django 1.5, and it's worth keeping in mind that Django's Python 3 support is currently <a href="https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3">considered experimental</a>.</p>
+<p>Django 1.6's Python 3 support is expected to be officially labeled as 'production-ready'.</p>
+<p>If you want to start ensuring that your own projects are Python 3 ready, we can highly recommend Django's <a href="https://docs.djangoproject.com/en/dev/topics/python3/">Porting to Python 3</a> documentation.</p>
+<p>Django REST framework's Python 2.6 support now requires 2.6.5 or above, in line with <a href="https://docs.djangoproject.com/en/dev/releases/1.5/#python-compatibility">Django 1.5's Python compatibility</a>.</p>
+<h2 id="deprecation-policy">Deprecation policy</h2>
+<p>We've now introduced an official deprecation policy, which is in line with <a href="https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy">Django's deprecation policy</a>. This policy will make it easy for you to continue to track the latest, greatest version of REST framework.</p>
+<p>The timeline for deprecation works as follows:</p>
+<ul>
+<li>
+<p>Version 2.2 introduces some API changes as detailed in the release notes. It remains fully backwards compatible with 2.1, but will raise <code>PendingDeprecationWarning</code> warnings if you use bits of API that are due to be deprecated. These warnings are silent by default, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using <code>python -Wd manage.py test</code>, you'll be warned of any API changes you need to make.</p>
+</li>
+<li>
+<p>Version 2.3 will escalate these warnings to <code>DeprecationWarning</code>, which is loud by default.</p>
+</li>
+<li>
+<p>Version 2.4 will remove the deprecated bits of API entirely.</p>
+</li>
+</ul>
+<p>Note that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.</p>
+<h2 id="community">Community</h2>
+<p>As of the 2.2 merge, we've also hit an impressive milestone. The number of committers listed in <a href="http://django-rest-framework.org/topics/credits.html">the credits</a>, is now at over <strong>one hundred individuals</strong>. Each name on that list represents at least one merged pull request, however large or small.</p>
+<p>Our <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">mailing list</a> and #restframework IRC channel are also very active, and we've got a really impressive rate of development both on REST framework itself, and on third party packages such as the great <a href="https://github.com/marcgibbons/django-rest-framework-docs">django-rest-framework-docs</a> package from <a href="https://github.com/marcgibbons/">Marc Gibbons</a>.</p>
+<hr />
+<h2 id="api-changes">API changes</h2>
+<p>The 2.2 release makes a few changes to the API, in order to make it more consistent, simple, and easier to use.</p>
+<h3 id="cleaner-to-many-related-fields">Cleaner to-many related fields</h3>
+<p>The <code>ManyRelatedField()</code> style is being deprecated in favor of a new <code>RelatedField(many=True)</code> syntax.</p>
+<p>For example, if a user is associated with multiple questions, which we want to represent using a primary key relationship, we might use something like the following: </p>
+<pre class="prettyprint lang-py"><code>class UserSerializer(serializers.HyperlinkedModelSerializer):
+ questions = serializers.PrimaryKeyRelatedField(many=True)
+
+ class Meta:
+ fields = ('username', 'questions')
+</code></pre>
+<p>The new syntax is cleaner and more obvious, and the change will also make the documentation cleaner, simplify the internal API, and make writing custom relational fields easier.</p>
+<p>The change also applies to serializers. If you have a nested serializer, you should start using <code>many=True</code> for to-many relationships. For example, a serializer representation of an Album that can contain many Tracks might look something like this:</p>
+<pre class="prettyprint lang-py"><code>class TrackSerializer(serializer.ModelSerializer):
+ class Meta:
+ model = Track
+ fields = ('name', 'duration')
+
+class AlbumSerializer(serializer.ModelSerializer):
+ tracks = TrackSerializer(many=True)
+
+ class Meta:
+ model = Album
+ fields = ('album_name', 'artist', 'tracks')
+</code></pre>
+<p>Additionally, the change also applies when serializing or deserializing data. For example to serialize a queryset of models you should now use the <code>many=True</code> flag.</p>
+<pre class="prettyprint lang-py"><code>serializer = SnippetSerializer(Snippet.objects.all(), many=True)
+serializer.data
+</code></pre>
+<p>This more explicit behavior on serializing and deserializing data <a href="https://github.com/tomchristie/django-rest-framework/issues/564">makes integration with non-ORM backends such as MongoDB easier</a>, as instances to be serialized can include the <code>__iter__</code> method, without incorrectly triggering list-based serialization, or requiring workarounds.</p>
+<p>The implicit to-many behavior on serializers, and the <code>ManyRelatedField</code> style classes will continue to function, but will raise a <code>PendingDeprecationWarning</code>, which can be made visible using the <code>-Wd</code> flag.</p>
+<p><strong>Note</strong>: If you need to forcibly turn off the implicit "<code>many=True</code> for <code>__iter__</code> objects" behavior, you can now do so by specifying <code>many=False</code>. This will become the default (instead of the current default of <code>None</code>) once the deprecation of the implicit behavior is finalised in version 2.4.</p>
+<h3 id="cleaner-optional-relationships">Cleaner optional relationships</h3>
+<p>Serializer relationships for nullable Foreign Keys will change from using the current <code>null=True</code> flag, to instead using <code>required=False</code>.</p>
+<p>For example, is a user account has an optional foreign key to a company, that you want to express using a hyperlink, you might use the following field in a <code>Serializer</code> class:</p>
+<pre class="prettyprint lang-py"><code>current_company = serializers.HyperlinkedRelatedField(required=False)
+</code></pre>
+<p>This is in line both with the rest of the serializer fields API, and with Django's <code>Form</code> and <code>ModelForm</code> API.</p>
+<p>Using <code>required</code> throughout the serializers API means you won't need to consider if a particular field should take <code>blank</code> or <code>null</code> arguments instead of <code>required</code>, and also means there will be more consistent behavior for how fields are treated when they are not present in the incoming data. </p>
+<p>The <code>null=True</code> argument will continue to function, and will imply <code>required=False</code>, but will raise a <code>PendingDeprecationWarning</code>.</p>
+<h3 id="cleaner-charfield-syntax">Cleaner CharField syntax</h3>
+<p>The <code>CharField</code> API previously took an optional <code>blank=True</code> argument, which was intended to differentiate between null CharField input, and blank CharField input.</p>
+<p>In keeping with Django's CharField API, REST framework's <code>CharField</code> will only ever return the empty string, for missing or <code>None</code> inputs. The <code>blank</code> flag will no longer be in use, and you should instead just use the <code>required=&lt;bool&gt;</code> flag. For example:</p>
+<pre class="prettyprint lang-py"><code>extra_details = CharField(required=False)
+</code></pre>
+<p>The <code>blank</code> keyword argument will continue to function, but will raise a <code>PendingDeprecationWarning</code>.</p>
+<h3 id="simpler-object-level-permissions">Simpler object-level permissions</h3>
+<p>Custom permissions classes previously used the signature <code>.has_permission(self, request, view, obj=None)</code>. This method would be called twice, firstly for the global permissions check, with the <code>obj</code> parameter set to <code>None</code>, and again for the object-level permissions check when appropriate, with the <code>obj</code> parameter set to the relevant model instance.</p>
+<p>The global permissions check and object-level permissions check are now separated into two separate methods, which gives a cleaner, more obvious API.</p>
+<ul>
+<li>Global permission checks now use the <code>.has_permission(self, request, view)</code> signature.</li>
+<li>Object-level permission checks use a new method <code>.has_object_permission(self, request, view, obj)</code>.</li>
+</ul>
+<p>For example, the following custom permission class:</p>
+<pre class="prettyprint lang-py"><code>class IsOwner(permissions.BasePermission):
+ """
+ Custom permission to only allow owners of an object to view or edit it.
+ Model instances are expected to include an `owner` attribute.
+ """
+
+ def has_permission(self, request, view, obj=None):
+ if obj is None:
+ # Ignore global permissions check
+ return True
+
+ return obj.owner == request.user
+</code></pre>
+<p>Now becomes:</p>
+<pre class="prettyprint lang-py"><code>class IsOwner(permissions.BasePermission):
+ """
+ Custom permission to only allow owners of an object to view or edit it.
+ Model instances are expected to include an `owner` attribute.
+ """
+
+ def has_object_permission(self, request, view, obj):
+ return obj.owner == request.user
+</code></pre>
+<p>If you're overriding the <code>BasePermission</code> class, the old-style signature will continue to function, and will correctly handle both global and object-level permissions checks, but its use will raise a <code>PendingDeprecationWarning</code>.</p>
+<p>Note also that the usage of the internal APIs for permission checking on the <code>View</code> class has been cleaned up slightly, and is now documented and subject to the deprecation policy in all future versions.</p>
+<h3 id="more-explicit-hyperlink-relations-behavior">More explicit hyperlink relations behavior</h3>
+<p>When using a serializer with a <code>HyperlinkedRelatedField</code> or <code>HyperlinkedIdentityField</code>, the hyperlinks would previously use absolute URLs if the serializer context included a <code>'request'</code> key, and fall back to using relative URLs otherwise. This could lead to non-obvious behavior, as it might not be clear why some serializers generated absolute URLs, and others do not.</p>
+<p>From version 2.2 onwards, serializers with hyperlinked relationships <em>always</em> require a <code>'request'</code> key to be supplied in the context dictionary. The implicit behavior will continue to function, but its use will raise a <code>PendingDeprecationWarning</code>.</p>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/2.3-announcement.html b/topics/2.3-announcement.html
new file mode 100644
index 00000000..82c2f8d0
--- /dev/null
+++ b/topics/2.3-announcement.html
@@ -0,0 +1,443 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - REST framework 2.3 announcement</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, REST framework 2.3 announcement, API Changes, Other notes">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="2.3-announcement-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/release-notes.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/2.2-announcement.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#rest-framework-23-announcement">REST framework 2.3 announcement</a></li>
+<li><a href="#viewsets-and-routers">ViewSets and Routers</a></li>
+<li><a href="#simpler-views">Simpler views</a></li>
+<li><a href="#easier-serializers">Easier Serializers</a></li>
+<li><a href="#more-flexible-filtering">More flexible filtering</a></li>
+<li class="main"><a href="#api-changes">API Changes</a></li>
+<li><a href="#simplified-generic-view-classes">Simplified generic view classes</a></li>
+<li><a href="#simpler-url-lookups">Simpler URL lookups</a></li>
+<li><a href="#fileuploadparser">FileUploadParser</a></li>
+<li><a href="#decimalfield">DecimalField</a></li>
+<li><a href="#modelserializers-and-reverse-relationships">ModelSerializers and reverse relationships</a></li>
+<li><a href="#view-names-and-descriptions">View names and descriptions</a></li>
+<li class="main"><a href="#other-notes">Other notes</a></li>
+<li><a href="#more-explicit-style">More explicit style</a></li>
+<li><a href="#django-13-support">Django 1.3 support</a></li>
+<li><a href="#version-22-api-changes">Version 2.2 API changes</a></li>
+<li><a href="#what-comes-next">What comes next?</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="rest-framework-23-announcement">REST framework 2.3 announcement</h1>
+<p>REST framework 2.3 makes it even quicker and easier to build your Web APIs.</p>
+<h2 id="viewsets-and-routers">ViewSets and Routers</h2>
+<p>The 2.3 release introduces the <a href="../api-guide/viewsets.html">ViewSet</a> and <a href="../api-guide/routers.html">Router</a> classes.</p>
+<p>A viewset is simply a type of class based view that allows you to group multiple views into a single common class.</p>
+<p>Routers allow you to automatically determine the URLconf for your viewset classes.</p>
+<p>As an example of just how simple REST framework APIs can now be, here's an API written in a single <code>urls.py</code> module:</p>
+<pre class="prettyprint lang-py"><code>"""
+A REST framework API for viewing and editing users and groups.
+"""
+from django.conf.urls.defaults import url, patterns, include
+from django.contrib.auth.models import User, Group
+from rest_framework import viewsets, routers
+
+
+# ViewSets define the view behavior.
+class UserViewSet(viewsets.ModelViewSet):
+ model = User
+
+class GroupViewSet(viewsets.ModelViewSet):
+ model = Group
+
+
+# Routers provide an easy way of automatically determining the URL conf
+router = routers.DefaultRouter()
+router.register(r'users', UserViewSet)
+router.register(r'groups', GroupViewSet)
+
+
+# Wire up our API using automatic URL routing.
+# Additionally, we include login URLs for the browseable API.
+urlpatterns = patterns('',
+ url(r'^', include(router.urls)),
+ url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
+)
+</code></pre>
+<p>The best place to get started with ViewSets and Routers is to take a look at the <a href="../tutorial/6-viewsets-and-routers.html">newest section in the tutorial</a>, which demonstrates their usage.</p>
+<h2 id="simpler-views">Simpler views</h2>
+<p>This release rationalises the API and implementation of the generic views, dropping the dependency on Django's <code>SingleObjectMixin</code> and <code>MultipleObjectMixin</code> classes, removing a number of unneeded attributes, and generally making the implementation more obvious and easy to work with.</p>
+<p>This improvement is reflected in improved documentation for the <code>GenericAPIView</code> base class, and should make it easier to determine how to override methods on the base class if you need to write customized subclasses.</p>
+<h2 id="easier-serializers">Easier Serializers</h2>
+<p>REST framework lets you be totally explicit regarding how you want to represent relationships, allowing you to choose between styles such as hyperlinking or primary key relationships.</p>
+<p>The ability to specify exactly how you want to represent relationships is powerful, but it also introduces complexity. In order to keep things more simple, REST framework now allows you to include reverse relationships simply by including the field name in the <code>fields</code> metadata of the serializer class.</p>
+<p>For example, in REST framework 2.2, reverse relationships needed to be included explicitly on a serializer class.</p>
+<pre class="prettyprint lang-py"><code>class BlogSerializer(serializers.ModelSerializer):
+ comments = serializers.PrimaryKeyRelatedField(many=True)
+
+ class Meta:
+ model = Blog
+ fields = ('id', 'title', 'created', 'comments')
+</code></pre>
+<p>As of 2.3, you can simply include the field name, and the appropriate serializer field will automatically be used for the relationship.</p>
+<pre class="prettyprint lang-py"><code>class BlogSerializer(serializers.ModelSerializer):
+ """
+ Don't need to specify the 'comments' field explicitly anymore.
+ """
+ class Meta:
+ model = Blog
+ fields = ('id', 'title', 'created', 'comments')
+</code></pre>
+<p>Similarly, you can now easily include the primary key in hyperlinked relationships, simply by adding the field name to the metadata.</p>
+<pre class="prettyprint lang-py"><code>class BlogSerializer(serializers.HyperlinkedModelSerializer):
+ """
+ This is a hyperlinked serializer, which default to using
+ a field named 'url' as the primary identifier.
+ Note that we can now easily also add in the 'id' field.
+ """
+ class Meta:
+ model = Blog
+ fields = ('url', 'id', 'title', 'created', 'comments')
+</code></pre>
+<h2 id="more-flexible-filtering">More flexible filtering</h2>
+<p>The <code>FILTER_BACKEND</code> setting has moved to pending deprecation, in favor of a <code>DEFAULT_FILTER_BACKENDS</code> setting that takes a <em>list</em> of filter backend classes, instead of a single filter backend class.</p>
+<p>The generic view <code>filter_backend</code> attribute has also been moved to pending deprecation in favor of a <code>filter_backends</code> setting.</p>
+<p>Being able to specify multiple filters will allow for more flexible, powerful behavior. New filter classes to handle searching and ordering of results are planned to be released shortly.</p>
+<hr />
+<h1 id="api-changes">API Changes</h1>
+<h2 id="simplified-generic-view-classes">Simplified generic view classes</h2>
+<p>The functionality provided by <code>SingleObjectAPIView</code> and <code>MultipleObjectAPIView</code> base classes has now been moved into the base class <code>GenericAPIView</code>. The implementation of this base class is simple enough that providing subclasses for the base classes of detail and list views is somewhat unnecessary.</p>
+<p>Additionally the base generic view no longer inherits from Django's <code>SingleObjectMixin</code> or <code>MultipleObjectMixin</code> classes, simplifying the implementation, and meaning you don't need to cross-reference across to Django's codebase.</p>
+<p>Using the <code>SingleObjectAPIView</code> and <code>MultipleObjectAPIView</code> base classes continues to be supported, but will raise a <code>PendingDeprecationWarning</code>. You should instead simply use <code>GenericAPIView</code> as the base for any generic view subclasses.</p>
+<h3 id="removed-attributes">Removed attributes</h3>
+<p>The following attributes and methods, were previously present as part of Django's generic view implementations, but were unneeded and unused and have now been entirely removed.</p>
+<ul>
+<li>context_object_name</li>
+<li>get_context_data()</li>
+<li>get_context_object_name()</li>
+</ul>
+<p>The following attributes and methods, which were previously present as part of Django's generic view implementations have also been entirely removed.</p>
+<ul>
+<li>paginator_class</li>
+<li>get_paginator()</li>
+<li>get_allow_empty()</li>
+<li>get_slug_field()</li>
+</ul>
+<p>There may be cases when removing these bits of API might mean you need to write a little more code if your view has highly customized behavior, but generally we believe that providing a coarser-grained API will make the views easier to work with, and is the right trade-off to make for the vast majority of cases.</p>
+<p>Note that the listed attributes and methods have never been a documented part of the REST framework API, and as such are not covered by the deprecation policy.</p>
+<h3 id="simplified-methods">Simplified methods</h3>
+<p>The <code>get_object</code> and <code>get_paginate_by</code> methods no longer take an optional queryset argument. This makes overridden these methods more obvious, and a little more simple.</p>
+<p>Using an optional queryset with these methods continues to be supported, but will raise a <code>PendingDeprecationWarning</code>.</p>
+<p>The <code>paginate_queryset</code> method no longer takes a <code>page_size</code> argument, or returns a four-tuple of pagination information. Instead it simply takes a queryset argument, and either returns a <code>page</code> object with an appropriate page size, or returns <code>None</code>, if pagination is not configured for the view.</p>
+<p>Using the <code>page_size</code> argument is still supported and will trigger the old-style return type, but will raise a <code>PendingDeprecationWarning</code>.</p>
+<h3 id="deprecated-attributes">Deprecated attributes</h3>
+<p>The following attributes are used to control queryset lookup, and have all been moved into a pending deprecation state.</p>
+<ul>
+<li>pk_url_kwarg = 'pk'</li>
+<li>slug_url_kwarg = 'slug'</li>
+<li>slug_field = 'slug'</li>
+</ul>
+<p>Their usage is replaced with a single attribute:</p>
+<ul>
+<li>lookup_field = 'pk'</li>
+</ul>
+<p>This attribute is used both as the regex keyword argument in the URL conf, and as the model field to filter against when looking up a model instance. To use non-pk based lookup, simply set the <code>lookup_field</code> argument to an alternative field, and ensure that the keyword argument in the url conf matches the field name.</p>
+<p>For example, a view with 'username' based lookup might look like this:</p>
+<pre class="prettyprint lang-py"><code>class UserDetail(generics.RetrieveAPIView):
+ lookup_field = 'username'
+ queryset = User.objects.all()
+ serializer_class = UserSerializer
+</code></pre>
+<p>And would have the following entry in the urlconf:</p>
+<pre class="prettyprint lang-py"><code> url(r'^users/(?P&lt;username&gt;\w+)/$', UserDetail.as_view()),
+</code></pre>
+<p>Usage of the old-style attributes continues to be supported, but will raise a <code>PendingDeprecationWarning</code>.</p>
+<p>The <code>allow_empty</code> attribute is also deprecated. To use <code>allow_empty=False</code> style behavior you should explicitly override <code>get_queryset</code> and raise an <code>Http404</code> on empty querysets.</p>
+<p>For example:</p>
+<pre class="prettyprint lang-py"><code>class DisallowEmptyQuerysetMixin(object):
+ def get_queryset(self):
+ queryset = super(DisallowEmptyQuerysetMixin, self).get_queryset()
+ if not queryset.exists():
+ raise Http404
+ return queryset
+</code></pre>
+<p>In our opinion removing lesser-used attributes like <code>allow_empty</code> helps us move towards simpler generic view implementations, making them more obvious to use and override, and re-enforcing the preferred style of developers writing their own base classes and mixins for custom behavior rather than relying on the configurability of the generic views.</p>
+<h2 id="simpler-url-lookups">Simpler URL lookups</h2>
+<p>The <code>HyperlinkedRelatedField</code> class now takes a single optional <code>lookup_field</code> argument, that replaces the <code>pk_url_kwarg</code>, <code>slug_url_kwarg</code>, and <code>slug_field</code> arguments.</p>
+<p>For example, you might have a field that references it's relationship by a hyperlink based on a slug field:</p>
+<pre class="prettyprint lang-py"><code> account = HyperlinkedRelatedField(read_only=True,
+ lookup_field='slug',
+ view_name='account-detail')
+</code></pre>
+<p>Usage of the old-style attributes continues to be supported, but will raise a <code>PendingDeprecationWarning</code>.</p>
+<h2 id="fileuploadparser">FileUploadParser</h2>
+<p>2.3 adds a <code>FileUploadParser</code> parser class, that supports raw file uploads, in addition to the existing multipart upload support.</p>
+<h2 id="decimalfield">DecimalField</h2>
+<p>2.3 introduces a <code>DecimalField</code> serializer field, which returns <code>Decimal</code> instances.</p>
+<p>For most cases APIs using model fields will behave as previously, however if you are using a custom renderer, not provided by REST framework, then you may now need to add support for rendering <code>Decimal</code> instances to your renderer implementation.</p>
+<h2 id="modelserializers-and-reverse-relationships">ModelSerializers and reverse relationships</h2>
+<p>The support for adding reverse relationships to the <code>fields</code> option on a <code>ModelSerializer</code> class means that the <code>get_related_field</code> and <code>get_nested_field</code> method signatures have now changed.</p>
+<p>In the unlikely event that you're providing a custom serializer class, and implementing these methods you should note the new call signature for both methods is now <code>(self, model_field, related_model, to_many)</code>. For reverse relationships <code>model_field</code> will be <code>None</code>.</p>
+<p>The old-style signature will continue to function but will raise a <code>PendingDeprecationWarning</code>. </p>
+<h2 id="view-names-and-descriptions">View names and descriptions</h2>
+<p>The mechanics of how the names and descriptions used in the browseable API are generated has been modified and cleaned up somewhat.</p>
+<p>If you've been customizing this behavior, for example perhaps to use <code>rst</code> markup for the browseable API, then you'll need to take a look at the implementation to see what updates you need to make.</p>
+<p>Note that the relevant methods have always been private APIs, and the docstrings called them out as intended to be deprecated. </p>
+<hr />
+<h1 id="other-notes">Other notes</h1>
+<h2 id="more-explicit-style">More explicit style</h2>
+<p>The usage of <code>model</code> attribute in generic Views is still supported, but it's usage is generally being discouraged throughout the documentation, in favour of the setting the more explicit <code>queryset</code> and <code>serializer_class</code> attributes.</p>
+<p>For example, the following is now the recommended style for using generic views:</p>
+<pre class="prettyprint lang-py"><code>class AccountListView(generics.RetrieveAPIView):
+ queryset = MyModel.objects.all()
+ serializer_class = MyModelSerializer
+</code></pre>
+<p>Using an explicit <code>queryset</code> and <code>serializer_class</code> attributes makes the functioning of the view more clear than using the shortcut <code>model</code> attribute.</p>
+<p>It also makes the usage of the <code>get_queryset()</code> or <code>get_serializer_class()</code> methods more obvious.</p>
+<pre class="prettyprint lang-py"><code>class AccountListView(generics.RetrieveAPIView):
+ serializer_class = MyModelSerializer
+
+ def get_queryset(self):
+ """
+ Determine the queryset dynamically, depending on the
+ user making the request.
+
+ Note that overriding this method follows on more obviously now
+ that an explicit `queryset` attribute is the usual view style.
+ """
+ return self.user.accounts
+</code></pre>
+<h2 id="django-13-support">Django 1.3 support</h2>
+<p>The 2.3.x release series will be the last series to provide compatibility with Django 1.3.</p>
+<h2 id="version-22-api-changes">Version 2.2 API changes</h2>
+<p>All API changes in 2.2 that previously raised <code>PendingDeprecationWarning</code> will now raise a <code>DeprecationWarning</code>, which is loud by default.</p>
+<h2 id="what-comes-next">What comes next?</h2>
+<ul>
+<li>Support for read-write nested serializers is almost complete, and due to be released in the next few weeks.</li>
+<li>Extra filter backends for searching and ordering of results are planned to be added shortly.</li>
+</ul>
+<p>The next few months should see a renewed focus on addressing outstanding tickets. The 2.4 release is currently planned for around August-September.</p>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/ajax-csrf-cors.html b/topics/ajax-csrf-cors.html
new file mode 100644
index 00000000..47a73333
--- /dev/null
+++ b/topics/ajax-csrf-cors.html
@@ -0,0 +1,263 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - Working with AJAX, CSRF & CORS</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Working with AJAX, CSRF & CORS">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="ajax-csrf-cors-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/browser-enhancements.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/documenting-your-api.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#working-with-ajax,-csrf-&-cors">Working with AJAX, CSRF & CORS</a></li>
+<li><a href="#javascript-clients">Javascript clients</a></li>
+<li><a href="#csrf-protection">CSRF protection</a></li>
+<li><a href="#cors">CORS</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="working-with-ajax-csrf-cors">Working with AJAX, CSRF &amp; CORS</h1>
+<blockquote>
+<p>"Take a close look at possible CSRF / XSRF vulnerabilities on your own websites. They're the worst kind of vulnerability &mdash; very easy to exploit by attackers, yet not so intuitively easy to understand for software developers, at least until you've been bitten by one."</p>
+<p>&mdash; <a href="http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html">Jeff Atwood</a></p>
+</blockquote>
+<h2 id="javascript-clients">Javascript clients</h2>
+<p>If you’re building a JavaScript client to interface with your Web API, you'll need to consider if the client can use the same authentication policy that is used by the rest of the website, and also determine if you need to use CSRF tokens or CORS headers.</p>
+<p>AJAX requests that are made within the same context as the API they are interacting with will typically use <code>SessionAuthentication</code>. This ensures that once a user has logged in, any AJAX requests made can be authenticated using the same session-based authentication that is used for the rest of the website.</p>
+<p>AJAX requests that are made on a different site from the API they are communicating with will typically need to use a non-session-based authentication scheme, such as <code>TokenAuthentication</code>. </p>
+<h2 id="csrf-protection">CSRF protection</h2>
+<p><a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)">Cross Site Request Forgery</a> protection is a mechanism of guarding against a particular type of attack, which can occur when a user has not logged out of a web site, and continues to have a valid session. In this circumstance a malicious site may be able to perform actions against the target site, within the context of the logged-in session.</p>
+<p>To guard against these type of attacks, you need to do two things:</p>
+<ol>
+<li>Ensure that the 'safe' HTTP operations, such as <code>GET</code>, <code>HEAD</code> and <code>OPTIONS</code> cannot be used to alter any server-side state.</li>
+<li>Ensure that any 'unsafe' HTTP operations, such as <code>POST</code>, <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code>, always require a valid CSRF token. </li>
+</ol>
+<p>If you're using <code>SessionAuthentication</code> you'll need to include valid CSRF tokens for any <code>POST</code>, <code>PUT</code>, <code>PATCH</code> or <code>DELETE</code> operations.</p>
+<p>In order to make AJAX requests, you need to include CSRF token in the HTTP header, as <a href="https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax">described in the Django documentation</a>.</p>
+<h2 id="cors">CORS</h2>
+<p><a href="http://www.w3.org/TR/cors/">Cross-Origin Resource Sharing</a> is a mechanism for allowing clients to interact with APIs that are hosted on a different domain. CORS works by requiring the server to include a specific set of headers that allow a browser to determine if and when cross-domain requests should be allowed.</p>
+<p>The best way to deal with CORS in REST framework is to add the required response headers in middleware. This ensures that CORS is supported transparently, without having to change any behavior in your views.</p>
+<p><a href="https://github.com/ottoyiu/">Otto Yiu</a> maintains the <a href="https://github.com/ottoyiu/django-cors-headers/">django-cors-headers</a> package, which is known to work correctly with REST framework APIs.</p>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/browsable-api.html b/topics/browsable-api.html
new file mode 100644
index 00000000..88165d49
--- /dev/null
+++ b/topics/browsable-api.html
@@ -0,0 +1,357 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - The Browsable API</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, The Browsable API">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="browsable-api-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/rest-hypermedia-hateoas.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/browser-enhancements.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#the-browsable-api">The Browsable API</a></li>
+<li><a href="#urls">URLs</a></li>
+<li><a href="#formats">Formats</a></li>
+<li><a href="#customizing">Customizing</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="the-browsable-api">The Browsable API</h1>
+<blockquote>
+<p>It is a profoundly erroneous truism... that we should cultivate the habit of thinking of what we are doing. The precise opposite is the case. Civilization advances by extending the number of important operations which we can perform without thinking about them.</p>
+<p>&mdash; <a href="http://en.wikiquote.org/wiki/Alfred_North_Whitehead">Alfred North Whitehead</a>, An Introduction to Mathematics (1911)</p>
+</blockquote>
+<p>API may stand for Application <em>Programming</em> Interface, but humans have to be able to read the APIs, too; someone has to do the programming. Django REST Framework supports generating human-friendly HTML output for each resource when the <code>HTML</code> format is requested. These pages allow for easy browsing of resources, as well as forms for submitting data to the resources using <code>POST</code>, <code>PUT</code>, and <code>DELETE</code>.</p>
+<h2 id="urls">URLs</h2>
+<p>If you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The <code>rest_framework</code> package includes a <a href="../api-guide/reverse.html"><code>reverse</code></a> helper for this purpose.</p>
+<h2 id="formats">Formats</h2>
+<p>By default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using <code>?format=</code> in the request, so you can look at the raw JSON response in a browser by adding <code>?format=json</code> to the URL. There are helpful extensions for viewing JSON in <a href="https://addons.mozilla.org/en-US/firefox/addon/jsonview/">Firefox</a> and <a href="https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc">Chrome</a>.</p>
+<h2 id="customizing">Customizing</h2>
+<p>The browsable API is built with <a href="http://getbootstrap.com">Twitter's Bootstrap</a> (v 2.1.1), making it easy to customize the look-and-feel.</p>
+<p>To customize the default style, create a template called <code>rest_framework/api.html</code> that extends from <code>rest_framework/base.html</code>. For example:</p>
+<p><strong>templates/rest_framework/api.html</strong></p>
+<pre class="prettyprint lang-py"><code>{% extends "rest_framework/base.html" %}
+
+... # Override blocks with required customizations
+</code></pre>
+<h3 id="overriding-the-default-theme">Overriding the default theme</h3>
+<p>To replace the default theme, add a <code>bootstrap_theme</code> block to your <code>api.html</code> and insert a <code>link</code> to the desired Bootstrap theme css file. This will completely replace the included theme.</p>
+<pre class="prettyprint lang-py"><code>{% block bootstrap_theme %}
+ &lt;link rel="stylesheet" href="/path/to/my/bootstrap.css" type="text/css"&gt;
+{% endblock %}
+</code></pre>
+<p>A suitable replacement theme can be generated using Bootstrap's <a href="http://twitter.github.com/bootstrap/customize.html#variables">Customize Tool</a>. There are also pre-made themes available at <a href="http://bootswatch.com/">Bootswatch</a>. To use any of the Bootswatch themes, simply download the theme's <code>bootstrap.min.css</code> file, add it to your project, and replace the default one as described above.</p>
+<p>You can also change the navbar variant, which by default is <code>navbar-inverse</code>, using the <code>bootstrap_navbar_variant</code> block. The empty <code>{% block bootstrap_navbar_variant %}{% endblock %}</code> will use the original Bootstrap navbar style.</p>
+<p>Full example:</p>
+<pre class="prettyprint lang-py"><code>{% extends "rest_framework/base.html" %}
+
+{% block bootstrap_theme %}
+ &lt;link rel="stylesheet" href="http://bootswatch.com/flatly/bootstrap.min.css" type="text/css"&gt;
+{% endblock %}
+
+{% block bootstrap_navbar_variant %}{% endblock %}
+</code></pre>
+<p>For more specific CSS tweaks than simply overriding the default bootstrap theme you can override the <code>style</code> block.</p>
+<hr />
+<p><img alt="Cerulean theme" src="../img/cerulean.png" /></p>
+<p><em>Screenshot of the bootswatch 'Cerulean' theme</em></p>
+<hr />
+<p><img alt="Slate theme" src="../img/slate.png" /></p>
+<p><em>Screenshot of the bootswatch 'Slate' theme</em></p>
+<hr />
+<h3 id="blocks">Blocks</h3>
+<p>All of the blocks available in the browsable API base template that can be used in your <code>api.html</code>.</p>
+<ul>
+<li><code>bodyclass</code> - Class attribute for the <code>&lt;body&gt;</code> tag, empty by default.</li>
+<li><code>bootstrap_theme</code> - CSS for the Bootstrap theme.</li>
+<li><code>bootstrap_navbar_variant</code> - CSS class for the navbar.</li>
+<li><code>branding</code> - Branding section of the navbar, see <a href="http://twitter.github.com/bootstrap/components.html#navbar">Bootstrap components</a>.</li>
+<li><code>breadcrumbs</code> - Links showing resource nesting, allowing the user to go back up the resources. It's recommended to preserve these, but they can be overridden using the breadcrumbs block.</li>
+<li><code>footer</code> - Any copyright notices or similar footer materials can go here (by default right-aligned).</li>
+<li><code>script</code> - JavaScript files for the page.</li>
+<li><code>style</code> - CSS stylesheets for the page.</li>
+<li><code>title</code> - Title of the page.</li>
+<li><code>userlinks</code> - This is a list of links on the right of the header, by default containing login/logout links. To add links instead of replace, use <code>{{ block.super }}</code> to preserve the authentication links.</li>
+</ul>
+<h4 id="components">Components</h4>
+<p>All of the standard <a href="http://twitter.github.com/bootstrap/components.html">Bootstrap components</a> are available.</p>
+<h4 id="tooltips">Tooltips</h4>
+<p>The browsable API makes use of the Bootstrap tooltips component. Any element with the <code>js-tooltip</code> class and a <code>title</code> attribute has that title content will display a tooltip on hover events.</p>
+<h3 id="login-template">Login Template</h3>
+<p>To add branding and customize the look-and-feel of the login template, create a template called <code>login.html</code> and add it to your project, eg: <code>templates/rest_framework/login.html</code>. The template should extend from <code>rest_framework/login_base.html</code>.</p>
+<p>You can add your site name or branding by including the branding block:</p>
+<pre class="prettyprint lang-py"><code>{% block branding %}
+ &lt;h3 style="margin: 0 0 20px;"&gt;My Site Name&lt;/h3&gt;
+{% endblock %}
+</code></pre>
+<p>You can also customize the style by adding the <code>bootstrap_theme</code> or <code>style</code> block similar to <code>api.html</code>.</p>
+<h3 id="advanced-customization">Advanced Customization</h3>
+<h4 id="context">Context</h4>
+<p>The context that's available to the template:</p>
+<ul>
+<li><code>allowed_methods</code> : A list of methods allowed by the resource</li>
+<li><code>api_settings</code> : The API settings</li>
+<li><code>available_formats</code> : A list of formats allowed by the resource</li>
+<li><code>breadcrumblist</code> : The list of links following the chain of nested resources</li>
+<li><code>content</code> : The content of the API response</li>
+<li><code>description</code> : The description of the resource, generated from its docstring</li>
+<li><code>name</code> : The name of the resource</li>
+<li><code>post_form</code> : A form instance for use by the POST form (if allowed)</li>
+<li><code>put_form</code> : A form instance for use by the PUT form (if allowed)</li>
+<li><code>display_edit_forms</code> : A boolean indicating whether or not POST, PUT and PATCH forms will be displayed</li>
+<li><code>request</code> : The request object</li>
+<li><code>response</code> : The response object</li>
+<li><code>version</code> : The version of Django REST Framework</li>
+<li><code>view</code> : The view handling the request</li>
+<li><code>FORMAT_PARAM</code> : The view can accept a format override</li>
+<li><code>METHOD_PARAM</code> : The view can accept a method override</li>
+</ul>
+<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>
+<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>
+<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>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>
+<pre class="prettyprint lang-py"><code>{% block script %}
+{{ block.super }}
+{% include 'autocomplete_light/static.html' %}
+{% endblock %}
+</code></pre>
+<p>You can now add the <code>autocomplete_light.ChoiceWidget</code> widget to the serializer field.</p>
+<pre class="prettyprint lang-py"><code>import autocomplete_light
+
+class BookSerializer(serializers.ModelSerializer):
+ 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 />
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/browser-enhancements.html b/topics/browser-enhancements.html
new file mode 100644
index 00000000..7f71b932
--- /dev/null
+++ b/topics/browser-enhancements.html
@@ -0,0 +1,297 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - Browser enhancements</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Browser enhancements">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="browser-enhancements-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/browsable-api.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/ajax-csrf-cors.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#browser-enhancements">Browser enhancements</a></li>
+<li><a href="#browser-based-put,-delete,-etc">Browser based PUT, DELETE, etc...</a></li>
+<li><a href="#http-header-based-method-overriding">HTTP header based method overriding</a></li>
+<li><a href="#browser-based-submission-of-non-form-content">Browser based submission of non-form content</a></li>
+<li><a href="#url-based-accept-headers">URL based accept headers</a></li>
+<li><a href="#url-based-format-suffixes">URL based format suffixes</a></li>
+<li><a href="#doesnt-html5-support-put-and-delete-forms">Doesn't HTML5 support PUT and DELETE forms?</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="browser-enhancements">Browser enhancements</h1>
+<blockquote>
+<p>"There are two noncontroversial uses for overloaded POST. The first is to <em>simulate</em> HTTP's uniform interface for clients like web browsers that don't support PUT or DELETE"</p>
+<p>&mdash; <a href="http://www.amazon.com/Restful-Web-Services-Leonard-Richardson/dp/0596529260">RESTful Web Services</a>, Leonard Richardson &amp; Sam Ruby.</p>
+</blockquote>
+<h2 id="browser-based-put-delete-etc">Browser based PUT, DELETE, etc...</h2>
+<p>REST framework supports browser-based <code>PUT</code>, <code>DELETE</code> and other methods, by
+overloading <code>POST</code> requests using a hidden form field.</p>
+<p>Note that this is the same strategy as is used in <a href="http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-put-or-delete-methods-work">Ruby on Rails</a>.</p>
+<p>For example, given the following form:</p>
+<pre class="prettyprint lang-py"><code>&lt;form action="/news-items/5" method="POST"&gt;
+ &lt;input type="hidden" name="_method" value="DELETE"&gt;
+&lt;/form&gt;
+</code></pre>
+<p><code>request.method</code> would return <code>"DELETE"</code>.</p>
+<h2 id="http-header-based-method-overriding">HTTP header based method overriding</h2>
+<p>REST framework also supports method overriding via the semi-standard <code>X-HTTP-Method-Override</code> header. This can be useful if you are working with non-form content such as JSON and are working with an older web server and/or hosting provider that doesn't recognise particular HTTP methods such as <code>PATCH</code>. For example <a href="https://forums.aws.amazon.com/thread.jspa?messageID=400724">Amazon Web Services ELB</a>.</p>
+<p>To use it, make a <code>POST</code> request, setting the <code>X-HTTP-Method-Override</code> header.</p>
+<p>For example, making a <code>PATCH</code> request via <code>POST</code> in jQuery:</p>
+<pre class="prettyprint lang-py"><code>$.ajax({
+ url: '/myresource/',
+ method: 'POST',
+ headers: {'X-HTTP-Method-Override': 'PATCH'},
+ ...
+});
+</code></pre>
+<h2 id="browser-based-submission-of-non-form-content">Browser based submission of non-form content</h2>
+<p>Browser-based submission of content types other than form are supported by
+using form fields named <code>_content</code> and <code>_content_type</code>:</p>
+<p>For example, given the following form:</p>
+<pre class="prettyprint lang-py"><code>&lt;form action="/news-items/5" method="PUT"&gt;
+ &lt;input type="hidden" name="_content_type" value="application/json"&gt;
+ &lt;input name="_content" value="{'count': 1}"&gt;
+&lt;/form&gt;
+</code></pre>
+<p><code>request.content_type</code> would return <code>"application/json"</code>, and
+<code>request.stream</code> would return <code>"{'count': 1}"</code></p>
+<h2 id="url-based-accept-headers">URL based accept headers</h2>
+<p>REST framework can take <code>?accept=application/json</code> style URL parameters,
+which allow the <code>Accept</code> header to be overridden.</p>
+<p>This can be useful for testing the API from a web browser, where you don't
+have any control over what is sent in the <code>Accept</code> header.</p>
+<h2 id="url-based-format-suffixes">URL based format suffixes</h2>
+<p>REST framework can take <code>?format=json</code> style URL parameters, which can be a
+useful shortcut for determining which content type should be returned from
+the view.</p>
+<p>This is a more concise than using the <code>accept</code> override, but it also gives
+you less control. (For example you can't specify any media type parameters)</p>
+<h2 id="doesnt-html5-support-put-and-delete-forms">Doesn't HTML5 support PUT and DELETE forms?</h2>
+<p>Nope. It was at one point intended to support <code>PUT</code> and <code>DELETE</code> forms, but
+was later <a href="http://www.w3.org/TR/html5-diff/#changes-2010-06-24">dropped from the spec</a>. There remains
+<a href="http://amundsen.com/examples/put-delete-forms/">ongoing discussion</a> about adding support for <code>PUT</code> and <code>DELETE</code>,
+as well as how to support content types other than form-encoded data.</p>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/contributing.html b/topics/contributing.html
new file mode 100644
index 00000000..4c96c60c
--- /dev/null
+++ b/topics/contributing.html
@@ -0,0 +1,351 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - Contributing to REST framework</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Contributing to REST framework, Community, Issues, Development, Testing, Documentation, Third party packages, Core committers">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="contributing-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/rest-framework-2-announcement.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/rest-hypermedia-hateoas.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#contributing-to-rest-framework">Contributing to REST framework</a></li>
+<li class="main"><a href="#community">Community</a></li>
+<li class="main"><a href="#issues">Issues</a></li>
+<li class="main"><a href="#development">Development</a></li>
+<li class="main"><a href="#testing">Testing</a></li>
+<li class="main"><a href="#documentation">Documentation</a></li>
+<li><a href="#building-the-documentation">Building the documentation</a></li>
+<li><a href="#language-style">Language style</a></li>
+<li><a href="#markdown-style">Markdown style</a></li>
+<li class="main"><a href="#third-party-packages">Third party packages</a></li>
+<li class="main"><a href="#core-committers">Core committers</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="contributing-to-rest-framework">Contributing to REST framework</h1>
+<blockquote>
+<p>The world can only really be changed one piece at a time. The art is picking that piece.</p>
+<p>&mdash; <a href="http://www.w3.org/People/Berners-Lee/FAQ.html">Tim Berners-Lee</a></p>
+</blockquote>
+<p>There are many ways you can contribute to Django REST framework. We'd like it to be a community-led project, so please get involved and help shape the future of the project.</p>
+<h1 id="community">Community</h1>
+<p>If you use and enjoy REST framework please consider <a href="https://github.com/tomchristie/django-rest-framework">staring the project on GitHub</a>, and <a href="https://www.djangopackages.com/grids/g/api/">upvoting it on Django packages</a>. Doing so helps potential new users see that the project is well used, and help us continue to attract new users.</p>
+<p>You might also consider writing a blog post on your experience with using REST framework, writing a tutorial about using the project with a particular javascript framework, or simply sharing the love on Twitter.</p>
+<p>Other really great ways you can help move the community forward include helping answer questions on the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">discussion group</a>, or setting up an <a href="http://stackexchange.com/filters/66475/rest-framework">email alert on StackOverflow</a> so that you get notified of any new questions with the <code>django-rest-framework</code> tag.</p>
+<p>When answering questions make sure to help future contributors find their way around by hyperlinking wherever possible to related threads and tickets, and include backlinks from those items if relevant. </p>
+<h1 id="issues">Issues</h1>
+<p>It's really helpful if you make sure you address issues to the correct channel. Usage questions should be directed to the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">discussion group</a>. Feature requests, bug reports and other issues should be raised on the GitHub <a href="https://github.com/tomchristie/django-rest-framework/issues?state=open">issue tracker</a>.</p>
+<p>Some tips on good issue reporting:</p>
+<ul>
+<li>When describing issues try to phrase your ticket in terms of the <em>behavior</em> you think needs changing rather than the <em>code</em> you think need changing.</li>
+<li>Search the issue list first for related items, and make sure you're running the latest version of REST framework before reporting an issue.</li>
+<li>
+<p>If reporting a bug, then try to include a pull request with a failing test case. This will help us quickly identify if there is a valid issue, and make sure that it gets fixed more quickly if there is one.</p>
+</li>
+<li>
+<p>TODO: Triage</p>
+</li>
+</ul>
+<h1 id="development">Development</h1>
+<ul>
+<li>git clone &amp; PYTHONPATH</li>
+<li>Pep8</li>
+<li>Recommend editor that runs pep8</li>
+</ul>
+<h3 id="pull-requests">Pull requests</h3>
+<ul>
+<li>Make pull requests early</li>
+<li>Describe branching</li>
+</ul>
+<h3 id="managing-compatibility-issues">Managing compatibility issues</h3>
+<ul>
+<li>Describe compat module</li>
+</ul>
+<h1 id="testing">Testing</h1>
+<ul>
+<li>Running the tests</li>
+<li>tox</li>
+</ul>
+<h1 id="documentation">Documentation</h1>
+<p>The documentation for REST framework is built from the <a href="http://daringfireball.net/projects/markdown/basics">Markdown</a> source files in <a href="https://github.com/tomchristie/django-rest-framework/tree/master/docs">the docs directory</a>.</p>
+<p>There are many great markdown editors that make working with the documentation really easy. The <a href="http://mouapp.com/">Mou editor for Mac</a> is one such editor that comes highly recommended.</p>
+<h2 id="building-the-documentation">Building the documentation</h2>
+<p>To build the documentation, simply run the <code>mkdocs.py</code> script.</p>
+<pre class="prettyprint lang-py"><code>./mkdocs.py
+</code></pre>
+<p>This will build the html output into the <code>html</code> directory.</p>
+<p>You can build the documentation and open a preview in a browser window by using the <code>-p</code> flag.</p>
+<pre class="prettyprint lang-py"><code>./mkdocs.py -p
+</code></pre>
+<h2 id="language-style">Language style</h2>
+<p>Documentation should be in American English. The tone of the documentation is very important - try to stick to a simple, plain, objective and well-balanced style where possible.</p>
+<p>Some other tips:</p>
+<ul>
+<li>Keep paragraphs reasonably short.</li>
+<li>Use double spacing after the end of sentences.</li>
+<li>Don't use the abbreviations such as 'e.g..' but instead use long form, such as 'For example'.</li>
+</ul>
+<h2 id="markdown-style">Markdown style</h2>
+<p>There are a couple of conventions you should follow when working on the documentation.</p>
+<h5 id="1-headers">1. Headers</h5>
+<p>Headers should use the hash style. For example:</p>
+<pre class="prettyprint lang-py"><code>### Some important topic
+</code></pre>
+<p>The underline style should not be used. <strong>Don't do this:</strong> </p>
+<pre class="prettyprint lang-py"><code>Some important topic
+====================
+</code></pre>
+<h5 id="2-links">2. Links</h5>
+<p>Links should always use the reference style, with the referenced hyperlinks kept at the end of the document.</p>
+<pre class="prettyprint lang-py"><code>Here is a link to [some other thing][other-thing].
+
+More text...
+
+[other-thing]: http://example.com/other/thing
+</code></pre>
+<p>This style helps keep the documentation source consistent and readable.</p>
+<p>If you are hyperlinking to another REST framework document, you should use a relative link, and link to the <code>.md</code> suffix. For example:</p>
+<pre class="prettyprint lang-py"><code>[authentication]: ../api-guide/authentication.md
+</code></pre>
+<p>Linking in this style means you'll be able to click the hyperlink in your markdown editor to open the referenced document. When the documentation is built, these links will be converted into regular links to HTML pages.</p>
+<h5 id="3-notes">3. Notes</h5>
+<p>If you want to draw attention to a note or warning, use a pair of enclosing lines, like so:</p>
+<pre class="prettyprint lang-py"><code>---
+
+**Note:** Make sure you do this thing.
+
+---
+</code></pre>
+<h1 id="third-party-packages">Third party packages</h1>
+<ul>
+<li>Django reusable app</li>
+</ul>
+<h1 id="core-committers">Core committers</h1>
+<ul>
+<li>Still use pull reqs</li>
+<li>Credits</li>
+</ul>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/credits.html b/topics/credits.html
new file mode 100644
index 00000000..03f0ba76
--- /dev/null
+++ b/topics/credits.html
@@ -0,0 +1,432 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - Credits</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Credits">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="credits-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small disabled" href="#">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/release-notes.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#credits">Credits</a></li>
+<li><a href="#additional-thanks">Additional thanks</a></li>
+<li><a href="#contact">Contact</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="credits">Credits</h1>
+<p>The following people have helped make REST framework great.</p>
+<ul>
+<li>Tom Christie - <a href="https://github.com/tomchristie">tomchristie</a></li>
+<li>Marko Tibold - <a href="https://github.com/markotibold">markotibold</a></li>
+<li>Paul Miller - <a href="https://github.com/paulmillr">paulmillr</a></li>
+<li>Sébastien Piquemal - <a href="https://github.com/sebpiq">sebpiq</a></li>
+<li>Carmen Wick - <a href="https://github.com/cwick">cwick</a></li>
+<li>Alex Ehlke - <a href="https://github.com/aehlke">aehlke</a></li>
+<li>Alen Mujezinovic - <a href="https://github.com/flashingpumpkin">flashingpumpkin</a></li>
+<li>Carles Barrobés - <a href="https://github.com/txels">txels</a></li>
+<li>Michael Fötsch - <a href="https://github.com/mfoetsch">mfoetsch</a></li>
+<li>David Larlet - <a href="https://github.com/david">david</a></li>
+<li>Andrew Straw - <a href="https://github.com/astraw">astraw</a></li>
+<li>Zeth - <a href="https://github.com/zeth">zeth</a></li>
+<li>Fernando Zunino - <a href="https://github.com/fzunino">fzunino</a></li>
+<li>Jens Alm - <a href="https://github.com/ulmus">ulmus</a></li>
+<li>Craig Blaszczyk - <a href="https://github.com/jakul">jakul</a></li>
+<li>Garcia Solero - <a href="https://github.com/garciasolero">garciasolero</a></li>
+<li>Tom Drummond - <a href="https://github.com/devioustree">devioustree</a></li>
+<li>Danilo Bargen - <a href="https://github.com/dbrgn">dbrgn</a></li>
+<li>Andrew McCloud - <a href="https://github.com/amccloud">amccloud</a></li>
+<li>Thomas Steinacher - <a href="https://github.com/thomasst">thomasst</a></li>
+<li>Meurig Freeman - <a href="https://github.com/meurig">meurig</a></li>
+<li>Anthony Nemitz - <a href="https://github.com/anemitz">anemitz</a></li>
+<li>Ewoud Kohl van Wijngaarden - <a href="https://github.com/ekohl">ekohl</a></li>
+<li>Michael Ding - <a href="https://github.com/yandy">yandy</a></li>
+<li>Mjumbe Poe - <a href="https://github.com/mjumbewu">mjumbewu</a></li>
+<li>Natim - <a href="https://github.com/natim">natim</a></li>
+<li>Sebastian Żurek - <a href="https://github.com/sebzur">sebzur</a></li>
+<li>Benoit C - <a href="https://github.com/dzen">dzen</a></li>
+<li>Chris Pickett - <a href="https://github.com/bunchesofdonald">bunchesofdonald</a></li>
+<li>Ben Timby - <a href="https://github.com/btimby">btimby</a></li>
+<li>Michele Lazzeri - <a href="https://github.com/michelelazzeri-nextage">michelelazzeri-nextage</a></li>
+<li>Camille Harang - <a href="https://github.com/mammique">mammique</a></li>
+<li>Paul Oswald - <a href="https://github.com/poswald">poswald</a></li>
+<li>Sean C. Farley - <a href="https://github.com/scfarley">scfarley</a></li>
+<li>Daniel Izquierdo - <a href="https://github.com/izquierdo">izquierdo</a></li>
+<li>Can Yavuz - <a href="https://github.com/tschan">tschan</a></li>
+<li>Shawn Lewis - <a href="https://github.com/shawnlewis">shawnlewis</a></li>
+<li>Alec Perkins - <a href="https://github.com/alecperkins">alecperkins</a></li>
+<li>Michael Barrett - <a href="https://github.com/phobologic">phobologic</a></li>
+<li>Mathieu Dhondt - <a href="https://github.com/laundromat">laundromat</a></li>
+<li>Johan Charpentier - <a href="https://github.com/cyberj">cyberj</a></li>
+<li>Jamie Matthews - <a href="https://github.com/j4mie">j4mie</a></li>
+<li>Mattbo - <a href="https://github.com/mattbo">mattbo</a></li>
+<li>Max Hurl - <a href="https://github.com/maximilianhurl">maximilianhurl</a></li>
+<li>Tomi Pajunen - <a href="https://github.com/eofs">eofs</a></li>
+<li>Rob Dobson - <a href="https://github.com/rdobson">rdobson</a></li>
+<li>Daniel Vaca Araujo - <a href="https://github.com/diviei">diviei</a></li>
+<li>Madis Väin - <a href="https://github.com/madisvain">madisvain</a></li>
+<li>Stephan Groß - <a href="https://github.com/minddust">minddust</a></li>
+<li>Pavel Savchenko - <a href="https://github.com/asfaltboy">asfaltboy</a></li>
+<li>Otto Yiu - <a href="https://github.com/OttoYiu">ottoyiu</a></li>
+<li>Jacob Magnusson - <a href="https://github.com/jmagnusson">jmagnusson</a></li>
+<li>Osiloke Harold Emoekpere - <a href="https://github.com/osiloke">osiloke</a></li>
+<li>Michael Shepanski - <a href="https://github.com/mjs7231">mjs7231</a></li>
+<li>Toni Michel - <a href="https://github.com/tonimichel">tonimichel</a></li>
+<li>Ben Konrath - <a href="https://github.com/benkonrath">benkonrath</a></li>
+<li>Marc Aymerich - <a href="https://github.com/glic3rinu">glic3rinu</a></li>
+<li>Ludwig Kraatz - <a href="https://github.com/ludwigkraatz">ludwigkraatz</a></li>
+<li>Rob Romano - <a href="https://github.com/robromano">robromano</a></li>
+<li>Eugene Mechanism - <a href="https://github.com/mechanism">mechanism</a></li>
+<li>Jonas Liljestrand - <a href="https://github.com/jonlil">jonlil</a></li>
+<li>Justin Davis - <a href="https://github.com/irrelative">irrelative</a></li>
+<li>Dustin Bachrach - <a href="https://github.com/dbachrach">dbachrach</a></li>
+<li>Mark Shirley - <a href="https://github.com/maspwr">maspwr</a></li>
+<li>Olivier Aubert - <a href="https://github.com/oaubert">oaubert</a></li>
+<li>Yuri Prezument - <a href="https://github.com/yprez">yprez</a></li>
+<li>Fabian Buechler - <a href="https://github.com/fabianbuechler">fabianbuechler</a></li>
+<li>Mark Hughes - <a href="https://github.com/mhsparks">mhsparks</a></li>
+<li>Michael van de Waeter - <a href="https://github.com/mvdwaeter">mvdwaeter</a></li>
+<li>Reinout van Rees - <a href="https://github.com/reinout">reinout</a></li>
+<li>Michael Richards - <a href="https://github.com/justanotherbody">justanotherbody</a></li>
+<li>Ben Roberts - <a href="https://github.com/roberts81">roberts81</a></li>
+<li>Venkata Subramanian Mahalingam - <a href="https://github.com/annacoder">annacoder</a></li>
+<li>George Kappel - <a href="https://github.com/gkappel">gkappel</a></li>
+<li>Colin Murtaugh - <a href="https://github.com/cmurtaugh">cmurtaugh</a></li>
+<li>Simon Pantzare - <a href="https://github.com/pilt">pilt</a></li>
+<li>Szymon Teżewski - <a href="https://github.com/sunscrapers">sunscrapers</a></li>
+<li>Joel Marcotte - <a href="https://github.com/joual">joual</a></li>
+<li>Trey Hunner - <a href="https://github.com/treyhunner">treyhunner</a></li>
+<li>Roman Akinfold - <a href="https://github.com/akinfold">akinfold</a></li>
+<li>Toran Billups - <a href="https://github.com/toranb">toranb</a></li>
+<li>Sébastien Béal - <a href="https://github.com/sebastibe">sebastibe</a></li>
+<li>Andrew Hankinson - <a href="https://github.com/ahankinson">ahankinson</a></li>
+<li>Juan Riaza - <a href="https://github.com/juanriaza">juanriaza</a></li>
+<li>Michael Mior - <a href="https://github.com/michaelmior">michaelmior</a></li>
+<li>Marc Tamlyn - <a href="https://github.com/mjtamlyn">mjtamlyn</a></li>
+<li>Richard Wackerbarth - <a href="https://github.com/wackerbarth">wackerbarth</a></li>
+<li>Johannes Spielmann - <a href="https://github.com/shezi">shezi</a></li>
+<li>James Cleveland - <a href="https://github.com/radiosilence">radiosilence</a></li>
+<li>Steve Gregory - <a href="https://github.com/steve-gregory">steve-gregory</a></li>
+<li>Federico Capoano - <a href="https://github.com/nemesisdesign">nemesisdesign</a></li>
+<li>Bruno Renié - <a href="https://github.com/brutasse">brutasse</a></li>
+<li>Kevin Stone - <a href="https://github.com/kevinastone">kevinastone</a></li>
+<li>Guglielmo Celata - <a href="https://github.com/guglielmo">guglielmo</a></li>
+<li>Mike Tums - <a href="https://github.com/mktums">mktums</a></li>
+<li>Michael Elovskikh - <a href="https://github.com/wronglink">wronglink</a></li>
+<li>Michał Jaworski - <a href="https://github.com/swistakm">swistakm</a></li>
+<li>Andrea de Marco - <a href="https://github.com/z4r">z4r</a></li>
+<li>Fernando Rocha - <a href="https://github.com/fernandogrd">fernandogrd</a></li>
+<li>Xavier Ordoquy - <a href="https://github.com/xordoquy">xordoquy</a></li>
+<li>Adam Wentz - <a href="https://github.com/floppya">floppya</a></li>
+<li>Andreas Pelme - <a href="https://github.com/pelme">pelme</a></li>
+<li>Ryan Detzel - <a href="https://github.com/ryanrdetzel">ryanrdetzel</a></li>
+<li>Omer Katz - <a href="https://github.com/thedrow">thedrow</a></li>
+<li>Wiliam Souza - <a href="https://github.com/wiliamsouza">waa</a></li>
+<li>Jonas Braun - <a href="https://github.com/iekadou">iekadou</a></li>
+<li>Ian Dash - <a href="https://github.com/bitmonkey">bitmonkey</a></li>
+<li>Bouke Haarsma - <a href="https://github.com/bouke">bouke</a></li>
+<li>Pierre Dulac - <a href="https://github.com/dulaccc">dulaccc</a></li>
+<li>Dave Kuhn - <a href="https://github.com/kuhnza">kuhnza</a></li>
+<li>Sitong Peng - <a href="https://github.com/stoneg">stoneg</a></li>
+<li>Victor Shih - <a href="https://github.com/vshih">vshih</a></li>
+<li>Atle Frenvik Sveen - <a href="https://github.com/atlefren">atlefren</a></li>
+<li>J Paul Reed - <a href="https://github.com/preed">preed</a></li>
+<li>Matt Majewski - <a href="https://github.com/forgingdestiny">forgingdestiny</a></li>
+<li>Jerome Chen - <a href="https://github.com/chenjyw">chenjyw</a></li>
+<li>Andrew Hughes - <a href="https://github.com/eyepulp">eyepulp</a></li>
+<li>Daniel Hepper - <a href="https://github.com/dhepper">dhepper</a></li>
+<li>Hamish Campbell - <a href="https://github.com/hamishcampbell">hamishcampbell</a></li>
+<li>Marlon Bailey - <a href="https://github.com/avinash240">avinash240</a></li>
+<li>James Summerfield - <a href="https://github.com/jsummerfield">jsummerfield</a></li>
+<li>Andy Freeland - <a href="https://github.com/rouge8">rouge8</a></li>
+<li>Craig de Stigter - <a href="https://github.com/craigds">craigds</a></li>
+<li>Pablo Recio - <a href="https://github.com/pyriku">pyriku</a></li>
+<li>Brian Zambrano - <a href="https://github.com/brianz">brianz</a></li>
+<li>Òscar Vilaplana - <a href="https://github.com/grimborg">grimborg</a></li>
+<li>Ryan Kaskel - <a href="https://github.com/ryankask">ryankask</a></li>
+<li>Andy McKay - <a href="https://github.com/andymckay">andymckay</a></li>
+<li>Matteo Suppo - <a href="https://github.com/matteosuppo">matteosuppo</a></li>
+<li>Karol Majta - <a href="https://github.com/lolek09">lolek09</a></li>
+<li>David Jones - <a href="https://github.com/commonorgarden">commonorgarden</a></li>
+<li>Andrew Tarzwell - <a href="https://github.com/atarzwell">atarzwell</a></li>
+<li>Michal Dvořák - <a href="https://github.com/mikee2185">mikee2185</a></li>
+<li>Markus Törnqvist - <a href="https://github.com/mjtorn">mjtorn</a></li>
+<li>Pascal Borreli - <a href="https://github.com/pborreli">pborreli</a></li>
+<li>Alex Burgel - <a href="https://github.com/aburgel">aburgel</a></li>
+<li>David Medina - <a href="https://github.com/copitux">copitux</a></li>
+<li>Areski Belaid - <a href="https://github.com/areski">areski</a></li>
+<li>Ethan Freman - <a href="https://github.com/mindlace">mindlace</a></li>
+<li>David Sanders - <a href="https://github.com/davesque">davesque</a></li>
+<li>Philip Douglas - <a href="https://github.com/freakydug">freakydug</a></li>
+<li>Igor Kalat - <a href="https://github.com/trwired">trwired</a></li>
+<li>Rudolf Olah - <a href="https://github.com/omouse">omouse</a></li>
+<li>Gertjan Oude Lohuis - <a href="https://github.com/gertjanol">gertjanol</a></li>
+<li>Matthias Jacob - <a href="https://github.com/cyroxx">cyroxx</a></li>
+<li>Pavel Zinovkin - <a href="https://github.com/pzinovkin">pzinovkin</a></li>
+<li>Will Kahn-Greene - <a href="https://github.com/willkg">willkg</a></li>
+<li>Kevin Brown - <a href="https://github.com/kevin-brown">kevin-brown</a></li>
+<li>Rodrigo Martell - <a href="https://github.com/coderigo">coderigo</a></li>
+<li>James Rutherford - <a href="https://github.com/jimr">jimr</a></li>
+<li>Ricky Rosario - <a href="https://github.com/rlr">rlr</a></li>
+<li>Veronica Lynn - <a href="https://github.com/kolvia">kolvia</a></li>
+<li>Dan Stephenson - <a href="https://github.com/etos">etos</a></li>
+<li>Martin Clement - <a href="https://github.com/martync">martync</a></li>
+<li>Jeremy Satterfield - <a href="https://github.com/jsatt">jsatt</a></li>
+<li>Christopher Paolini - <a href="https://github.com/chrispaolini">chrispaolini</a></li>
+<li>Filipe A Ximenes - <a href="https://github.com/filipeximenes">filipeximenes</a></li>
+<li>Ramiro Morales - <a href="https://github.com/ramiro">ramiro</a></li>
+<li>Krzysztof Jurewicz - <a href="https://github.com/krzysiekj">krzysiekj</a></li>
+<li>Eric Buehl - <a href="https://github.com/ericbuehl">ericbuehl</a></li>
+<li>Kristian Øllegaard - <a href="https://github.com/kristianoellegaard">kristianoellegaard</a></li>
+<li>Alexander Akhmetov - <a href="https://github.com/alexander-akhmetov">alexander-akhmetov</a></li>
+<li>Andrey Antukh - <a href="https://github.com/niwibe">niwibe</a></li>
+<li>Mathieu Pillard - <a href="https://github.com/diox">diox</a></li>
+<li>Edmond Wong - <a href="https://github.com/edmondwong">edmondwong</a></li>
+<li>Ben Reilly - <a href="https://github.com/bwreilly">bwreilly</a></li>
+<li>Tai Lee - <a href="https://github.com/mrmachine">mrmachine</a></li>
+<li>Markus Kaiserswerth - <a href="https://github.com/mkai">mkai</a></li>
+<li>Henry Clifford - <a href="https://github.com/hcliff">hcliff</a></li>
+<li>Thomas Badaud - <a href="https://github.com/badale">badale</a></li>
+<li>Colin Huang - <a href="https://github.com/tamakisquare">tamakisquare</a></li>
+<li>Ross McFarland - <a href="https://github.com/ross">ross</a></li>
+<li>Jacek Bzdak - <a href="https://github.com/jbzdak">jbzdak</a></li>
+<li>Alexander Lukanin - <a href="https://github.com/alexanderlukanin13">alexanderlukanin13</a></li>
+<li>Yamila Moreno - <a href="https://github.com/yamila-moreno">yamila-moreno</a></li>
+<li>Rob Hudson - <a href="https://github.com/robhudson">robhudson</a></li>
+<li>Alex Good - <a href="https://github.com/alexjg">alexjg</a></li>
+</ul>
+<p>Many thanks to everyone who's contributed to the project.</p>
+<h2 id="additional-thanks">Additional thanks</h2>
+<p>The documentation is built with <a href="http://twitter.github.com/bootstrap/">Bootstrap</a> and <a href="http://daringfireball.net/projects/markdown/">Markdown</a>.</p>
+<p>Project hosting is with <a href="https://github.com/tomchristie/django-rest-framework">GitHub</a>.</p>
+<p>Continuous integration testing is managed with <a href="https://secure.travis-ci.org/tomchristie/django-rest-framework">Travis CI</a>.</p>
+<p>The <a href="http://restframework.herokuapp.com/">live sandbox</a> is hosted on <a href="http://www.heroku.com/">Heroku</a>.</p>
+<p>Various inspiration taken from the <a href="http://rubyonrails.org/">Rails</a>, <a href="https://bitbucket.org/jespern/django-piston">Piston</a>, <a href="https://github.com/toastdriven/django-tastypie">Tastypie</a>, <a href="https://github.com/zacharyvoase/dagny">Dagny</a> and <a href="https://github.com/BertrandBordage/django-viewsets">django-viewsets</a> projects.</p>
+<p>Development of REST framework 2.0 was sponsored by <a href="http://lab.dabapps.com">DabApps</a>.</p>
+<h2 id="contact">Contact</h2>
+<p>For usage questions please see the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">REST framework discussion group</a>.</p>
+<p>You can also contact <a href="http://twitter.com/_tomchristie">@_tomchristie</a> directly on twitter.</p>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/documenting-your-api.html b/topics/documenting-your-api.html
new file mode 100644
index 00000000..79bba0d6
--- /dev/null
+++ b/topics/documenting-your-api.html
@@ -0,0 +1,302 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - Documenting your API</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Documenting your API">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="documenting-your-api-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/ajax-csrf-cors.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../api-guide/settings.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#documenting-your-api">Documenting your API</a></li>
+<li><a href="#endpoint-documentation">Endpoint documentation</a></li>
+<li><a href="#self-describing-apis">Self describing APIs</a></li>
+<li><a href="#the-hypermedia-approach">The hypermedia approach</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="documenting-your-api">Documenting your API</h1>
+<blockquote>
+<p>A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state.</p>
+<p>&mdash; Roy Fielding, <a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">REST APIs must be hypertext driven</a></p>
+</blockquote>
+<p>There are a variety of approaches to API documentation. This document introduces a few of the various tools and options you might choose from. The approaches should not be considered exclusive - you may want to provide more than one documentation style for you API, such as a self describing API that also includes static documentation of the various API endpoints.</p>
+<h2 id="endpoint-documentation">Endpoint documentation</h2>
+<p>The most common way to document Web APIs today is to produce documentation that lists the API endpoints verbatim, and describes the allowable operations on each. There are various tools that allow you to do this in an automated or semi-automated way.</p>
+<hr />
+<h4 id="django-rest-swagger">Django REST Swagger</h4>
+<p>Marc Gibbons' <a href="https://github.com/marcgibbons/django-rest-swagger">Django REST Swagger</a> integrates REST framework with the <a href="https://developers.helloreverb.com/swagger/">Swagger</a> API documentation tool. The package produces well presented API documentation, and includes interactive tools for testing API endpoints.</p>
+<p>The package is fully documented, well supported, and comes highly recommended.</p>
+<p>Django REST Swagger supports REST framework versions 2.3 and above.</p>
+<p><img alt="Screenshot - Django REST Swagger" src="../img/django-rest-swagger.png" /></p>
+<hr />
+<h4 id="rest-framework-docs">REST Framework Docs</h4>
+<p>The <a href="https://github.com/marcgibbons/django-rest-framework-docs">REST Framework Docs</a> package is an earlier project, also by Marc Gibbons, that offers clean, simple autogenerated documentation for your API.</p>
+<p><img alt="Screenshot - REST Framework Docs" src="../img/rest-framework-docs.png" /></p>
+<hr />
+<h4 id="apiary">Apiary</h4>
+<p>There are various other online tools and services for providing API documentation. One notable service is <a href="http://apiary.io/">Apiary</a>. With Apiary, you describe your API using a simple markdown-like syntax. The generated documentation includes API interaction, a mock server for testing &amp; prototyping, and various other tools.</p>
+<p><img alt="Screenshot - Apiary" src="../img/apiary.png" /></p>
+<hr />
+<h2 id="self-describing-apis">Self describing APIs</h2>
+<p>The browsable API that REST framework provides makes it possible for your API to be entirely self describing. The documentation for each API endpoint can be provided simply by visiting the URL in your browser.</p>
+<p><img alt="Screenshot - Self describing API" src="../img/self-describing.png" /></p>
+<hr />
+<h4 id="setting-the-title">Setting the title</h4>
+<p>The title that is used in the browsable API is generated from the view class name or function name. Any trailing <code>View</code> or <code>ViewSet</code> suffix is stripped, and the string is whitespace separated on uppercase/lowercase boundaries or underscores.</p>
+<p>For example, the view <code>UserListView</code>, will be named <code>User List</code> when presented in the browsable API.</p>
+<p>When working with viewsets, an appropriate suffix is appended to each generated view. For example, the view set <code>UserViewSet</code> will generate views named <code>User List</code> and <code>User Instance</code>. </p>
+<h4 id="setting-the-description">Setting the description</h4>
+<p>The description in the browsable API is generated from the docstring of the view or viewset.</p>
+<p>If the python <code>markdown</code> library is installed, then <a href="http://daringfireball.net/projects/markdown/">markdown syntax</a> may be used in the docstring, and will be converted to HTML in the browsable API. For example:</p>
+<pre class="prettyprint lang-py"><code>class AccountListView(views.APIView):
+ """
+ Returns a list of all **active** accounts in the system.
+
+ For more details on how accounts are activated please [see here][ref].
+
+ [ref]: http://example.com/activating-accounts
+ """
+</code></pre>
+<p>Note that one constraint of using viewsets is that any documentation be used for all generated views, so for example, you cannot have differing documentation for the generated list view and detail view.</p>
+<h4 id="the-options-method">The <code>OPTIONS</code> method</h4>
+<p>REST framework APIs also support programmatically accessible descriptions, using the <code>OPTIONS</code> HTTP method. A view will respond to an <code>OPTIONS</code> request with metadata including the name, description, and the various media types it accepts and responds with.</p>
+<p>When using the generic views, any <code>OPTIONS</code> requests will additionally respond with metadata regarding any <code>POST</code> or <code>PUT</code> actions available, describing which fields are on the serializer.</p>
+<p>You can modify the response behavior to <code>OPTIONS</code> requests by overriding the <code>metadata</code> view method. For example:</p>
+<pre class="prettyprint lang-py"><code>def metadata(self, request):
+ """
+ Don't include the view description in OPTIONS responses.
+ """
+ data = super(ExampleView, self).metadata(request)
+ data.pop('description')
+ return data
+</code></pre>
+<hr />
+<h2 id="the-hypermedia-approach">The hypermedia approach</h2>
+<p>To be fully RESTful an API should present its available actions as hypermedia controls in the responses that it sends.</p>
+<p>In this approach, rather than documenting the available API endpoints up front, the description instead concentrates on the <em>media types</em> that are used. The available actions take may be taken on any given URL are not strictly fixed, but are instead made available by the presence of link and form controls in the returned document.</p>
+<p>To implement a hypermedia API you'll need to decide on an appropriate media type for the API, and implement a custom renderer and parser for that media type. The <a href="rest-hypermedia-hateoas.html">REST, Hypermedia &amp; HATEOAS</a> section of the documentation includes pointers to background reading, as well as links to various hypermedia formats.</p>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/release-notes.html b/topics/release-notes.html
new file mode 100644
index 00000000..5d4322b2
--- /dev/null
+++ b/topics/release-notes.html
@@ -0,0 +1,771 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - Release Notes</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Release Notes">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="release-notes-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/credits.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/2.3-announcement.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#release-notes">Release Notes</a></li>
+<li><a href="#versioning">Versioning</a></li>
+<li><a href="#deprecation-policy">Deprecation policy</a></li>
+<li><a href="#upgrading">Upgrading</a></li>
+<li><a href="#23x-series">2.3.x series</a></li>
+<li><a href="#22x-series">2.2.x series</a></li>
+<li><a href="#21x-series">2.1.x series</a></li>
+<li><a href="#20x-series">2.0.x series</a></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>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="release-notes">Release Notes</h1>
+<blockquote>
+<p>Release Early, Release Often</p>
+<p>&mdash; Eric S. Raymond, <a href="http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html">The Cathedral and the Bazaar</a>.</p>
+</blockquote>
+<h2 id="versioning">Versioning</h2>
+<p>Minor version numbers (0.0.x) are used for changes that are API compatible. You should be able to upgrade between minor point releases without any other code changes.</p>
+<p>Medium version numbers (0.x.0) may include API changes, in line with the <a href="#deprecation-policy">deprecation policy</a>. You should read the release notes carefully before upgrading between medium point releases.</p>
+<p>Major version numbers (x.0.0) are reserved for substantial project milestones. No major point releases are currently planned.</p>
+<h2 id="deprecation-policy">Deprecation policy</h2>
+<p>REST framework releases follow a formal deprecation policy, which is in line with <a href="https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy">Django's deprecation policy</a>.</p>
+<p>The timeline for deprecation of a feature present in version 1.0 would work as follows:</p>
+<ul>
+<li>
+<p>Version 1.1 would remain <strong>fully backwards compatible</strong> with 1.0, but would raise <code>PendingDeprecationWarning</code> warnings if you use the feature that are due to be deprecated. These warnings are <strong>silent by default</strong>, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using <code>python -Wd manage.py test</code>, you'll be warned of any API changes you need to make.</p>
+</li>
+<li>
+<p>Version 1.2 would escalate these warnings to <code>DeprecationWarning</code>, which is loud by default.</p>
+</li>
+<li>
+<p>Version 1.3 would remove the deprecated bits of API entirely.</p>
+</li>
+</ul>
+<p>Note that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.</p>
+<h2 id="upgrading">Upgrading</h2>
+<p>To upgrade Django REST framework to the latest version, use pip:</p>
+<pre class="prettyprint lang-py"><code>pip install -U djangorestframework
+</code></pre>
+<p>You can determine your currently installed version using <code>pip freeze</code>:</p>
+<pre class="prettyprint lang-py"><code>pip freeze | grep djangorestframework
+</code></pre>
+<hr />
+<h2 id="23x-series">2.3.x series</h2>
+<h3 id="239">2.3.9</h3>
+<p><strong>Date</strong>: 15th November 2013</p>
+<ul>
+<li>Fix Django 1.6 exception API compatibility issue caused by <code>ValidationError</code>.</li>
+<li>Include errors in HTML forms in browsable API.</li>
+<li>Added JSON renderer support for numpy scalars.</li>
+<li>Added <code>transform_&lt;fieldname&gt;</code> hooks on serializers for easily modifying field output.</li>
+<li>Added <code>get_context</code> hook in <code>BrowsableAPIRenderer</code>.</li>
+<li>Allow serializers to be passed <code>files</code> but no <code>data</code>.</li>
+<li><code>HTMLFormRenderer</code> now renders serializers directly to HTML without needing to create an intermediate form object.</li>
+<li>Added <code>get_filter_backends</code> hook.</li>
+<li>Added queryset aggregates to allowed fields in <code>OrderingFilter</code>.</li>
+<li>Bugfix: Fix decimal suppoprt with <code>YAMLRenderer</code>.</li>
+<li>Bugfix: Fix submission of unicode in browsable API through raw data form.</li>
+</ul>
+<h3 id="238">2.3.8</h3>
+<p><strong>Date</strong>: 11th September 2013</p>
+<ul>
+<li>Added <code>DjangoObjectPermissions</code>, and <code>DjangoObjectPermissionsFilter</code>.</li>
+<li>Support customizable exception handling, using the <code>EXCEPTION_HANDLER</code> setting.</li>
+<li>Support customizable view name and description functions, using the <code>VIEW_NAME_FUNCTION</code> and <code>VIEW_DESCRIPTION_FUNCTION</code> settings.</li>
+<li>Added <code>MAX_PAGINATE_BY</code> setting and <code>max_paginate_by</code> generic view attribute.</li>
+<li>Added <code>cache</code> attribute to throttles to allow overriding of default cache.</li>
+<li>'Raw data' tab in browsable API now contains pre-populated data.</li>
+<li>'Raw data' and 'HTML form' tab preference in browseable API now saved between page views.</li>
+<li>Bugfix: <code>required=True</code> argument fixed for boolean serializer fields.</li>
+<li>Bugfix: <code>client.force_authenticate(None)</code> should also clear session info if it exists.</li>
+<li>Bugfix: Client sending empty string instead of file now clears <code>FileField</code>.</li>
+<li>Bugfix: Empty values on ChoiceFields with <code>required=False</code> now consistently return <code>None</code>.</li>
+</ul>
+<h3 id="237">2.3.7</h3>
+<p><strong>Date</strong>: 16th August 2013</p>
+<ul>
+<li>Added <code>APITestClient</code>, <code>APIRequestFactory</code> and <code>APITestCase</code> etc...</li>
+<li>Refactor <code>SessionAuthentication</code> to allow esier override for CSRF exemption.</li>
+<li>Remove 'Hold down "Control" message from help_text' widget messaging when not appropriate.</li>
+<li>Added admin configuration for auth tokens.</li>
+<li>Bugfix: <code>AnonRateThrottle</code> fixed to not throttle authenticated users.</li>
+<li>Bugfix: Don't set <code>X-Throttle-Wait-Seconds</code> when throttle does not have <code>wait</code> value.</li>
+<li>Bugfix: Fixed <code>PATCH</code> button title in browsable API.</li>
+<li>Bugfix: Fix issue with OAuth2 provider naive datetimes.</li>
+</ul>
+<h3 id="236">2.3.6</h3>
+<p><strong>Date</strong>: 27th June 2013</p>
+<ul>
+<li>Added <code>trailing_slash</code> option to routers.</li>
+<li>Include support for <code>HttpStreamingResponse</code>.</li>
+<li>Support wider range of default serializer validation when used with custom model fields.</li>
+<li>UTF-8 Support for browsable API descriptions. </li>
+<li>OAuth2 provider uses timezone aware datetimes when supported.</li>
+<li>Bugfix: Return error correctly when OAuth non-existent consumer occurs. </li>
+<li>Bugfix: Allow <code>FileUploadParser</code> to correctly filename if provided as URL kwarg.</li>
+<li>Bugfix: Fix <code>ScopedRateThrottle</code>.</li>
+</ul>
+<h3 id="235">2.3.5</h3>
+<p><strong>Date</strong>: 3rd June 2013</p>
+<ul>
+<li>Added <code>get_url</code> hook to <code>HyperlinkedIdentityField</code>.</li>
+<li>Serializer field <code>default</code> argument may be a callable.</li>
+<li><code>@action</code> decorator now accepts a <code>methods</code> argument.</li>
+<li>Bugfix: <code>request.user</code> should be still be accessible in renderer context if authentication fails.</li>
+<li>Bugfix: The <code>lookup_field</code> option on <code>HyperlinkedIdentityField</code> should apply by default to the url field on the serializer.</li>
+<li>Bugfix: <code>HyperlinkedIdentityField</code> should continue to support <code>pk_url_kwarg</code>, <code>slug_url_kwarg</code>, <code>slug_field</code>, in a pending deprecation state.</li>
+<li>Bugfix: Ensure we always return 404 instead of 500 if a lookup field cannot be converted to the correct lookup type. (Eg non-numeric <code>AutoInteger</code> pk lookup)</li>
+</ul>
+<h3 id="234">2.3.4</h3>
+<p><strong>Date</strong>: 24th May 2013</p>
+<ul>
+<li>Serializer fields now support <code>label</code> and <code>help_text</code>.</li>
+<li>Added <code>UnicodeJSONRenderer</code>.</li>
+<li><code>OPTIONS</code> requests now return metadata about fields for <code>POST</code> and <code>PUT</code> requests.</li>
+<li>Bugfix: <code>charset</code> now properly included in <code>Content-Type</code> of responses.</li>
+<li>Bugfix: Blank choice now added in browsable API on nullable relationships.</li>
+<li>Bugfix: Many to many relationships with <code>through</code> tables are now read-only.</li>
+<li>Bugfix: Serializer fields now respect model field args such as <code>max_length</code>.</li>
+<li>Bugfix: SlugField now performs slug validation.</li>
+<li>Bugfix: Lazy-translatable strings now properly serialized.</li>
+<li>Bugfix: Browsable API now supports bootswatch styles properly.</li>
+<li>Bugfix: HyperlinkedIdentityField now uses <code>lookup_field</code> kwarg.</li>
+</ul>
+<p><strong>Note</strong>: Responses now correctly include an appropriate charset on the <code>Content-Type</code> header. For example: <code>application/json; charset=utf-8</code>. If you have tests that check the content type of responses, you may need to update these accordingly.</p>
+<h3 id="233">2.3.3</h3>
+<p><strong>Date</strong>: 16th May 2013</p>
+<ul>
+<li>Added SearchFilter</li>
+<li>Added OrderingFilter</li>
+<li>Added GenericViewSet</li>
+<li>Bugfix: Multiple <code>@action</code> and <code>@link</code> methods now allowed on viewsets. </li>
+<li>Bugfix: Fix API Root view issue with DjangoModelPermissions</li>
+</ul>
+<h3 id="232">2.3.2</h3>
+<p><strong>Date</strong>: 8th May 2013</p>
+<ul>
+<li>Bugfix: Fix <code>TIME_FORMAT</code>, <code>DATETIME_FORMAT</code> and <code>DATE_FORMAT</code> settings.</li>
+<li>Bugfix: Fix <code>DjangoFilterBackend</code> issue, failing when used on view with queryset attribute.</li>
+</ul>
+<h3 id="231">2.3.1</h3>
+<p><strong>Date</strong>: 7th May 2013</p>
+<ul>
+<li>Bugfix: Fix breadcrumb rendering issue.</li>
+</ul>
+<h3 id="230">2.3.0</h3>
+<p><strong>Date</strong>: 7th May 2013</p>
+<ul>
+<li>ViewSets and Routers.</li>
+<li>ModelSerializers support reverse relations in 'fields' option.</li>
+<li>HyperLinkedModelSerializers support 'id' field in 'fields' option.</li>
+<li>Cleaner generic views.</li>
+<li>Support for multiple filter classes.</li>
+<li>FileUploadParser support for raw file uploads.</li>
+<li>DecimalField support.</li>
+<li>Made Login template easier to restyle.</li>
+<li>Bugfix: Fix issue with depth&gt;1 on ModelSerializer.</li>
+</ul>
+<p><strong>Note</strong>: See the <a href="2.3-announcement.html">2.3 announcement</a> for full details.</p>
+<hr />
+<h2 id="22x-series">2.2.x series</h2>
+<h3 id="227">2.2.7</h3>
+<p><strong>Date</strong>: 17th April 2013</p>
+<ul>
+<li>Loud failure when view does not return a <code>Response</code> or <code>HttpResponse</code>.</li>
+<li>Bugfix: Fix for Django 1.3 compatibility.</li>
+<li>Bugfix: Allow overridden <code>get_object()</code> to work correctly.</li>
+</ul>
+<h3 id="226">2.2.6</h3>
+<p><strong>Date</strong>: 4th April 2013</p>
+<ul>
+<li>OAuth2 authentication no longer requires unnecessary URL parameters in addition to the token.</li>
+<li>URL hyperlinking in browsable API now handles more cases correctly.</li>
+<li>Long HTTP headers in browsable API are broken in multiple lines when possible.</li>
+<li>Bugfix: Fix regression with DjangoFilterBackend not worthing correctly with single object views.</li>
+<li>Bugfix: OAuth should fail hard when invalid token used.</li>
+<li>Bugfix: Fix serializer potentially returning <code>None</code> object for models that define <code>__bool__</code> or <code>__len__</code>. </li>
+</ul>
+<h3 id="225">2.2.5</h3>
+<p><strong>Date</strong>: 26th March 2013</p>
+<ul>
+<li>Serializer support for bulk create and bulk update operations.</li>
+<li>Regression fix: Date and time fields return date/time objects by default. Fixes regressions caused by 2.2.2. See <a href="https://github.com/tomchristie/django-rest-framework/pull/743">#743</a> for more details.</li>
+<li>Bugfix: Fix 500 error is OAuth not attempted with OAuthAuthentication class installed.</li>
+<li><code>Serializer.save()</code> now supports arbitrary keyword args which are passed through to the object <code>.save()</code> method. Mixins use <code>force_insert</code> and <code>force_update</code> where appropriate, resulting in one less database query.</li>
+</ul>
+<h3 id="224">2.2.4</h3>
+<p><strong>Date</strong>: 13th March 2013</p>
+<ul>
+<li>OAuth 2 support.</li>
+<li>OAuth 1.0a support.</li>
+<li>Support X-HTTP-Method-Override header.</li>
+<li>Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404)</li>
+<li>Deal with error data nicely when deserializing lists of objects.</li>
+<li>Extra override hook to configure <code>DjangoModelPermissions</code> for unauthenticated users.</li>
+<li>Bugfix: Fix regression which caused extra database query on paginated list views.</li>
+<li>Bugfix: Fix pk relationship bug for some types of 1-to-1 relations.</li>
+<li>Bugfix: Workaround for Django bug causing case where <code>Authtoken</code> could be registered for cascade delete from <code>User</code> even if not installed.</li>
+</ul>
+<h3 id="223">2.2.3</h3>
+<p><strong>Date</strong>: 7th March 2013</p>
+<ul>
+<li>Bugfix: Fix None values for for <code>DateField</code>, <code>DateTimeField</code> and <code>TimeField</code>.</li>
+</ul>
+<h3 id="222">2.2.2</h3>
+<p><strong>Date</strong>: 6th March 2013</p>
+<ul>
+<li>Support for custom input and output formats for <code>DateField</code>, <code>DateTimeField</code> and <code>TimeField</code>.</li>
+<li>Cleanup: Request authentication is no longer lazily evaluated, instead authentication is always run, which results in more consistent, obvious behavior. Eg. Supplying bad auth credentials will now always return an error response, even if no permissions are set on the view.</li>
+<li>Bugfix for serializer data being uncacheable with pickle protocol 0.</li>
+<li>Bugfixes for model field validation edge-cases.</li>
+<li>Bugfix for authtoken migration while using a custom user model and south.</li>
+</ul>
+<h3 id="221">2.2.1</h3>
+<p><strong>Date</strong>: 22nd Feb 2013</p>
+<ul>
+<li>Security fix: Use <code>defusedxml</code> package to address XML parsing vulnerabilities.</li>
+<li>Raw data tab added to browsable API. (Eg. Allow for JSON input.)</li>
+<li>Added TimeField.</li>
+<li>Serializer fields can be mapped to any method that takes no args, or only takes kwargs which have defaults.</li>
+<li>Unicode support for view names/descriptions in browsable API.</li>
+<li>Bugfix: request.DATA should return an empty <code>QueryDict</code> with no data, not <code>None</code>.</li>
+<li>Bugfix: Remove unneeded field validation, which caused extra queries.</li>
+</ul>
+<p><strong>Security note</strong>: Following the <a href="http://blog.python.org/2013/02/announcing-defusedxml-fixes-for-xml.html">disclosure of security vulnerabilities</a> in Python's XML parsing libraries, use of the <code>XMLParser</code> class now requires the <code>defusedxml</code> package to be installed.</p>
+<p>The security vulnerabilities only affect APIs which use the <code>XMLParser</code> class, by enabling it in any views, or by having it set in the <code>DEFAULT_PARSER_CLASSES</code> setting. Note that the <code>XMLParser</code> class is not enabled by default, so this change should affect a minority of users.</p>
+<h3 id="220">2.2.0</h3>
+<p><strong>Date</strong>: 13th Feb 2013</p>
+<ul>
+<li>Python 3 support.</li>
+<li>Added a <code>post_save()</code> hook to the generic views.</li>
+<li>Allow serializers to handle dicts as well as objects.</li>
+<li>Deprecate <code>ManyRelatedField()</code> syntax in favor of <code>RelatedField(many=True)</code></li>
+<li>Deprecate <code>null=True</code> on relations in favor of <code>required=False</code>.</li>
+<li>Deprecate <code>blank=True</code> on CharFields, just use <code>required=False</code>.</li>
+<li>Deprecate optional <code>obj</code> argument in permissions checks in favor of <code>has_object_permission</code>.</li>
+<li>Deprecate implicit hyperlinked relations behavior.</li>
+<li>Bugfix: Fix broken DjangoModelPermissions.</li>
+<li>Bugfix: Allow serializer output to be cached.</li>
+<li>Bugfix: Fix styling on browsable API login.</li>
+<li>Bugfix: Fix issue with deserializing empty to-many relations.</li>
+<li>Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom <code>.restore_object()</code> method.</li>
+</ul>
+<p><strong>Note</strong>: See the <a href="2.2-announcement.html">2.2 announcement</a> for full details.</p>
+<hr />
+<h2 id="21x-series">2.1.x series</h2>
+<h3 id="2117">2.1.17</h3>
+<p><strong>Date</strong>: 26th Jan 2013</p>
+<ul>
+<li>Support proper 401 Unauthorized responses where appropriate, instead of always using 403 Forbidden.</li>
+<li>Support json encoding of timedelta objects.</li>
+<li><code>format_suffix_patterns()</code> now supports <code>include</code> style URL patterns.</li>
+<li>Bugfix: Fix issues with custom pagination serializers.</li>
+<li>Bugfix: Nested serializers now accept <code>source='*'</code> argument.</li>
+<li>Bugfix: Return proper validation errors when incorrect types supplied for relational fields.</li>
+<li>Bugfix: Support nullable FKs with <code>SlugRelatedField</code>.</li>
+<li>Bugfix: Don't call custom validation methods if the field has an error.</li>
+</ul>
+<p><strong>Note</strong>: If the primary authentication class is <code>TokenAuthentication</code> or <code>BasicAuthentication</code>, a view will now correctly return 401 responses to unauthenticated access, with an appropriate <code>WWW-Authenticate</code> header, instead of 403 responses.</p>
+<h3 id="2116">2.1.16</h3>
+<p><strong>Date</strong>: 14th Jan 2013</p>
+<ul>
+<li>Deprecate <code>django.utils.simplejson</code> in favor of Python 2.6's built-in json module.</li>
+<li>Bugfix: <code>auto_now</code>, <code>auto_now_add</code> and other <code>editable=False</code> fields now default to read-only.</li>
+<li>Bugfix: PK fields now only default to read-only if they are an AutoField or if <code>editable=False</code>.</li>
+<li>Bugfix: Validation errors instead of exceptions when serializers 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>
+</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>
+<h3 id="2115">2.1.15</h3>
+<p><strong>Date</strong>: 3rd Jan 2013</p>
+<ul>
+<li>Added <code>PATCH</code> support.</li>
+<li>Added <code>RetrieveUpdateAPIView</code>.</li>
+<li>Remove unused internal <code>save_m2m</code> flag on <code>ModelSerializer.save()</code>.</li>
+<li>Tweak behavior of hyperlinked fields with an explicit format suffix.</li>
+<li>Relation changes are now persisted in <code>.save()</code> instead of in <code>.restore_object()</code>.</li>
+<li>Bugfix: Fix issue with FileField raising exception instead of validation error when files=None.</li>
+<li>Bugfix: Partial updates should not set default values if field is not included.</li>
+</ul>
+<h3 id="2114">2.1.14</h3>
+<p><strong>Date</strong>: 31st Dec 2012</p>
+<ul>
+<li>Bugfix: ModelSerializers now include reverse FK fields on creation.</li>
+<li>Bugfix: Model fields with <code>blank=True</code> are now <code>required=False</code> by default.</li>
+<li>Bugfix: Nested serializers now support nullable relationships.</li>
+</ul>
+<p><strong>Note</strong>: From 2.1.14 onwards, relational fields move out of the <code>fields.py</code> module and into the new <code>relations.py</code> module, in order to separate them from regular data type fields, such as <code>CharField</code> and <code>IntegerField</code>.</p>
+<p>This change will not affect user code, so long as it's following the recommended import style of <code>from rest_framework import serializers</code> and referring to fields using the style <code>serializers.PrimaryKeyRelatedField</code>.</p>
+<h3 id="2113">2.1.13</h3>
+<p><strong>Date</strong>: 28th Dec 2012</p>
+<ul>
+<li>Support configurable <code>STATICFILES_STORAGE</code> storage.</li>
+<li>Bugfix: Related fields now respect the required flag, and may be required=False.</li>
+</ul>
+<h3 id="2112">2.1.12</h3>
+<p><strong>Date</strong>: 21st Dec 2012</p>
+<ul>
+<li>Bugfix: Fix bug that could occur using ChoiceField.</li>
+<li>Bugfix: Fix exception in browsable API on DELETE.</li>
+<li>Bugfix: Fix issue where pk was was being set to a string if set by URL kwarg.</li>
+</ul>
+<h3 id="2111">2.1.11</h3>
+<p><strong>Date</strong>: 17th Dec 2012</p>
+<ul>
+<li>Bugfix: Fix issue with M2M fields in browsable API.</li>
+</ul>
+<h3 id="2110">2.1.10</h3>
+<p><strong>Date</strong>: 17th Dec 2012</p>
+<ul>
+<li>Bugfix: Ensure read-only fields don't have model validation applied.</li>
+<li>Bugfix: Fix hyperlinked fields in paginated results.</li>
+</ul>
+<h3 id="219">2.1.9</h3>
+<p><strong>Date</strong>: 11th Dec 2012</p>
+<ul>
+<li>Bugfix: Fix broken nested serialization.</li>
+<li>Bugfix: Fix <code>Meta.fields</code> only working as tuple not as list.</li>
+<li>Bugfix: Edge case if unnecessarily specifying <code>required=False</code> on read only field.</li>
+</ul>
+<h3 id="218">2.1.8</h3>
+<p><strong>Date</strong>: 8th Dec 2012</p>
+<ul>
+<li>Fix for creating nullable Foreign Keys with <code>''</code> as well as <code>None</code>.</li>
+<li>Added <code>null=&lt;bool&gt;</code> related field option.</li>
+</ul>
+<h3 id="217">2.1.7</h3>
+<p><strong>Date</strong>: 7th Dec 2012</p>
+<ul>
+<li>Serializers now properly support nullable Foreign Keys.</li>
+<li>Serializer validation now includes model field validation, such as uniqueness constraints.</li>
+<li>Support 'true' and 'false' string values for BooleanField.</li>
+<li>Added pickle support for serialized data.</li>
+<li>Support <code>source='dotted.notation'</code> style for nested serializers.</li>
+<li>Make <code>Request.user</code> settable.</li>
+<li>Bugfix: Fix <code>RegexField</code> to work with <code>BrowsableAPIRenderer</code>.</li>
+</ul>
+<h3 id="216">2.1.6</h3>
+<p><strong>Date</strong>: 23rd Nov 2012</p>
+<ul>
+<li>Bugfix: Unfix DjangoModelPermissions. (I am a doofus.)</li>
+</ul>
+<h3 id="215">2.1.5</h3>
+<p><strong>Date</strong>: 23rd Nov 2012</p>
+<ul>
+<li>Bugfix: Fix DjangoModelPermissions.</li>
+</ul>
+<h3 id="214">2.1.4</h3>
+<p><strong>Date</strong>: 22nd Nov 2012</p>
+<ul>
+<li>Support for partial updates with serializers.</li>
+<li>Added <code>RegexField</code>.</li>
+<li>Added <code>SerializerMethodField</code>.</li>
+<li>Serializer performance improvements.</li>
+<li>Added <code>obtain_token_view</code> to get tokens when using <code>TokenAuthentication</code>.</li>
+<li>Bugfix: Django 1.5 configurable user support for <code>TokenAuthentication</code>.</li>
+</ul>
+<h3 id="213">2.1.3</h3>
+<p><strong>Date</strong>: 16th Nov 2012</p>
+<ul>
+<li>Added <code>FileField</code> and <code>ImageField</code>. For use with <code>MultiPartParser</code>.</li>
+<li>Added <code>URLField</code> and <code>SlugField</code>.</li>
+<li>Support for <code>read_only_fields</code> on <code>ModelSerializer</code> classes.</li>
+<li>Support for clients overriding the pagination page sizes. Use the <code>PAGINATE_BY_PARAM</code> setting or set the <code>paginate_by_param</code> attribute on a generic view.</li>
+<li>201 Responses now return a 'Location' header.</li>
+<li>Bugfix: Serializer fields now respect <code>max_length</code>.</li>
+</ul>
+<h3 id="212">2.1.2</h3>
+<p><strong>Date</strong>: 9th Nov 2012</p>
+<ul>
+<li><strong>Filtering support.</strong></li>
+<li>Bugfix: Support creation of objects with reverse M2M relations.</li>
+</ul>
+<h3 id="211">2.1.1</h3>
+<p><strong>Date</strong>: 7th Nov 2012</p>
+<ul>
+<li>Support use of HTML exception templates. Eg. <code>403.html</code></li>
+<li>Hyperlinked fields take optional <code>slug_field</code>, <code>slug_url_kwarg</code> and <code>pk_url_kwarg</code> arguments.</li>
+<li>Bugfix: Deal with optional trailing slashes properly when generating breadcrumbs.</li>
+<li>Bugfix: Make textareas same width as other fields in browsable API.</li>
+<li>Private API change: <code>.get_serializer</code> now uses same <code>instance</code> and <code>data</code> ordering as serializer initialization.</li>
+</ul>
+<h3 id="210">2.1.0</h3>
+<p><strong>Date</strong>: 5th Nov 2012</p>
+<ul>
+<li><strong>Serializer <code>instance</code> and <code>data</code> keyword args have their position swapped.</strong></li>
+<li><code>queryset</code> argument is now optional on writable model fields.</li>
+<li>Hyperlinked related fields optionally take <code>slug_field</code> and <code>slug_url_kwarg</code> arguments.</li>
+<li>Support Django's cache framework.</li>
+<li>Minor field improvements. (Don't stringify dicts, more robust many-pk fields.)</li>
+<li>Bugfix: Support choice field in Browsable API.</li>
+<li>Bugfix: Related fields with <code>read_only=True</code> do not require a <code>queryset</code> argument.</li>
+</ul>
+<p><strong>API-incompatible changes</strong>: Please read <a href="https://groups.google.com/d/topic/django-rest-framework/Vv2M0CMY9bg/discussion">this thread</a> regarding the <code>instance</code> and <code>data</code> keyword args before updating to 2.1.0.</p>
+<hr />
+<h2 id="20x-series">2.0.x series</h2>
+<h3 id="202">2.0.2</h3>
+<p><strong>Date</strong>: 2nd Nov 2012</p>
+<ul>
+<li>Fix issues with pk related fields in the browsable API.</li>
+</ul>
+<h3 id="201">2.0.1</h3>
+<p><strong>Date</strong>: 1st Nov 2012</p>
+<ul>
+<li>Add support for relational fields in the browsable API.</li>
+<li>Added SlugRelatedField and ManySlugRelatedField.</li>
+<li>If PUT creates an instance return '201 Created', instead of '200 OK'.</li>
+</ul>
+<h3 id="200">2.0.0</h3>
+<p><strong>Date</strong>: 30th Oct 2012</p>
+<ul>
+<li><strong>Fix all of the things.</strong> (Well, almost.)</li>
+<li>For more information please see the <a href="rest-framework-2-announcement.html">2.0 announcement</a>.</li>
+</ul>
+<hr />
+<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><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/rest-framework-2-announcement.html b/topics/rest-framework-2-announcement.html
new file mode 100644
index 00000000..99a0604b
--- /dev/null
+++ b/topics/rest-framework-2-announcement.html
@@ -0,0 +1,298 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - Django REST framework 2</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Django REST framework 2">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="rest-framework-2-announcement-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/2.2-announcement.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/contributing.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#django-rest-framework-2">Django REST framework 2</a></li>
+<li><a href="#user-feedback">User feedback</a></li>
+<li><a href="#serialization">Serialization</a></li>
+<li><a href="#generic-views">Generic views</a></li>
+<li><a href="#requests,-responses-&-views">Requests, Responses & Views</a></li>
+<li><a href="#api-design">API Design</a></li>
+<li><a href="#the-browsable-api">The Browsable API</a></li>
+<li><a href="#documentation">Documentation</a></li>
+<li><a href="#summary">Summary</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="django-rest-framework-2">Django REST framework 2</h1>
+<p>What it is, and why you should care.</p>
+<blockquote>
+<p>Most people just make the mistake that it should be simple to design simple things. In reality, the effort required to design something is inversely proportional to the simplicity of the result.</p>
+<p>&mdash; <a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven#comment-724">Roy Fielding</a></p>
+</blockquote>
+<hr />
+<p><strong>Announcement:</strong> REST framework 2 released - Tue 30th Oct 2012 </p>
+<hr />
+<p>REST framework 2 is an almost complete reworking of the original framework, which comprehensively addresses some of the original design issues.</p>
+<p>Because the latest version should be considered a re-release, rather than an incremental improvement, we've skipped a version, and called this release Django REST framework 2.0.</p>
+<p>This article is intended to give you a flavor of what REST framework 2 is, and why you might want to give it a try.</p>
+<h2 id="user-feedback">User feedback</h2>
+<p>Before we get cracking, let's start with the hard sell, with a few bits of feedback from some early adopters…</p>
+<p>"Django REST framework 2 is beautiful. Some of the API design is worthy of @kennethreitz." - <a href="https://twitter.com/kobutsu/status/261689665952833536">Kit La Touche</a></p>
+<p>"Since it's pretty much just Django, controlling things like URLs has been a breeze... I think [REST framework 2] has definitely got the right approach here; even simple things like being able to override a function called post to do custom work during rather than having to intimately know what happens during a post make a huge difference to your productivity." - <a href="https://groups.google.com/d/msg/django-rest-framework/heRGHzG6BWQ/ooVURgpwVC0J">Ian Strachan</a></p>
+<p>"I switched to the 2.0 branch and I don't regret it - fully refactored my code in another &half; day and it's <em>much</em> more to my tastes" - <a href="https://groups.google.com/d/msg/django-rest-framework/flsXbvYqRoY/9lSyntOf5cUJ">Bruno Desthuilliers</a></p>
+<p>Sounds good, right? Let's get into some details...</p>
+<h2 id="serialization">Serialization</h2>
+<p>REST framework 2 includes a totally re-worked serialization engine, that was initially intended as a replacement for Django's existing inflexible fixture serialization, and which meets the following design goals:</p>
+<ul>
+<li>A declarative serialization API, that mirrors Django's <code>Forms</code>/<code>ModelForms</code> API.</li>
+<li>Structural concerns are decoupled from encoding concerns.</li>
+<li>Able to support rendering and parsing to many formats, including both machine-readable representations and HTML forms.</li>
+<li>Validation that can be mapped to obvious and comprehensive error responses. </li>
+<li>Serializers that support both nested, flat, and partially-nested representations.</li>
+<li>Relationships that can be expressed as primary keys, hyperlinks, slug fields, and other custom representations.</li>
+</ul>
+<p>Mapping between the internal state of the system and external representations of that state is the core concern of building Web APIs. Designing serializers that allow the developer to do so in a flexible and obvious way is a deceptively difficult design task, and with the new serialization API we think we've pretty much nailed it.</p>
+<h2 id="generic-views">Generic views</h2>
+<p>When REST framework was initially released at the start of 2011, the current Django release was version 1.2. REST framework included a backport of Django 1.3's upcoming <code>View</code> class, but it didn't take full advantage of the generic view implementations.</p>
+<p>With the new release the generic views in REST framework now tie in with Django's generic views. The end result is that framework is clean, lightweight and easy to use.</p>
+<h2 id="requests-responses-views">Requests, Responses &amp; Views</h2>
+<p>REST framework 2 includes <code>Request</code> and <code>Response</code> classes, than are used in place of Django's existing <code>HttpRequest</code> and <code>HttpResponse</code> classes. Doing so allows logic such as parsing the incoming request or rendering the outgoing response to be supported transparently by the framework.</p>
+<p>The <code>Request</code>/<code>Response</code> approach leads to a much cleaner API, less logic in the view itself, and a simple, obvious request-response cycle.</p>
+<p>REST framework 2 also allows you to work with both function-based and class-based views. For simple API views all you need is a single <code>@api_view</code> decorator, and you're good to go.</p>
+<h2 id="api-design">API Design</h2>
+<p>Pretty much every aspect of REST framework has been reworked, with the aim of ironing out some of the design flaws of the previous versions. Each of the components of REST framework are cleanly decoupled, and can be used independently of each-other, and there are no monolithic resource classes, overcomplicated mixin combinations, or opinionated serialization or URL routing decisions.</p>
+<h2 id="the-browsable-api">The Browsable API</h2>
+<p>Django REST framework's most unique feature is the way it is able to serve up both machine-readable representations, and a fully browsable HTML representation to the same endpoints.</p>
+<p>Browsable Web APIs are easier to work with, visualize and debug, and generally makes it easier and more frictionless to inspect and work with.</p>
+<p>With REST framework 2, the browsable API gets a snazzy new bootstrap-based theme that looks great and is even nicer to work with.</p>
+<p>There are also some functionality improvements - actions such as as <code>POST</code> and <code>DELETE</code> will only display if the user has the appropriate permissions.</p>
+<p><img alt="Browsable API" src="../img/quickstart.png" /></p>
+<p><strong>Image above</strong>: An example of the browsable API in REST framework 2</p>
+<h2 id="documentation">Documentation</h2>
+<p>As you can see the documentation for REST framework has been radically improved. It gets a completely new style, using markdown for the documentation source, and a bootstrap-based theme for the styling.</p>
+<p>We're really pleased with how the docs style looks - it's simple and clean, is easy to navigate around, and we think it reads great.</p>
+<h2 id="summary">Summary</h2>
+<p>In short, we've engineered the hell outta this thing, and we're incredibly proud of the result.</p>
+<p>If you're interested please take a browse around the documentation. <a href="../tutorial/1-serialization.html">The tutorial</a> is a great place to get started.</p>
+<p>There's also a <a href="http://restframework.herokuapp.com/">live sandbox version of the tutorial API</a> available for testing.</p>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/rest-hypermedia-hateoas.html b/topics/rest-hypermedia-hateoas.html
new file mode 100644
index 00000000..2f26f901
--- /dev/null
+++ b/topics/rest-hypermedia-hateoas.html
@@ -0,0 +1,266 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - REST, Hypermedia & HATEOAS</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, REST, Hypermedia & HATEOAS">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="rest-hypermedia-hateoas-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small " href="../topics/contributing.html">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small " href="../topics/browsable-api.html"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#rest,-hypermedia-&-hateoas">REST, Hypermedia & HATEOAS</a></li>
+<li><a href="#building-hypermedia-apis-with-rest-framework">Building Hypermedia APIs with REST framework</a></li>
+<li><a href="#what-rest-framework-provides">What REST framework provides.</a></li>
+<li><a href="#what-rest-framework-doesnt-provide">What REST framework doesn't provide.</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <h1 id="rest-hypermedia-hateoas">REST, Hypermedia &amp; HATEOAS</h1>
+<blockquote>
+<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>
+</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>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>The following fall into the "required reading" category.</p>
+<ul>
+<li>Roy Fielding's dissertation - <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">Architectural Styles and
+the Design of Network-based Software Architectures</a>.</li>
+<li>Roy Fielding's "<a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">REST APIs must be hypertext-driven</a>" blog post.</li>
+<li>Leonard Richardson &amp; Sam Ruby's <a href="http://www.amazon.com/Restful-Web-Services-Leonard-Richardson/dp/0596529260">RESTful Web Services</a>.</li>
+<li>Mike Amundsen's <a href="http://www.amazon.com/Building-Hypermedia-APIs-HTML5-Node/dp/1449306578">Building Hypermedia APIs with HTML5 and Node</a>.</li>
+<li>Steve Klabnik's <a href="http://designinghypermediaapis.com/">Designing Hypermedia APIs</a>.</li>
+<li>The <a href="http://martinfowler.com/articles/richardsonMaturityModel.html">Richardson Maturity Model</a>.</li>
+</ul>
+<p>For a more thorough background, check out Klabnik's <a href="http://blog.steveklabnik.com/posts/2012-02-27-hypermedia-api-reading-list">Hypermedia API reading list</a>.</p>
+<h2 id="building-hypermedia-apis-with-rest-framework">Building Hypermedia APIs with REST framework</h2>
+<p>REST framework is an agnostic Web API toolkit. It does help guide you towards building well-connected APIs, and makes it easy to design appropriate media types, but it does not strictly enforce any particular design style.</p>
+<h2 id="what-rest-framework-provides">What REST framework provides.</h2>
+<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.html">serialization</a> and <a href="../api-guide/parsers.html">parser</a>/<a href="../api-guide/renderers.html">renderer</a> components that make it easy to build appropriate media types, <a href="../api-guide/fields.html">hyperlinked relations</a> for building well-connected systems, and great support for <a href="../api-guide/content-negotiation.html">content negotiation</a>.</p>
+<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>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>
diff --git a/topics/writable-nested-serializers.html b/topics/writable-nested-serializers.html
new file mode 100644
index 00000000..0ccdc25b
--- /dev/null
+++ b/topics/writable-nested-serializers.html
@@ -0,0 +1,274 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Django REST framework - Writable nested serializers</title>
+ <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Writable nested serializers">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet">
+
+ <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-18852272-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </head>
+ <body onload="prettyPrint()" class="writable-nested-serializers-page">
+
+ <div class="wrapper">
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <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-inverse btn-small disabled" href="#">Next <i class="icon-arrow-right icon-white"></i></a>
+ <a class="repo-link btn btn-inverse btn-small disabled" href="#"><i class="icon-arrow-left icon-white"></i> Previous</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="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="http://django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+ <ul class="nav">
+ <li><a href="http://django-rest-framework.org">Home</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/tutorial/quickstart.html">Quickstart</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/1-serialization.html">1 - Serialization</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views.html">3 - Class based views</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
+ <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/api-guide/requests.html">Requests</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/responses.html">Responses</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/views.html">Views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/generic-views.html">Generic views</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/viewsets.html">Viewsets</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/routers.html">Routers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/parsers.html">Parsers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/renderers.html">Renderers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/serializers.html">Serializers</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/fields.html">Serializer fields</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/relations.html">Serializer relations</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/authentication.html">Authentication</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/permissions.html">Permissions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/throttling.html">Throttling</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/filtering.html">Filtering</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/pagination.html">Pagination</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/content-negotiation.html">Content negotiation</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/format-suffixes.html">Format suffixes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/reverse.html">Returning URLs</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/exceptions.html">Exceptions</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/status-codes.html">Status codes</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/testing.html">Testing</a></li>
+ <li><a href="http://django-rest-framework.org/api-guide/settings.html">Settings</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://django-rest-framework.org/topics/documenting-your-api.html">Documenting your API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browser-enhancements.html">Browser enhancements</a></li>
+ <li><a href="http://django-rest-framework.org/topics/browsable-api.html">The Browsable API</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
+ <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.2-announcement.html">2.2 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/2.3-announcement.html">2.3 Announcement</a></li>
+ <li><a href="http://django-rest-framework.org/topics/release-notes.html">Release Notes</a></li>
+ <li><a href="http://django-rest-framework.org/topics/credits.html">Credits</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav pull-right">
+ <!-- TODO
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="#">Trunk</a></li>
+ <li><a href="#">2.0.0</a></li>
+ </ul>
+ </li>
+ -->
+ </ul>
+ </div><!--/.nav-collapse -->
+ </div>
+ </div>
+ </div>
+
+ <div class="body-content">
+ <div class="container-fluid">
+
+<!-- Search Modal -->
+<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h3 id="myModalLabel">Documentation search</h3>
+ </div>
+ <div class="modal-body">
+ <!-- Custom google search -->
+ <script>
+ (function() {
+ var cx = '015016005043623903336:rxraeohqk6w';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ </script>
+ <gcse:search></gcse:search>
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ </div>
+</div>
+
+ <div class="row-fluid">
+
+ <div class="span3">
+ <!-- TODO
+ <p style="margin-top: -12px">
+ <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
+ <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
+ </p>
+ -->
+ <div id="table-of-contents">
+ <ul class="nav nav-list side-nav well sidebar-nav-fixed">
+ <li class="main"><a href="#writable-nested-serializers">Writable nested serializers</a></li>
+<li><a href="#one-to-many-data-structures">One-to-many data structures</a></li>
+
+ <div>
+ <hr>
+
+<p><strong>The team behind REST framework are launching a new API service.</strong></p>
+
+<p>If you want to be first in line when we start issuing invitations, please sign up here:</p>
+
+<!-- Begin MailChimp Signup Form -->
+<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+ #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
+ /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
+ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
+</style>
+<div id="mc_embed_signup" style="background: rgb(245, 245, 245)">
+<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&amp;id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
+<!-- <label for="mce-EMAIL">Keep me posted!</label>
+ --> <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required>
+ <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
+</form>
+</div>
+</style></div>
+ </ul>
+
+
+<!--End mc_embed_signup-->
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+ <blockquote>
+<p>To save HTTP requests, it may be convenient to send related documents along with the request.</p>
+<p>&mdash; <a href="http://jsonapi.org/format/#url-based-json-api">JSON API specification for Ember Data</a>.</p>
+</blockquote>
+<h1 id="writable-nested-serializers">Writable nested serializers</h1>
+<p>Although flat data structures serve to properly delineate between the individual entities in your service, there are cases where it may be more appropriate or convenient to use nested data structures.</p>
+<p>Nested data structures are easy enough to work with if they're read-only - simply nest your serializer classes and you're good to go. However, there are a few more subtleties to using writable nested serializers, due to the dependancies between the various model instances, and the need to save or delete multiple instances in a single action.</p>
+<h2 id="one-to-many-data-structures">One-to-many data structures</h2>
+<p><em>Example of a <strong>read-only</strong> nested serializer. Nothing complex to worry about here.</em></p>
+<pre class="prettyprint lang-py"><code>class ToDoItemSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = ToDoItem
+ fields = ('text', 'is_completed')
+
+class ToDoListSerializer(serializers.ModelSerializer):
+ items = ToDoItemSerializer(many=True, read_only=True)
+
+ class Meta:
+ model = ToDoList
+ fields = ('title', 'items')
+</code></pre>
+<p>Some example output from our serializer.</p>
+<pre class="prettyprint lang-py"><code>{
+ 'title': 'Leaving party preperations',
+ 'items': {
+ {'text': 'Compile playlist', 'is_completed': True},
+ {'text': 'Send invites', 'is_completed': False},
+ {'text': 'Clean house', 'is_completed': False}
+ }
+}
+</code></pre>
+<p>Let's take a look at updating our nested one-to-many data structure.</p>
+<h3 id="validation-errors">Validation errors</h3>
+<h3 id="adding-and-removing-items">Adding and removing items</h3>
+<h3 id="making-patch-requests">Making PATCH requests</h3>
+ </div><!--/span-->
+ </div><!--/row-->
+ </div><!--/.fluid-container-->
+ </div><!--/.body content-->
+
+ <div id="push"></div>
+ </div><!--/.wrapper -->
+
+ <footer class="span12">
+ <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
+ </footer>
+
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
+ <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script>
+ <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() { scrollBy(0, -50) };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
+
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
+
+ // Dynamically force sidenav to no higher than browser window
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+
+ $(function(){
+ $(window).resize(function(){
+ $('.side-nav').css('max-height', window.innerHeight - 130);
+ });
+ });
+ </script>
+</body></html>