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.2-announcement/index.html533
-rw-r--r--topics/2.3-announcement/index.html (renamed from topics/2.3-announcement.html)643
-rw-r--r--topics/2.4-accouncement.html354
-rw-r--r--topics/2.4-announcement.html355
-rw-r--r--topics/2.4-announcement/index.html556
-rw-r--r--topics/3.0-announcement.html886
-rw-r--r--topics/ajax-csrf-cors.html263
-rw-r--r--topics/ajax-csrf-cors/index.html443
-rw-r--r--topics/browsable-api.html358
-rw-r--r--topics/browsable-api/index.html538
-rw-r--r--topics/browser-enhancements.html297
-rw-r--r--topics/browser-enhancements/index.html486
-rw-r--r--topics/contributing.html399
-rw-r--r--topics/contributing/index.html631
-rw-r--r--topics/credits/index.html (renamed from topics/credits.html)533
-rw-r--r--topics/documenting-your-api.html302
-rw-r--r--topics/documenting-your-api/index.html482
-rw-r--r--topics/kickstarter-announcement/index.html (renamed from topics/kickstarter-announcement.html)533
-rw-r--r--topics/release-notes/index.html (renamed from topics/release-notes.html)601
-rw-r--r--topics/rest-framework-2-announcement.html298
-rw-r--r--topics/rest-framework-2-announcement/index.html493
-rw-r--r--topics/rest-hypermedia-hateoas.html266
-rw-r--r--topics/rest-hypermedia-hateoas/index.html446
-rw-r--r--topics/third-party-resources.html330
-rw-r--r--topics/third-party-resources/index.html622
-rw-r--r--topics/writable-nested-serializers.html274
27 files changed, 6779 insertions, 5493 deletions
diff --git a/topics/2.2-announcement.html b/topics/2.2-announcement.html
deleted file mode 100644
index ca5414bc..00000000
--- a/topics/2.2-announcement.html
+++ /dev/null
@@ -1,350 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>REST framework 2.2 announcement - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/2.2-announcement"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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">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"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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 class="promo">
-
- </div>
-</ul>
-
- </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://www.django-rest-framework.org/topics/credits">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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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.2-announcement/index.html b/topics/2.2-announcement/index.html
new file mode 100644
index 00000000..2c41b0ca
--- /dev/null
+++ b/topics/2.2-announcement/index.html
@@ -0,0 +1,533 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>2.2 Announcement - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/2.2-announcement/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, 2.2 Announcement">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../2.3-announcement">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../rest-framework-2-announcement">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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>
+
+
+
+
+
+
+ </ul>
+
+ </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://www.django-rest-framework.org/topics/credits">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><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><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><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><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><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><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><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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/2.3-announcement.html b/topics/2.3-announcement/index.html
index 27da50d8..ccbf4b7f 100644
--- a/topics/2.3-announcement.html
+++ b/topics/2.3-announcement/index.html
@@ -1,65 +1,74 @@
<!DOCTYPE html>
<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>REST framework 2.3 announcement - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/2.3-announcement"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </head>
- <body onload="prettyPrint()" class="2.3-announcement-page">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>2.3 Announcement - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/2.3-announcement/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, 2.3 Announcement">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-page">
<div class="wrapper">
- <div class="navbar navbar-inverse navbar-fixed-top">
+ <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.4-announcement">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/2.2-announcement"><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="repo-link btn btn-primary btn-small" href="https://github.com/tomchristie/django-rest-framework/tree/master">GitHub</a>
+ <a class="repo-link btn btn-inverse btn-small " rel="prev" href="../2.4-announcement">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../2.2-announcement">
+ <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>
@@ -67,80 +76,218 @@ a.fusion-poweredby {
</a>
<a class="brand" href="http://www.django-rest-framework.org">Django REST framework</a>
<div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
+
+ <li >
+ <a href="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
</ul>
</li>
+
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
</ul>
</li>
- <li class="dropdown">
+
+ <li class="dropdown active">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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>
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</a>
+ </li>
+
</ul>
</li>
- -->
+
+
</ul>
- </div><!--/.nav-collapse -->
+
+ </div>
+ <!--/.nav-collapse -->
+
</div>
</div>
</div>
@@ -148,32 +295,34 @@ a.fusion-poweredby {
<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>
+ <!-- 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">
@@ -186,41 +335,109 @@ a.fusion-poweredby {
-->
<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 class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <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>
+
+
+
+
+
+
+ </ul>
</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">ViewSet</a> and <a href="../api-guide/routers">Router</a> classes.</p>
+<p>The 2.3 release introduces the <a href="../../api-guide/viewsets">ViewSet</a> and <a href="../../api-guide/routers">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>"""
+<pre><code>"""
A REST framework API for viewing and editing users and groups.
"""
from django.conf.urls.defaults import url, include
@@ -249,7 +466,7 @@ urlpatterns = [
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">newest section in the tutorial</a>, which demonstrates their usage.</p>
+<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">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>
@@ -257,7 +474,7 @@ urlpatterns = [
<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):
+<pre><code>class BlogSerializer(serializers.ModelSerializer):
comments = serializers.PrimaryKeyRelatedField(many=True)
class Meta:
@@ -265,7 +482,7 @@ urlpatterns = [
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):
+<pre><code>class BlogSerializer(serializers.ModelSerializer):
"""
Don't need to specify the 'comments' field explicitly anymore.
"""
@@ -274,7 +491,7 @@ urlpatterns = [
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):
+<pre><code>class BlogSerializer(serializers.HyperlinkedModelSerializer):
"""
This is a hyperlinked serializer, which default to using
a field named 'url' as the primary identifier.
@@ -328,18 +545,18 @@ urlpatterns = [
</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):
+<pre><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()),
+<pre><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):
+<pre><code>class DisallowEmptyQuerysetMixin(object):
def get_queryset(self):
queryset = super(DisallowEmptyQuerysetMixin, self).get_queryset()
if not queryset.exists():
@@ -350,7 +567,7 @@ urlpatterns = [
<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,
+<pre><code> account = HyperlinkedRelatedField(read_only=True,
lookup_field='slug',
view_name='account-detail')
</code></pre>
@@ -363,23 +580,23 @@ urlpatterns = [
<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>
+<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>
+<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):
+<pre><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):
+<pre><code>class AccountListView(generics.RetrieveAPIView):
serializer_class = MyModelSerializer
def get_queryset(self):
@@ -402,42 +619,52 @@ urlpatterns = [
<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 -->
+ </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>
+ <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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- var shiftWindow = function() { scrollBy(0, -50) };
- if (location.hash) shiftWindow();
- window.addEventListener("hashchange", shiftWindow);
-
- $('.dropdown-menu').on('click touchstart', function(event) {
- event.stopPropagation();
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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>
- // 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>
+</html> \ No newline at end of file
diff --git a/topics/2.4-accouncement.html b/topics/2.4-accouncement.html
deleted file mode 100644
index 7526010f..00000000
--- a/topics/2.4-accouncement.html
+++ /dev/null
@@ -1,354 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>REST framework 2.4 announcement - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/2.4-accouncement"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, REST framework 2.4 announcement">
- <meta name="author" content="Tom Christie">
-
- <!-- Le styles -->
- <link href="http://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </head>
- <body onload="prettyPrint()" class="2.4-accouncement-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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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-24-announcement">REST framework 2.4 announcement</a></li>
-<li><a href="#version-requirements">Version requirements</a></li>
-<li><a href="#django-17-support">Django 1.7 support</a></li>
-<li><a href="#deprecation-of-`model`-view-attribute">Deprecation of `.model` view attribute</a></li>
-<li><a href="#updated-test-runner">Updated test runner</a></li>
-<li><a href="#improved-viewset-routing">Improved viewset routing</a></li>
-<li><a href="#throttle-behavior">Throttle behavior</a></li>
-<li><a href="#other-features">Other features</a></li>
-<li><a href="#deprecations">Deprecations</a></li>
-<li><a href="#labels-and-milestones">Labels and milestones</a></li>
-<li><a href="#next-steps">Next steps</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <h1 id="rest-framework-24-announcement">REST framework 2.4 announcement</h1>
-<p>The 2.4 release is largely an intermediate step, tying up some outstanding issues prior to the 3.x series.</p>
-<h2 id="version-requirements">Version requirements</h2>
-<p>Support for Django 1.3 has been dropped.
-The lowest supported version of Django is now 1.4.2.</p>
-<p>The current plan is for REST framework to remain in lockstep with <a href="https://docs.djangoproject.com/en/dev/internals/release-process/#long-term-support-lts-releases">Django's long-term support policy</a>.</p>
-<h2 id="django-17-support">Django 1.7 support</h2>
-<p>The optional authtoken application now includes support for <em>both</em> Django 1.7 schema migrations, <em>and</em> for old-style <code>south</code> migrations.</p>
-<p><strong>If you are using authtoken, and you want to continue using <code>south</code>, you must upgrade your <code>south</code> package to version 1.0.</strong></p>
-<h2 id="deprecation-of-model-view-attribute">Deprecation of <code>.model</code> view attribute</h2>
-<p>The <code>.model</code> attribute on view classes is an optional shortcut for either or both of <code>.serializer_class</code> and <code>.queryset</code>. It's usage results in more implicit, less obvious behavior.</p>
-<p>The documentation has previously stated that usage of the more explicit style is prefered, and we're now taking that one step further and deprecating the usage of the <code>.model</code> shortcut.</p>
-<p>Doing so will mean that there are cases of API code where you'll now need to include a serializer class where you previously were just using the <code>.model</code> shortcut. However we firmly believe that it is the right trade-off to make.</p>
-<p>Removing the shortcut takes away an unneccessary layer of abstraction, and makes your codebase more explicit without any significant extra complexity. It also results in better consistency, as there's now only one way to set the serializer class and queryset attributes for the view, instead of two.</p>
-<p>The <code>DEFAULT_MODEL_SERIALIZER_CLASS</code> API setting is now also deprecated.</p>
-<h2 id="updated-test-runner">Updated test runner</h2>
-<p>We now have a new test runner for developing against the project,, that uses the excellent <a href="http://pytest.org">py.test</a> library.</p>
-<p>To use it make sure you have first installed the test requirements.</p>
-<pre class="prettyprint lang-py"><code>pip install -r requirements-test.txt
-</code></pre>
-<p>Then run the <code>runtests.py</code> script.</p>
-<pre class="prettyprint lang-py"><code>./runtests.py
-</code></pre>
-<p>The new test runner also includes <a href="https://flake8.readthedocs.org">flake8</a> code linting, which should help keep our coding style consistent.</p>
-<h4 id="test-runner-flags">Test runner flags</h4>
-<p>Run using a more concise output style.</p>
-<pre class="prettyprint lang-py"><code>./runtests -q
-</code></pre>
-<p>Run the tests using a more concise output style, no coverage, no flake8.</p>
-<pre class="prettyprint lang-py"><code>./runtests --fast
-</code></pre>
-<p>Don't run the flake8 code linting.</p>
-<pre class="prettyprint lang-py"><code>./runtests --nolint
-</code></pre>
-<p>Only run the flake8 code linting, don't run the tests.</p>
-<pre class="prettyprint lang-py"><code>./runtests --lintonly
-</code></pre>
-<p>Run the tests for a given test case.</p>
-<pre class="prettyprint lang-py"><code>./runtests MyTestCase
-</code></pre>
-<p>Run the tests for a given test method.</p>
-<pre class="prettyprint lang-py"><code>./runtests MyTestCase.test_this_method
-</code></pre>
-<p>Shorter form to run the tests for a given test method.</p>
-<pre class="prettyprint lang-py"><code>./runtests test_this_method
-</code></pre>
-<p>Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.</p>
-<h2 id="improved-viewset-routing">Improved viewset routing</h2>
-<p>The <code>@action</code> and <code>@link</code> decorators were inflexible in that they only allowed additional routes to be added against instance style URLs, not against list style URLs.</p>
-<p>The <code>@action</code> and <code>@link</code> decorators have now been moved to pending deprecation, and the <code>@list_route</code> and <code>@detail_route</code> decorators have been introduced.</p>
-<p>Here's an example of using the new decorators. Firstly we have a detail-type route named "set_password" that acts on a single instance, and takes a <code>pk</code> argument in the URL. Secondly we have a list-type route named "recent_users" that acts on a queryset, and does not take any arguments in the URL.</p>
-<pre class="prettyprint lang-py"><code>class UserViewSet(viewsets.ModelViewSet):
- """
- A viewset that provides the standard actions
- """
- queryset = User.objects.all()
- serializer_class = UserSerializer
-
- @detail_route(methods=['post'])
- def set_password(self, request, pk=None):
- user = self.get_object()
- serializer = PasswordSerializer(data=request.DATA)
- if serializer.is_valid():
- user.set_password(serializer.data['password'])
- user.save()
- return Response({'status': 'password set'})
- else:
- return Response(serializer.errors,
- status=status.HTTP_400_BAD_REQUEST)
-
- @list_route()
- def recent_users(self, request):
- recent_users = User.objects.all().order('-last_login')
- page = self.paginate_queryset(recent_users)
- serializer = self.get_pagination_serializer(page)
- return Response(serializer.data)
-</code></pre>
-<p>For more details, see the <a href="../api-guide/viewsets">viewsets documentation</a>.</p>
-<h2 id="throttle-behavior">Throttle behavior</h2>
-<p>There's one bugfix in 2.4 that's worth calling out, as it will <em>invalidate existing throttle caches</em> when you upgrade.</p>
-<p>We've now fixed a typo on the <code>cache_format</code> attribute. Previously this was named <code>"throtte_%(scope)s_%(ident)s"</code>, it is now <code>"throttle_%(scope)s_%(ident)s"</code>.</p>
-<p>If you're concerned about the invalidation you have two options.</p>
-<ul>
-<li>Manually pre-populate your cache with the fixed version.</li>
-<li>Set the <code>cache_format</code> attribute on your throttle class in order to retain the previous incorrect spelling.</li>
-</ul>
-<h2 id="other-features">Other features</h2>
-<p>There are also a number of other features and bugfixes as <a href="./topics/release-notes/#240">listed in the release notes</a>. In particular these include:</p>
-<p><a href="../api-guide/settings/#view-names-and-descriptions">Customizable view name and description functions</a> for use with the browsable API, by using the <code>VIEW_NAME_FUNCTION</code> and <code>VIEW_DESCRIPTION_FUNCTION</code> settings.</p>
-<p>Smarter <a href="../api-guide/throttling/#how-clients-are-identified">client IP identification for throttling</a>, with the addition of the <code>NUM_PROXIES</code> setting.</p>
-<p>Added the standardized <code>Retry-After</code> header to throttled responses, as per <a href="http://tools.ietf.org/html/rfc6585">RFC 6585</a>. This should now be used in preference to the custom <code>X-Trottle-Wait-Seconds</code> header which will be fully deprecated in 3.0.</p>
-<h2 id="deprecations">Deprecations</h2>
-<p>All API changes in 2.3 that previously raised <code>PendingDeprecationWarning</code> will now raise a <code>DeprecationWarning</code>, which is loud by default.</p>
-<p>All API changes in 2.3 that previously raised <code>DeprecationWarning</code> have now been removed entirely.</p>
-<p>Furter details on these deprecations is available in the <a href="./topics/2.3-announcement">2.3 announcement</a>.</p>
-<h2 id="labels-and-milestones">Labels and milestones</h2>
-<p>Although not strictly part of the 2.4 release it's also worth noting here that we've been working hard towards improving our triage process.</p>
-<p>The <a href="https://github.com/tomchristie/django-rest-framework/issues">labels that we use in GitHub</a> have been cleaned up, and all existing tickets triaged. Any given ticket should have one and only one label, indicating its current state.</p>
-<p>We've also <a href="https://github.com/tomchristie/django-rest-framework/milestones">started using milestones</a> in order to track tickets against particular releases.</p>
-<hr />
-<p><img alt="Labels and milestones" src="../img/labels-and-milestones.png" /></p>
-<p><strong>Above</strong>: <em>Overview of our current use of labels and milestones in GitHub.</em></p>
-<hr />
-<p>We hope both of these changes will help make the management process more clear and obvious and help keep tickets well-organised and relevant.</p>
-<h2 id="next-steps">Next steps</h2>
-<p>The next planned release will be 3.0, featuring an improved and simplified serializer implementation.</p>
-<p>Once again, many thanks to all the generous <a href="./topics/kickstarter-announcement/#sponsors">backers and sponsors</a> who've helped make this possible!</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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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.4-announcement.html b/topics/2.4-announcement.html
deleted file mode 100644
index 868f718c..00000000
--- a/topics/2.4-announcement.html
+++ /dev/null
@@ -1,355 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>REST framework 2.4 announcement - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/2.4-announcement"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, REST framework 2.4 announcement">
- <meta name="author" content="Tom Christie">
-
- <!-- Le styles -->
- <link href="http://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </head>
- <body onload="prettyPrint()" class="2.4-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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/2.3-announcement"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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-24-announcement">REST framework 2.4 announcement</a></li>
-<li><a href="#version-requirements">Version requirements</a></li>
-<li><a href="#django-17-support">Django 1.7 support</a></li>
-<li><a href="#deprecation-of-`model`-view-attribute">Deprecation of `.model` view attribute</a></li>
-<li><a href="#updated-test-runner">Updated test runner</a></li>
-<li><a href="#improved-viewset-routing">Improved viewset routing</a></li>
-<li><a href="#throttle-behavior">Throttle behavior</a></li>
-<li><a href="#other-features">Other features</a></li>
-<li><a href="#deprecations">Deprecations</a></li>
-<li><a href="#labels-and-milestones">Labels and milestones</a></li>
-<li><a href="#next-steps">Next steps</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <h1 id="rest-framework-24-announcement">REST framework 2.4 announcement</h1>
-<p>The 2.4 release is largely an intermediate step, tying up some outstanding issues prior to the 3.x series.</p>
-<h2 id="version-requirements">Version requirements</h2>
-<p>Support for Django 1.3 has been dropped.
-The lowest supported version of Django is now 1.4.2.</p>
-<p>The current plan is for REST framework to remain in lockstep with <a href="https://docs.djangoproject.com/en/dev/internals/release-process/#long-term-support-lts-releases">Django's long-term support policy</a>.</p>
-<h2 id="django-17-support">Django 1.7 support</h2>
-<p>The optional authtoken application now includes support for <em>both</em> Django 1.7 schema migrations, <em>and</em> for old-style <code>south</code> migrations.</p>
-<p><strong>If you are using authtoken, and you want to continue using <code>south</code>, you must upgrade your <code>south</code> package to version 1.0.</strong></p>
-<h2 id="deprecation-of-model-view-attribute">Deprecation of <code>.model</code> view attribute</h2>
-<p>The <code>.model</code> attribute on view classes is an optional shortcut for either or both of <code>.serializer_class</code> and <code>.queryset</code>. Its usage results in more implicit, less obvious behavior.</p>
-<p>The documentation has previously stated that usage of the more explicit style is prefered, and we're now taking that one step further and deprecating the usage of the <code>.model</code> shortcut.</p>
-<p>Doing so will mean that there are cases of API code where you'll now need to include a serializer class where you previously were just using the <code>.model</code> shortcut. However we firmly believe that it is the right trade-off to make.</p>
-<p>Removing the shortcut takes away an unneccessary layer of abstraction, and makes your codebase more explicit without any significant extra complexity. It also results in better consistency, as there's now only one way to set the serializer class and queryset attributes for the view, instead of two.</p>
-<p>The <code>DEFAULT_MODEL_SERIALIZER_CLASS</code> API setting is now also deprecated.</p>
-<h2 id="updated-test-runner">Updated test runner</h2>
-<p>We now have a new test runner for developing against the project,, that uses the excellent <a href="http://pytest.org">py.test</a> library.</p>
-<p>To use it make sure you have first installed the test requirements.</p>
-<pre class="prettyprint lang-py"><code>pip install -r requirements-test.txt
-</code></pre>
-<p>Then run the <code>runtests.py</code> script.</p>
-<pre class="prettyprint lang-py"><code>./runtests.py
-</code></pre>
-<p>The new test runner also includes <a href="https://flake8.readthedocs.org">flake8</a> code linting, which should help keep our coding style consistent.</p>
-<h4 id="test-runner-flags">Test runner flags</h4>
-<p>Run using a more concise output style.</p>
-<pre class="prettyprint lang-py"><code>./runtests -q
-</code></pre>
-<p>Run the tests using a more concise output style, no coverage, no flake8.</p>
-<pre class="prettyprint lang-py"><code>./runtests --fast
-</code></pre>
-<p>Don't run the flake8 code linting.</p>
-<pre class="prettyprint lang-py"><code>./runtests --nolint
-</code></pre>
-<p>Only run the flake8 code linting, don't run the tests.</p>
-<pre class="prettyprint lang-py"><code>./runtests --lintonly
-</code></pre>
-<p>Run the tests for a given test case.</p>
-<pre class="prettyprint lang-py"><code>./runtests MyTestCase
-</code></pre>
-<p>Run the tests for a given test method.</p>
-<pre class="prettyprint lang-py"><code>./runtests MyTestCase.test_this_method
-</code></pre>
-<p>Shorter form to run the tests for a given test method.</p>
-<pre class="prettyprint lang-py"><code>./runtests test_this_method
-</code></pre>
-<p>Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.</p>
-<h2 id="improved-viewset-routing">Improved viewset routing</h2>
-<p>The <code>@action</code> and <code>@link</code> decorators were inflexible in that they only allowed additional routes to be added against instance style URLs, not against list style URLs.</p>
-<p>The <code>@action</code> and <code>@link</code> decorators have now been moved to pending deprecation, and the <code>@list_route</code> and <code>@detail_route</code> decorators have been introduced.</p>
-<p>Here's an example of using the new decorators. Firstly we have a detail-type route named "set_password" that acts on a single instance, and takes a <code>pk</code> argument in the URL. Secondly we have a list-type route named "recent_users" that acts on a queryset, and does not take any arguments in the URL.</p>
-<pre class="prettyprint lang-py"><code>class UserViewSet(viewsets.ModelViewSet):
- """
- A viewset that provides the standard actions
- """
- queryset = User.objects.all()
- serializer_class = UserSerializer
-
- @detail_route(methods=['post'])
- def set_password(self, request, pk=None):
- user = self.get_object()
- serializer = PasswordSerializer(data=request.DATA)
- if serializer.is_valid():
- user.set_password(serializer.data['password'])
- user.save()
- return Response({'status': 'password set'})
- else:
- return Response(serializer.errors,
- status=status.HTTP_400_BAD_REQUEST)
-
- @list_route()
- def recent_users(self, request):
- recent_users = User.objects.all().order('-last_login')
- page = self.paginate_queryset(recent_users)
- serializer = self.get_pagination_serializer(page)
- return Response(serializer.data)
-</code></pre>
-<p>For more details, see the <a href="../api-guide/viewsets">viewsets documentation</a>.</p>
-<h2 id="throttle-behavior">Throttle behavior</h2>
-<p>There's one bugfix in 2.4 that's worth calling out, as it will <em>invalidate existing throttle caches</em> when you upgrade.</p>
-<p>We've now fixed a typo on the <code>cache_format</code> attribute. Previously this was named <code>"throtte_%(scope)s_%(ident)s"</code>, it is now <code>"throttle_%(scope)s_%(ident)s"</code>.</p>
-<p>If you're concerned about the invalidation you have two options.</p>
-<ul>
-<li>Manually pre-populate your cache with the fixed version.</li>
-<li>Set the <code>cache_format</code> attribute on your throttle class in order to retain the previous incorrect spelling.</li>
-</ul>
-<h2 id="other-features">Other features</h2>
-<p>There are also a number of other features and bugfixes as <a href="release-notes#240">listed in the release notes</a>. In particular these include:</p>
-<p><a href="../api-guide/settings#view-names-and-descriptions">Customizable view name and description functions</a> for use with the browsable API, by using the <code>VIEW_NAME_FUNCTION</code> and <code>VIEW_DESCRIPTION_FUNCTION</code> settings.</p>
-<p>Smarter <a href="../api-guide/throttling#how-clients-are-identified">client IP identification for throttling</a>, with the addition of the <code>NUM_PROXIES</code> setting.</p>
-<p>Added the standardized <code>Retry-After</code> header to throttled responses, as per <a href="http://tools.ietf.org/html/rfc6585">RFC 6585</a>. This should now be used in preference to the custom <code>X-Throttle-Wait-Seconds</code> header which will be fully deprecated in 3.0.</p>
-<h2 id="deprecations">Deprecations</h2>
-<p>All API changes in 2.3 that previously raised <code>PendingDeprecationWarning</code> will now raise a <code>DeprecationWarning</code>, which is loud by default.</p>
-<p>All API changes in 2.3 that previously raised <code>DeprecationWarning</code> have now been removed entirely.</p>
-<p>Furter details on these deprecations is available in the <a href="2.3-announcement">2.3 announcement</a>.</p>
-<h2 id="labels-and-milestones">Labels and milestones</h2>
-<p>Although not strictly part of the 2.4 release it's also worth noting here that we've been working hard towards improving our triage process.</p>
-<p>The <a href="https://github.com/tomchristie/django-rest-framework/issues">labels that we use in GitHub</a> have been cleaned up, and all existing tickets triaged. Any given ticket should have one and only one label, indicating its current state.</p>
-<p>We've also <a href="https://github.com/tomchristie/django-rest-framework/milestones">started using milestones</a> in order to track tickets against particular releases.</p>
-<hr />
-<p><img alt="Labels and milestones" src="../img/labels-and-milestones.png" /></p>
-<p><strong>Above</strong>: <em>Overview of our current use of labels and milestones in GitHub.</em></p>
-<hr />
-<p>We hope both of these changes will help make the management process more clear and obvious and help keep tickets well-organised and relevant.</p>
-<h2 id="next-steps">Next steps</h2>
-<p>The next planned release will be 3.0, featuring an improved and simplified serializer implementation.</p>
-<p>Once again, many thanks to all the generous <a href="kickstarter-announcement#sponsors">backers and sponsors</a> who've helped make this possible!</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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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.4-announcement/index.html b/topics/2.4-announcement/index.html
new file mode 100644
index 00000000..2b44bebe
--- /dev/null
+++ b/topics/2.4-announcement/index.html
@@ -0,0 +1,556 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>2.4 Announcement - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/2.4-announcement/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, 2.4 Announcement">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../kickstarter-announcement">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../2.3-announcement">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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-24-announcement">REST framework 2.4 announcement</a>
+ </li>
+
+
+ <li>
+ <a href="#version-requirements">Version requirements</a>
+ </li>
+
+ <li>
+ <a href="#django-17-support">Django 1.7 support</a>
+ </li>
+
+ <li>
+ <a href="#deprecation-of-model-view-attribute">Deprecation of .model view attribute</a>
+ </li>
+
+ <li>
+ <a href="#updated-test-runner">Updated test runner</a>
+ </li>
+
+ <li>
+ <a href="#improved-viewset-routing">Improved viewset routing</a>
+ </li>
+
+ <li>
+ <a href="#throttle-behavior">Throttle behavior</a>
+ </li>
+
+ <li>
+ <a href="#other-features">Other features</a>
+ </li>
+
+ <li>
+ <a href="#deprecations">Deprecations</a>
+ </li>
+
+ <li>
+ <a href="#labels-and-milestones">Labels and milestones</a>
+ </li>
+
+ <li>
+ <a href="#next-steps">Next steps</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <h1 id="rest-framework-24-announcement">REST framework 2.4 announcement</h1>
+<p>The 2.4 release is largely an intermediate step, tying up some outstanding issues prior to the 3.x series.</p>
+<h2 id="version-requirements">Version requirements</h2>
+<p>Support for Django 1.3 has been dropped.
+The lowest supported version of Django is now 1.4.2.</p>
+<p>The current plan is for REST framework to remain in lockstep with <a href="https://docs.djangoproject.com/en/dev/internals/release-process/#long-term-support-lts-releases">Django's long-term support policy</a>.</p>
+<h2 id="django-17-support">Django 1.7 support</h2>
+<p>The optional authtoken application now includes support for <em>both</em> Django 1.7 schema migrations, <em>and</em> for old-style <code>south</code> migrations.</p>
+<p><strong>If you are using authtoken, and you want to continue using <code>south</code>, you must upgrade your <code>south</code> package to version 1.0.</strong></p>
+<h2 id="deprecation-of-model-view-attribute">Deprecation of <code>.model</code> view attribute</h2>
+<p>The <code>.model</code> attribute on view classes is an optional shortcut for either or both of <code>.serializer_class</code> and <code>.queryset</code>. Its usage results in more implicit, less obvious behavior.</p>
+<p>The documentation has previously stated that usage of the more explicit style is prefered, and we're now taking that one step further and deprecating the usage of the <code>.model</code> shortcut.</p>
+<p>Doing so will mean that there are cases of API code where you'll now need to include a serializer class where you previously were just using the <code>.model</code> shortcut. However we firmly believe that it is the right trade-off to make.</p>
+<p>Removing the shortcut takes away an unnecessary layer of abstraction, and makes your codebase more explicit without any significant extra complexity. It also results in better consistency, as there's now only one way to set the serializer class and queryset attributes for the view, instead of two.</p>
+<p>The <code>DEFAULT_MODEL_SERIALIZER_CLASS</code> API setting is now also deprecated.</p>
+<h2 id="updated-test-runner">Updated test runner</h2>
+<p>We now have a new test runner for developing against the project,, that uses the excellent <a href="http://pytest.org">py.test</a> library.</p>
+<p>To use it make sure you have first installed the test requirements.</p>
+<pre><code>pip install -r requirements-test.txt
+</code></pre>
+<p>Then run the <code>runtests.py</code> script.</p>
+<pre><code>./runtests.py
+</code></pre>
+<p>The new test runner also includes <a href="https://flake8.readthedocs.org">flake8</a> code linting, which should help keep our coding style consistent.</p>
+<h4 id="test-runner-flags">Test runner flags</h4>
+<p>Run using a more concise output style.</p>
+<pre><code>./runtests -q
+</code></pre>
+<p>Run the tests using a more concise output style, no coverage, no flake8.</p>
+<pre><code>./runtests --fast
+</code></pre>
+<p>Don't run the flake8 code linting.</p>
+<pre><code>./runtests --nolint
+</code></pre>
+<p>Only run the flake8 code linting, don't run the tests.</p>
+<pre><code>./runtests --lintonly
+</code></pre>
+<p>Run the tests for a given test case.</p>
+<pre><code>./runtests MyTestCase
+</code></pre>
+<p>Run the tests for a given test method.</p>
+<pre><code>./runtests MyTestCase.test_this_method
+</code></pre>
+<p>Shorter form to run the tests for a given test method.</p>
+<pre><code>./runtests test_this_method
+</code></pre>
+<p>Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.</p>
+<h2 id="improved-viewset-routing">Improved viewset routing</h2>
+<p>The <code>@action</code> and <code>@link</code> decorators were inflexible in that they only allowed additional routes to be added against instance style URLs, not against list style URLs.</p>
+<p>The <code>@action</code> and <code>@link</code> decorators have now been moved to pending deprecation, and the <code>@list_route</code> and <code>@detail_route</code> decorators have been introduced.</p>
+<p>Here's an example of using the new decorators. Firstly we have a detail-type route named "set_password" that acts on a single instance, and takes a <code>pk</code> argument in the URL. Secondly we have a list-type route named "recent_users" that acts on a queryset, and does not take any arguments in the URL.</p>
+<pre><code>class UserViewSet(viewsets.ModelViewSet):
+ """
+ A viewset that provides the standard actions
+ """
+ queryset = User.objects.all()
+ serializer_class = UserSerializer
+
+ @detail_route(methods=['post'])
+ def set_password(self, request, pk=None):
+ user = self.get_object()
+ serializer = PasswordSerializer(data=request.DATA)
+ if serializer.is_valid():
+ user.set_password(serializer.data['password'])
+ user.save()
+ return Response({'status': 'password set'})
+ else:
+ return Response(serializer.errors,
+ status=status.HTTP_400_BAD_REQUEST)
+
+ @list_route()
+ def recent_users(self, request):
+ recent_users = User.objects.all().order('-last_login')
+ page = self.paginate_queryset(recent_users)
+ serializer = self.get_pagination_serializer(page)
+ return Response(serializer.data)
+</code></pre>
+<p>For more details, see the <a href="../../api-guide/viewsets">viewsets documentation</a>.</p>
+<h2 id="throttle-behavior">Throttle behavior</h2>
+<p>There's one bugfix in 2.4 that's worth calling out, as it will <em>invalidate existing throttle caches</em> when you upgrade.</p>
+<p>We've now fixed a typo on the <code>cache_format</code> attribute. Previously this was named <code>"throtte_%(scope)s_%(ident)s"</code>, it is now <code>"throttle_%(scope)s_%(ident)s"</code>.</p>
+<p>If you're concerned about the invalidation you have two options.</p>
+<ul>
+<li>Manually pre-populate your cache with the fixed version.</li>
+<li>Set the <code>cache_format</code> attribute on your throttle class in order to retain the previous incorrect spelling.</li>
+</ul>
+<h2 id="other-features">Other features</h2>
+<p>There are also a number of other features and bugfixes as <a href="../../release-notes#240">listed in the release notes</a>. In particular these include:</p>
+<p><a href="../../../api-guide/settings#view-names-and-descriptions">Customizable view name and description functions</a> for use with the browsable API, by using the <code>VIEW_NAME_FUNCTION</code> and <code>VIEW_DESCRIPTION_FUNCTION</code> settings.</p>
+<p>Smarter <a href="../../../api-guide/throttling#how-clients-are-identified">client IP identification for throttling</a>, with the addition of the <code>NUM_PROXIES</code> setting.</p>
+<p>Added the standardized <code>Retry-After</code> header to throttled responses, as per <a href="http://tools.ietf.org/html/rfc6585">RFC 6585</a>. This should now be used in preference to the custom <code>X-Throttle-Wait-Seconds</code> header which will be fully deprecated in 3.0.</p>
+<h2 id="deprecations">Deprecations</h2>
+<p>All API changes in 2.3 that previously raised <code>PendingDeprecationWarning</code> will now raise a <code>DeprecationWarning</code>, which is loud by default.</p>
+<p>All API changes in 2.3 that previously raised <code>DeprecationWarning</code> have now been removed entirely.</p>
+<p>Furter details on these deprecations is available in the <a href="../../2.3-announcement">2.3 announcement</a>.</p>
+<h2 id="labels-and-milestones">Labels and milestones</h2>
+<p>Although not strictly part of the 2.4 release it's also worth noting here that we've been working hard towards improving our triage process.</p>
+<p>The <a href="https://github.com/tomchristie/django-rest-framework/issues">labels that we use in GitHub</a> have been cleaned up, and all existing tickets triaged. Any given ticket should have one and only one label, indicating its current state.</p>
+<p>We've also <a href="https://github.com/tomchristie/django-rest-framework/milestones">started using milestones</a> in order to track tickets against particular releases.</p>
+<hr />
+<p><img alt="Labels and milestones" src="../../../img/labels-and-milestones.png" /></p>
+<p><strong>Above</strong>: <em>Overview of our current use of labels and milestones in GitHub.</em></p>
+<hr />
+<p>We hope both of these changes will help make the management process more clear and obvious and help keep tickets well-organised and relevant.</p>
+<h2 id="next-steps">Next steps</h2>
+<p>The next planned release will be 3.0, featuring an improved and simplified serializer implementation.</p>
+<p>Once again, many thanks to all the generous <a href="../../kickstarter-announcement#sponsors">backers and sponsors</a> who've helped make this possible!</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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/3.0-announcement.html b/topics/3.0-announcement.html
deleted file mode 100644
index 3ced0ce6..00000000
--- a/topics/3.0-announcement.html
+++ /dev/null
@@ -1,886 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Pre-release notes: - Django REST framework</title>
- <link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/3.0-announcement.html"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, REST framework 3.0">
- <meta name="author" content="Tom Christie">
-
- <!-- Le styles -->
- <link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//css/prettify.css" rel="stylesheet">
- <link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//css/bootstrap.css" rel="stylesheet">
- <link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//css/bootstrap-responsive.css" rel="stylesheet">
- <link href="file:///Users/tomchristie/GitHub/django-rest-framework/html//css/default.css" rel="stylesheet">
-
- <!-- 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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </head>
- <body onload="prettyPrint()" class="3.0-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 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="file:///Users/tomchristie/GitHub/django-rest-framework/html/index.html">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html/index.html">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/quickstart.html">Quickstart</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/1-serialization.html">1 - Serialization</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/2-requests-and-responses.html">2 - Requests and responses</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/3-class-based-views.html">3 - Class based views</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/4-authentication-and-permissions.html">4 - Authentication and permissions</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//tutorial/6-viewsets-and-routers.html">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/requests.html">Requests</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/responses.html">Responses</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/views.html">Views</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/generic-views.html">Generic views</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/viewsets.html">Viewsets</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/routers.html">Routers</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/parsers.html">Parsers</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/renderers.html">Renderers</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/serializers.html">Serializers</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/fields.html">Serializer fields</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/relations.html">Serializer relations</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/validators.html">Validators</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/authentication.html">Authentication</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/permissions.html">Permissions</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/throttling.html">Throttling</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/filtering.html">Filtering</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/pagination.html">Pagination</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/content-negotiation.html">Content negotiation</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/format-suffixes.html">Format suffixes</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/reverse.html">Returning URLs</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/exceptions.html">Exceptions</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/status-codes.html">Status codes</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/testing.html">Testing</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//api-guide/settings.html">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/documenting-your-api.html">Documenting your API</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/ajax-csrf-cors.html">AJAX, CSRF & CORS</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/browser-enhancements.html">Browser enhancements</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/browsable-api.html">The Browsable API</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/rest-hypermedia-hateoas.html">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/third-party-resources.html">Third Party Resources</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/contributing.html">Contributing to REST framework</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/rest-framework-2-announcement.html">2.0 Announcement</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/2.2-announcement.html">2.2 Announcement</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/2.3-announcement.html">2.3 Announcement</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/2.4-announcement.html">2.4 Announcement</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/kickstarter-announcement.html">Kickstarter Announcement</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/release-notes.html">Release Notes</a></li>
- <li><a href="file:///Users/tomchristie/GitHub/django-rest-framework/html//topics/credits.html">Credits</a></li>
- </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><a href="#pre-release-notes:">Pre-release notes:</a></li>
-<li class="main"><a href="#rest-framework-30">REST framework 3.0</a></li>
-<li><a href="#new-features">New features</a></li>
-<li><a href="#request-objects">Request objects</a></li>
-<li><a href="#serializers">Serializers</a></li>
-<li><a href="#serializer-fields">Serializer fields</a></li>
-<li><a href="#generic-views">Generic views</a></li>
-<li><a href="#the-metadata-api">The metadata API</a></li>
-<li><a href="#api-style">API style</a></li>
-<li><a href="#whats-coming-next">What's coming next.</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <h2 id="pre-release-notes">Pre-release notes:</h2>
-<p>The 3.0 release is now ready for some tentative testing and upgrades for super keen early adopters. You can install the development version directly from GitHub like so:</p>
-<pre class="prettyprint lang-py"><code>pip install https://github.com/tomchristie/django-rest-framework/archive/version-3.0.zip
-</code></pre>
-<p>See the <a href="https://github.com/tomchristie/django-rest-framework/pull/1800">Version 3.0 GitHub issue</a> for more details on remaining work.</p>
-<p>The most notable outstanding issues still to be resolved on the <code>version-3.0</code> branch are as follows:</p>
-<ul>
-<li>Finish forms support for serializers and in the browsable API.</li>
-<li>Optimisations for serializing primary keys.</li>
-<li>Refine style of validation errors in some cases, such as validation errors in <code>ListField</code>.</li>
-</ul>
-<p><strong>Your feedback on the upgrade process and 3.0 changes is hugely important!</strong></p>
-<p>Please do get in touch via twitter, IRC, a GitHub ticket, or the discussion group.</p>
-<hr />
-<h1 id="rest-framework-30">REST framework 3.0</h1>
-<p>The 3.0 release of Django REST framework is the result of almost four years of iteration and refinement. It comprehensively addresses some of the previous remaining design issues in serializers, fields and the generic views.</p>
-<p>This release is incremental in nature. There <em>are</em> some breaking API changes, and upgrading <em>will</em> require you to read the release notes carefully, but the migration path should otherwise be relatively straightforward.</p>
-<p>The difference in quality of the REST framework API and implementation should make writing, maintaining and debugging your application far easier.</p>
-<h2 id="new-features">New features</h2>
-<p>Notable features of this new release include:</p>
-<ul>
-<li>Printable representations on serializers that allow you to inspect exactly what fields are present on the instance.</li>
-<li>Simple model serializers that are vastly easier to understand and debug, and that make it easy to switch between the implicit <code>ModelSerializer</code> class and the explicit <code>Serializer</code> class.</li>
-<li>A new <code>BaseSerializer</code> class, making it easier to write serializers for alternative storage backends, or to completely customize your serialization and validation logic.</li>
-<li>A cleaner fields API plus new <code>ListField</code> and <code>MultipleChoiceField</code> classes.</li>
-<li>Super simple default implementations for the generic views.</li>
-<li>Support for overriding how validation errors are handled by your API.</li>
-<li>A metadata API that allows you to customize how <code>OPTIONS</code> requests are handled by your API.</li>
-<li>A more compact JSON output with unicode style encoding turned on by default.</li>
-</ul>
-<p>Below is an in-depth guide to the API changes and migration notes for 3.0.</p>
-<hr />
-<h2 id="request-objects">Request objects</h2>
-<h4 id="the-data-and-query_params-properties">The <code>.data</code> and <code>.query_params</code> properties.</h4>
-<p>The usage of <code>request.DATA</code> and <code>request.FILES</code> is now pending deprecation in favor of a single <code>request.data</code> attribute that contains <em>all</em> the parsed data.</p>
-<p>Having separate attributes is reasonable for web applications that only ever parse url-encoded or multipart requests, but makes less sense for the general-purpose request parsing that REST framework supports.</p>
-<p>You may now pass all the request data to a serializer class in a single argument:</p>
-<pre class="prettyprint lang-py"><code># Do this...
-ExampleSerializer(data=request.data)
-</code></pre>
-<p>Instead of passing the files argument separately:</p>
-<pre class="prettyprint lang-py"><code># Don't do this...
-ExampleSerializer(data=request.DATA, files=request.FILES)
-</code></pre>
-<p>The usage of <code>request.QUERY_PARAMS</code> is now pending deprecation in favor of the lowercased <code>request.query_params</code>.</p>
-<h2 id="serializers">Serializers</h2>
-<h4 id="single-step-object-creation">Single-step object creation.</h4>
-<p>Previously the serializers used a two-step object creation, as follows:</p>
-<ol>
-<li>Validating the data would create an object instance. This instance would be available as <code>serializer.object</code>.</li>
-<li>Calling <code>serializer.save()</code> would then save the object instance to the database.</li>
-</ol>
-<p>This style is in-line with how the <code>ModelForm</code> class works in Django, but is problematic for a number of reasons:</p>
-<ul>
-<li>Some data, such as many-to-many relationships, cannot be added to the object instance until after it has been saved. This type of data needed to be hidden in some undocumented state on the object instance, or kept as state on the serializer instance so that it could be used when <code>.save()</code> is called.</li>
-<li>Instantiating model instances directly means that you cannot use model manager classes for instance creation, eg <code>ExampleModel.objects.create(...)</code>. Manager classes are an excellent layer at which to enforce business logic and application-level data constraints.</li>
-<li>The two step process makes it unclear where to put deserialization logic. For example, should extra attributes such as the current user get added to the instance during object creation or during object save?</li>
-</ul>
-<p>We now use single-step object creation, like so:</p>
-<ol>
-<li>Validating the data makes the cleaned data available as <code>serializer.validated_data</code>.</li>
-<li>Calling <code>serializer.save()</code> then saves and returns the new object instance.</li>
-</ol>
-<p>The resulting API changes are further detailed below.</p>
-<h4 id="the-create-and-update-methods">The <code>.create()</code> and <code>.update()</code> methods.</h4>
-<p>The <code>.restore_object()</code> method is now replaced with two separate methods, <code>.create()</code> and <code>.update()</code>.</p>
-<p>When using the <code>.create()</code> and <code>.update()</code> methods you should both create <em>and save</em> the object instance. This is in contrast to the previous <code>.restore_object()</code> behavior that would instantiate the object but not save it.</p>
-<p>The following example from the tutorial previously used <code>restore_object()</code> to handle both creating and updating object instances.</p>
-<pre class="prettyprint lang-py"><code>def restore_object(self, attrs, instance=None):
- if instance:
- # Update existing instance
- instance.title = attrs.get('title', instance.title)
- instance.code = attrs.get('code', instance.code)
- instance.linenos = attrs.get('linenos', instance.linenos)
- instance.language = attrs.get('language', instance.language)
- instance.style = attrs.get('style', instance.style)
- return instance
-
- # Create new instance
- return Snippet(**attrs)
-</code></pre>
-<p>This would now be split out into two separate methods.</p>
-<pre class="prettyprint lang-py"><code>def update(self, instance, validated_data):
- instance.title = validated_data.get('title', instance.title)
- instance.code = validated_data.get('code', instance.code)
- instance.linenos = validated_data.get('linenos', instance.linenos)
- instance.language = validated_data.get('language', instance.language)
- instance.style = validated_data.get('style', instance.style)
- instance.save()
- return instance
-
-def create(self, validated_data):
- return Snippet.objects.create(**validated_data)
-</code></pre>
-<p>Note that these methods should return the newly created object instance.</p>
-<h4 id="use-validated_data-instead-of-object">Use <code>.validated_data</code> instead of <code>.object</code>.</h4>
-<p>You must now use the <code>.validated_data</code> attribute if you need to inspect the data before saving, rather than using the <code>.object</code> attribute, which no longer exists.</p>
-<p>For example the following code <em>is no longer valid</em>:</p>
-<pre class="prettyprint lang-py"><code>if serializer.is_valid():
- name = serializer.object.name # Inspect validated field data.
- logging.info('Creating ticket "%s"' % name)
- serializer.object.user = request.user # Include the user when saving.
- serializer.save()
-</code></pre>
-<p>Instead of using <code>.object</code> to inspect a partially constructed instance, you would now use <code>.validated_data</code> to inspect the cleaned incoming values. Also you can't set extra attributes on the instance directly, but instead pass them to the <code>.save()</code> method as keyword arguments.</p>
-<p>The corresponding code would now look like this:</p>
-<pre class="prettyprint lang-py"><code>if serializer.is_valid():
- name = serializer.validated_data['name'] # Inspect validated field data.
- logging.info('Creating ticket "%s"' % name)
- serializer.save(user=request.user) # Include the user when saving.
-</code></pre>
-<h4 id="using-serializersvalidationerror">Using <code>serializers.ValidationError</code>.</h4>
-<p>Previously <code>serializers.ValidationError</code> error was simply a synonym for <code>django.core.exceptions.ValidationError</code>. This has now been altered so that it inherits from the standard <code>APIException</code> base class.</p>
-<p>The reason behind this is that Django's <code>ValidationError</code> class is intended for use with HTML forms and its API makes using it slightly awkward with nested validation errors that can occur in serializers.</p>
-<p>For most users this change shouldn't require any updates to your codebase, but it is worth ensuring that whenever raising validation errors you are always using the <code>serializers.ValidationError</code> exception class, and not Django's built-in exception.</p>
-<p>We strongly recommend that you use the namespaced import style of <code>import serializers</code> and not <code>from serializers import ValidationError</code> in order to avoid any potential confusion.</p>
-<h4 id="change-to-validate_field_name">Change to <code>validate_&lt;field_name&gt;</code>.</h4>
-<p>The <code>validate_&lt;field_name&gt;</code> method hooks that can be attached to serializer classes change their signature slightly and return type. Previously these would take a dictionary of all incoming data, and a key representing the field name, and would return a dictionary including the validated data for that field:</p>
-<pre class="prettyprint lang-py"><code>def validate_score(self, attrs, source):
- if attrs[score] % 10 != 0:
- raise serializers.ValidationError('This field should be a multiple of ten.')
- return attrs
-</code></pre>
-<p>This is now simplified slightly, and the method hooks simply take the value to be validated, and return the validated value.</p>
-<pre class="prettyprint lang-py"><code>def validate_score(self, value):
- if value % 10 != 0:
- raise serializers.ValidationError('This field should be a multiple of ten.')
- return value
-</code></pre>
-<p>Any ad-hoc validation that applies to more than one field should go in the <code>.validate(self, attrs)</code> method as usual.</p>
-<p>Because <code>.validate_&lt;field_name&gt;</code> would previously accept the complete dictionary of attributes, it could be used to validate a field depending on the input in another field. Now if you need to do this you should use <code>.validate()</code> instead.</p>
-<p>You can either return <code>non_field_errors</code> from the validate method by raising a simple <code>ValidationError</code></p>
-<pre class="prettyprint lang-py"><code>def validate(self, attrs):
- # serializer.errors == {'non_field_errors': ['A non field error']}
- raise serailizers.ValidationError('A non field error')
-</code></pre>
-<p>Alternatively if you want the errors to be against a specific field, use a dictionary of when instantiating the <code>ValidationError</code>, like so:</p>
-<pre class="prettyprint lang-py"><code>def validate(self, attrs):
- # serializer.errors == {'my_field': ['A field error']}
- raise serailizers.ValidationError({'my_field': 'A field error'})
-</code></pre>
-<p>This ensures you can still write validation that compares all the input fields, but that marks the error against a particular field.</p>
-<h4 id="limitations-of-modelserializer-validation">Limitations of ModelSerializer validation.</h4>
-<p>This change also means that we no longer use the <code>.full_clean()</code> method on model instances, but instead perform all validation explicitly on the serializer. This gives a cleaner separation, and ensures that there's no automatic validation behavior on <code>ModelSerializer</code> classes that can't also be easily replicated on regular <code>Serializer</code> classes.</p>
-<p>This change comes with the following limitations:</p>
-<ul>
-<li>The model <code>.clean()</code> method will not be called as part of serializer validation. Use the serializer <code>.validate()</code> method to perform a final validation step on incoming data where required.</li>
-<li>The <code>.unique_for_date</code>, <code>.unique_for_month</code> and <code>.unique_for_year</code> options on model fields are not automatically validated. Again, you'll need to handle these explicitly on the serializer if required.</li>
-</ul>
-<h4 id="writable-nested-serialization">Writable nested serialization.</h4>
-<p>REST framework 2.x attempted to automatically support writable nested serialization, but the behavior was complex and non-obvious. Attempting to automatically handle these case is problematic:</p>
-<ul>
-<li>There can be complex dependencies involved in order of saving multiple related model instances.</li>
-<li>It's unclear what behavior the user should expect when related models are passed <code>None</code> data.</li>
-<li>It's unclear how the user should expect to-many relationships to handle updates, creations and deletions of multiple records.</li>
-</ul>
-<p>Using the <code>depth</code> option on <code>ModelSerializer</code> will now create <strong>read-only nested serializers</strong> by default.</p>
-<p>If you try to use a writable nested serializer without writing a custom <code>create()</code> and/or <code>update()</code> method you'll see an assertion error when you attempt to save the serializer. For example:</p>
-<pre class="prettyprint lang-py"><code>&gt;&gt;&gt; class ProfileSerializer(serializers.ModelSerializer):
-&gt;&gt;&gt; class Meta:
-&gt;&gt;&gt; model = Profile
-&gt;&gt;&gt; fields = ('address', 'phone')
-&gt;&gt;&gt;
-&gt;&gt;&gt; class UserSerializer(serializers.ModelSerializer):
-&gt;&gt;&gt; profile = ProfileSerializer()
-&gt;&gt;&gt; class Meta:
-&gt;&gt;&gt; model = User
-&gt;&gt;&gt; fields = ('username', 'email', 'profile')
-&gt;&gt;&gt;
-&gt;&gt;&gt; data = {
-&gt;&gt;&gt; 'username': 'lizzy',
-&gt;&gt;&gt; 'email': 'lizzy@example.com',
-&gt;&gt;&gt; 'profile': {'address': '123 Acacia Avenue', 'phone': '01273 100200'}
-&gt;&gt;&gt; }
-&gt;&gt;&gt;
-&gt;&gt;&gt; serializer = UserSerializer(data=data)
-&gt;&gt;&gt; serializer.save()
-AssertionError: The `.create()` method does not suport nested writable fields by default. Write an explicit `.create()` method for serializer `UserSerializer`, or set `read_only=True` on nested serializer fields.
-</code></pre>
-<p>To use writable nested serialization you'll want to declare a nested field on the serializer class, and write the <code>create()</code> and/or <code>update()</code> methods explicitly.</p>
-<pre class="prettyprint lang-py"><code>class UserSerializer(serializers.ModelSerializer):
- profile = ProfileSerializer()
-
- class Meta:
- model = User
- fields = ('username', 'email', 'profile')
-
- def create(self, validated_data):
- profile_data = validated_data.pop['profile']
- user = User.objects.create(**validated_data)
- Profile.objects.create(user=user, **profile_data)
- return user
-</code></pre>
-<p>The single-step object creation makes this far simpler and more obvious than the previous <code>.restore_object()</code> behavior.</p>
-<h4 id="printable-serializer-representations">Printable serializer representations.</h4>
-<p>Serializer instances now support a printable representation that allows you to inspect the fields present on the instance.</p>
-<p>For instance, given the following example model:</p>
-<pre class="prettyprint lang-py"><code>class LocationRating(models.Model):
- location = models.CharField(max_length=100)
- rating = models.IntegerField()
- created_by = models.ForeignKey(User)
-</code></pre>
-<p>Let's create a simple <code>ModelSerializer</code> class corresponding to the <code>LocationRating</code> model.</p>
-<pre class="prettyprint lang-py"><code>class LocationRatingSerializer(serializer.ModelSerializer):
- class Meta:
- model = LocationRating
-</code></pre>
-<p>We can now inspect the serializer representation in the Django shell, using <code>python manage.py shell</code>...</p>
-<pre class="prettyprint lang-py"><code>&gt;&gt;&gt; serializer = LocationRatingSerializer()
-&gt;&gt;&gt; print(serializer) # Or use `print serializer` in Python 2.x
-LocationRatingSerializer():
- id = IntegerField(label='ID', read_only=True)
- location = CharField(max_length=100)
- rating = IntegerField()
- created_by = PrimaryKeyRelatedField(queryset=User.objects.all())
-</code></pre>
-<h4 id="the-extra_kwargs-option">The <code>extra_kwargs</code> option.</h4>
-<p>The <code>write_only_fields</code> option on <code>ModelSerializer</code> has been moved to <code>PendingDeprecation</code> and replaced with a more generic <code>extra_kwargs</code>.</p>
-<pre class="prettyprint lang-py"><code>class MySerializer(serializer.ModelSerializer):
- class Meta:
- model = MyModel
- fields = ('id', 'email', 'notes', 'is_admin')
- extra_kwargs = {
- 'is_admin': {'write_only': True}
- }
-</code></pre>
-<p>Alternatively, specify the field explicitly on the serializer class:</p>
-<pre class="prettyprint lang-py"><code>class MySerializer(serializer.ModelSerializer):
- is_admin = serializers.BooleanField(write_only=True)
-
- class Meta:
- model = MyModel
- fields = ('id', 'email', 'notes', 'is_admin')
-</code></pre>
-<p>The <code>read_only_fields</code> option remains as a convenient shortcut for the more common case. </p>
-<h4 id="changes-to-hyperlinkedmodelserializer">Changes to <code>HyperlinkedModelSerializer</code>.</h4>
-<p>The <code>view_name</code> and <code>lookup_field</code> options have been moved to <code>PendingDeprecation</code>. They are no longer required, as you can use the <code>extra_kwargs</code> argument instead:</p>
-<pre class="prettyprint lang-py"><code>class MySerializer(serializer.HyperlinkedModelSerializer):
- class Meta:
- model = MyModel
- fields = ('url', 'email', 'notes', 'is_admin')
- extra_kwargs = {
- 'url': {'lookup_field': 'uuid'}
- }
-</code></pre>
-<p>Alternatively, specify the field explicitly on the serializer class:</p>
-<pre class="prettyprint lang-py"><code>class MySerializer(serializer.HyperlinkedModelSerializer):
- url = serializers.HyperlinkedIdentityField(
- view_name='mymodel-detail',
- lookup_field='uuid'
- )
-
- class Meta:
- model = MyModel
- fields = ('url', 'email', 'notes', 'is_admin')
-</code></pre>
-<h4 id="fields-for-model-methods-and-properties">Fields for model methods and properties.</h4>
-<p>With <code>ModelSerilizer</code> you can now specify field names in the <code>fields</code> option that refer to model methods or properties. For example, suppose you have the following model:</p>
-<pre class="prettyprint lang-py"><code>class Invitation(models.Model):
- created = models.DateTimeField()
- to_email = models.EmailField()
- message = models.CharField(max_length=1000)
-
- def expiry_date(self):
- return self.created + datetime.timedelta(days=30)
-</code></pre>
-<p>You can include <code>expiry_date</code> as a field option on a <code>ModelSerializer</code> class.</p>
-<pre class="prettyprint lang-py"><code>class InvitationSerializer(serializers.ModelSerializer):
- class Meta:
- model = Invitation
- fields = ('to_email', 'message', 'expiry_date')
-</code></pre>
-<p>These fields will be mapped to <code>serializers.ReadOnlyField()</code> instances.</p>
-<pre class="prettyprint lang-py"><code>&gt;&gt;&gt; serializer = InvitationSerializer()
-&gt;&gt;&gt; print repr(serializer)
-InvitationSerializer():
- to_email = EmailField(max_length=75)
- message = CharField(max_length=1000)
- expiry_date = ReadOnlyField()
-</code></pre>
-<h4 id="the-listserializer-class">The <code>ListSerializer</code> class.</h4>
-<p>The <code>ListSerializer</code> class has now been added, and allows you to create base serializer classes for only accepting multiple inputs.</p>
-<pre class="prettyprint lang-py"><code>class MultipleUserSerializer(ListSerializer):
- child = UserSerializer()
-</code></pre>
-<p>You can also still use the <code>many=True</code> argument to serializer classes. It's worth noting that <code>many=True</code> argument transparently creates a <code>ListSerializer</code> instance, allowing the validation logic for list and non-list data to be cleanly separated in the REST framework codebase. </p>
-<p>See also the new <code>ListField</code> class, which validates input in the same way, but does not include the serializer interfaces of <code>.is_valid()</code>, <code>.data</code>, <code>.save()</code> and so on.</p>
-<h4 id="the-baseserializer-class">The <code>BaseSerializer</code> class.</h4>
-<p>REST framework now includes a simple <code>BaseSerializer</code> class that can be used to easily support alternative serialization and deserialization styles.</p>
-<p>This class implements the same basic API as the <code>Serializer</code> class:</p>
-<ul>
-<li><code>.data</code> - Returns the outgoing primitive representation.</li>
-<li><code>.is_valid()</code> - Deserializes and validates incoming data.</li>
-<li><code>.validated_data</code> - Returns the validated incoming data.</li>
-<li><code>.errors</code> - Returns an errors during validation.</li>
-<li><code>.save()</code> - Persists the validated data into an object instance.</li>
-</ul>
-<p>There are four mathods that can be overriding, depending on what functionality you want the serializer class to support:</p>
-<ul>
-<li><code>.to_representation()</code> - Override this to support serialization, for read operations.</li>
-<li><code>.to_internal_value()</code> - Override this to support deserialization, for write operations.</li>
-<li><code>.create()</code> and <code>.update()</code> - Overide either or both of these to support saving instances.</li>
-</ul>
-<h5 id="read-only-baseserializer-classes">Read-only <code>BaseSerializer</code> classes.</h5>
-<p>To implement a read-only serializer using the <code>BaseSerializer</code> class, we just need to override the <code>.to_representation()</code> method. Let's take a look at an example using a simple Django model:</p>
-<pre class="prettyprint lang-py"><code>class HighScore(models.Model):
- created = models.DateTimeField(auto_now_add=True)
- player_name = models.CharField(max_length=10)
- score = models.IntegerField()
-</code></pre>
-<p>It's simple to create a read-only serializer for converting <code>HighScore</code> instances into primitive data types.</p>
-<pre class="prettyprint lang-py"><code>class HighScoreSerializer(serializers.BaseSerializer):
- def to_representation(self, obj):
- return {
- 'score': obj.score,
- 'player_name': obj.player_name
- }
-</code></pre>
-<p>We can now use this class to serialize single <code>HighScore</code> instances:</p>
-<pre class="prettyprint lang-py"><code>@api_view(['GET'])
-def high_score(request, pk):
- instance = HighScore.objects.get(pk=pk)
- serializer = HighScoreSerializer(instance)
- return Response(serializer.data)
-</code></pre>
-<p>Or use it to serialize multiple instances:</p>
-<pre class="prettyprint lang-py"><code>@api_view(['GET'])
-def all_high_scores(request):
- queryset = HighScore.objects.order_by('-score')
- serializer = HighScoreSerializer(queryset, many=True)
- return Response(serializer.data)
-</code></pre>
-<h5 id="read-write-baseserializer-classes">Read-write <code>BaseSerializer</code> classes.</h5>
-<p>To create a read-write serializer we first need to implement a <code>.to_internal_value()</code> method. This method returns the validated values that will be used to construct the object instance, and may raise a <code>ValidationError</code> if the supplied data is in an incorrect format.</p>
-<p>Once you've implemented <code>.to_internal_value()</code>, the basic validation API will be available on the serializer, and you will be able to use <code>.is_valid()</code>, <code>.validated_data</code> and <code>.errors</code>.</p>
-<p>If you want to also support <code>.save()</code> you'll need to also implement either or both of the <code>.create()</code> and <code>.update()</code> methods.</p>
-<p>Here's a complete example of our previous <code>HighScoreSerializer</code>, that's been updated to support both read and write operations.</p>
-<pre class="prettyprint lang-py"><code>class HighScoreSerializer(serializers.BaseSerializer):
- def to_internal_value(self, data):
- score = data.get('score')
- player_name = data.get('player_name')
-
- # Perform the data validation.
- if not score:
- raise ValidationError({
- 'score': 'This field is required.'
- })
- if not player_name:
- raise ValidationError({
- 'player_name': 'This field is required.'
- })
- if len(player_name) &gt; 10:
- raise ValidationError({
- 'player_name': 'May not be more than 10 characters.'
- })
-
- # Return the validated values. This will be available as
- # the `.validated_data` property.
- return {
- 'score': int(score),
- 'player_name': player_name
- }
-
- def to_representation(self, obj):
- return {
- 'score': obj.score,
- 'player_name': obj.player_name
- }
-
- def create(self, validated_data):
- return HighScore.objects.create(**validated_data)
-</code></pre>
-<h4 id="creating-new-generic-serializers-with-baseserializer">Creating new generic serializers with <code>BaseSerializer</code>.</h4>
-<p>The <code>BaseSerializer</code> class is also useful if you want to implement new generic serializer classes for dealing with particular serialization styles, or for integrating with alternative storage backends.</p>
-<p>The following class is an example of a generic serializer that can handle coercing aribitrary objects into primitive representations. </p>
-<pre class="prettyprint lang-py"><code>class ObjectSerializer(serializers.BaseSerializer):
- """
- A read-only serializer that coerces arbitrary complex objects
- into primitive representations.
- """
- def to_representation(self, obj):
- for attribute_name in dir(obj):
- attribute = getattr(obj, attribute_name)
- if attribute_name('_'):
- # Ignore private attributes.
- pass
- elif hasattr(attribute, '__call__'):
- # Ignore methods and other callables.
- pass
- elif isinstance(attribute, (str, int, bool, float, type(None))):
- # Primitive types can be passed through unmodified.
- output[attribute_name] = attribute
- elif isinstance(attribute, list):
- # Recursivly deal with items in lists.
- output[attribute_name] = [
- self.to_representation(item) for item in attribute
- ]
- elif isinstance(attribute, dict):
- # Recursivly deal with items in dictionarys.
- output[attribute_name] = {
- str(key): self.to_representation(value)
- for key, value in attribute.items()
- }
- else:
- # Force anything else to its string representation.
- output[attribute_name] = str(attribute)
-</code></pre>
-<h2 id="serializer-fields">Serializer fields</h2>
-<h4 id="the-field-and-readonly-field-classes">The <code>Field</code> and <code>ReadOnly</code> field classes.</h4>
-<p>There are some minor tweaks to the field base classes.</p>
-<p>Previously we had these two base classes:</p>
-<ul>
-<li><code>Field</code> as the base class for read-only fields. A default implementation was included for serializing data.</li>
-<li><code>WritableField</code> as the base class for read-write fields.</li>
-</ul>
-<p>We now use the following:</p>
-<ul>
-<li><code>Field</code> is the base class for all fields. It does not include any default implementation for either serializing or deserializing data.</li>
-<li><code>ReadOnlyField</code> is a concrete implementation for read-only fields that simply returns the attribute value without modification.</li>
-</ul>
-<h4 id="the-required-allow_none-allow_blank-and-default-arguments">The <code>required</code>, <code>allow_none</code>, <code>allow_blank</code> and <code>default</code> arguments.</h4>
-<p>REST framework now has more explicit and clear control over validating empty values for fields.</p>
-<p>Previously the meaning of the <code>required=False</code> keyword argument was underspecified. In practice its use meant that a field could either be not included in the input, or it could be included, but be <code>None</code>.</p>
-<p>We now have a better separation, with separate <code>required</code> and <code>allow_none</code> arguments.</p>
-<p>The following set of arguments are used to control validation of empty values:</p>
-<ul>
-<li><code>required=False</code>: The value does not need to be present in the input, and will not be passed to <code>.create()</code> or <code>.update()</code> if it is not seen.</li>
-<li><code>default=&lt;value&gt;</code>: The value does not need to be present in the input, and a default value will be passed to <code>.create()</code> or <code>.update()</code> if it is not seen.</li>
-<li><code>allow_none=True</code>: <code>None</code> is a valid input.</li>
-<li><code>allow_blank=True</code>: <code>''</code> is valid input. For <code>CharField</code> and subclasses only.</li>
-</ul>
-<p>Typically you'll want to use <code>required=False</code> if the corresponding model field has a default value, and additionally set either <code>allow_none=True</code> or <code>allow_blank=True</code> if required.</p>
-<p>The <code>default</code> argument is there if you need it, but you'll more typically want defaults to be set on model fields, rather than serializer fields.</p>
-<h4 id="coercing-output-types">Coercing output types.</h4>
-<p>The previous field implementations did not forcibly coerce returned values into the correct type in many cases. For example, an <code>IntegerField</code> would return a string output if the attribute value was a string. We now more strictly coerce to the correct return type, leading to more constrained and expected behavior. </p>
-<h4 id="the-listfield-class">The <code>ListField</code> class.</h4>
-<p>The <code>ListField</code> class has now been added. This field validates list input. It takes a <code>child</code> keyword argument which is used to specify the field used to validate each item in the list. For example:</p>
-<pre class="prettyprint lang-py"><code>scores = ListField(child=IntegerField(min_value=0, max_value=100))
-</code></pre>
-<p>You can also use a declarative style to create new subclasses of <code>ListField</code>, like this:</p>
-<pre class="prettyprint lang-py"><code>class ScoresField(ListField):
- child = IntegerField(min_value=0, max_value=100)
-</code></pre>
-<p>We can now use the <code>ScoresField</code> class inside another serializer:</p>
-<pre class="prettyprint lang-py"><code>scores = ScoresField()
-</code></pre>
-<p>See also the new <code>ListSerializer</code> class, which validates input in the same way, but also includes the serializer interfaces of <code>.is_valid()</code>, <code>.data</code>, <code>.save()</code> and so on.</p>
-<h4 id="the-choicefield-class-may-now-accept-a-flat-list">The <code>ChoiceField</code> class may now accept a flat list.</h4>
-<p>The <code>ChoiceField</code> class may now accept a list of choices in addition to the existing style of using a list of pairs of <code>(name, display_value)</code>. The following is now valid:</p>
-<pre class="prettyprint lang-py"><code>color = ChoiceField(choices=['red', 'green', 'blue'])
-</code></pre>
-<h4 id="the-multiplechoicefield-class">The <code>MultipleChoiceField</code> class.</h4>
-<p>The <code>MultipleChoiceField</code> class has been added. This field acts like <code>ChoiceField</code>, but returns a set, which may include none, one or many of the valid choices.</p>
-<h4 id="changes-to-the-custom-field-api">Changes to the custom field API.</h4>
-<p>The <code>from_native(self, value)</code> and <code>to_native(self, data)</code> method names have been replaced with the more obviously named <code>to_internal_value(self, data)</code> and <code>to_representation(self, value)</code>.</p>
-<p>The <code>field_from_native()</code> and <code>field_to_native()</code> methods are removed.</p>
-<h4 id="explicit-queryset-required-on-relational-fields">Explicit <code>queryset</code> required on relational fields.</h4>
-<p>Previously relational fields that were explicitly declared on a serializer class could omit the queryset argument if (and only if) they were declared on a <code>ModelSerializer</code>.</p>
-<p>This code <em>would be valid</em> in <code>2.4.3</code>:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.ModelSerializer):
- organisations = serializers.SlugRelatedField(slug_field='name')
-
- class Meta:
- model = Account
-</code></pre>
-<p>However this code <em>would not be valid</em> in <code>2.4.3</code>:</p>
-<pre class="prettyprint lang-py"><code># Missing `queryset`
-class AccountSerializer(serializers.Serializer):
- organisations = serializers.SlugRelatedField(slug_field='name')
-
- def restore_object(self, attrs, instance=None):
- # ...
-</code></pre>
-<p>The queryset argument is now always required for writable relational fields.
-This removes some magic and makes it easier and more obvious to move between implicit <code>ModelSerializer</code> classes and explicit <code>Serializer</code> classes.</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.ModelSerializer):
- organisations = serializers.SlugRelatedField(
- slug_field='name',
- queryset=Organisation.objects.all()
- )
-
- class Meta:
- model = Account
-</code></pre>
-<p>The <code>queryset</code> argument is only ever required for writable fields, and is not required or valid for fields with <code>read_only=True</code>.</p>
-<h4 id="optional-argument-to-serializermethodfield">Optional argument to <code>SerializerMethodField</code>.</h4>
-<p>The argument to <code>SerializerMethodField</code> is now optional, and defaults to <code>get_&lt;field_name&gt;</code>. For example the following is valid:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.Serializer):
- # `method_name='get_billing_details'` by default.
- billing_details = serializers.SerializerMethodField()
-
- def get_billing_details(self, account):
- return calculate_billing(account)
-</code></pre>
-<p>In order to ensure a consistent code style an assertion error will be raised if you include a redundant method name argument that matches the default method name. For example, the following code <em>will raise an error</em>:</p>
-<pre class="prettyprint lang-py"><code>billing_details = serializers.SerializerMethodField('get_billing_details')
-</code></pre>
-<h4 id="enforcing-consistent-source-usage">Enforcing consistent <code>source</code> usage.</h4>
-<p>I've see several codebases that unnecessarily include the <code>source</code> argument, setting it to the same value as the field name. This usage is redundant and confusing, making it less obvious that <code>source</code> is usually not required.</p>
-<p>The following usage will <em>now raise an error</em>:</p>
-<pre class="prettyprint lang-py"><code>email = serializers.EmailField(source='email')
-</code></pre>
-<h4 id="the-uniquevalidator-and-uniquetogethervalidator-classes">The <code>UniqueValidator</code> and <code>UniqueTogetherValidator</code> classes.</h4>
-<p>REST framework now provides two new validators that allow you to ensure field uniqueness, while still using a completely explicit <code>Serializer</code> class instead of using <code>ModelSerializer</code>.</p>
-<p>The <code>UniqueValidator</code> should be applied to a serializer field, and takes a single <code>queryset</code> argument.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import serializers
-from rest_framework.validators import UniqueValidator
-
-class OrganizationSerializer(serializers.Serializer):
- url = serializers.HyperlinkedIdentityField(view_name='organisation_detail')
- created = serializers.DateTimeField(read_only=True)
- name = serializers.CharField(
- max_length=100,
- validators=UniqueValidator(queryset=Organisation.objects.all())
- )
-</code></pre>
-<p>The <code>UniqueTogetherValidator</code> should be applied to a serializer, and takes a <code>queryset</code> argument and a <code>fields</code> argument which should be a list or tuple of field names.</p>
-<pre class="prettyprint lang-py"><code>class RaceResultSerializer(serializers.Serializer):
- category = serializers.ChoiceField(['5k', '10k'])
- position = serializers.IntegerField()
- name = serializers.CharField(max_length=100)
-
- default_validators = [UniqueTogetherValidator(
- queryset=RaceResult.objects.all(),
- fields=('category', 'position')
- )]
-</code></pre>
-<h2 id="generic-views">Generic views</h2>
-<h4 id="simplification-of-view-logic">Simplification of view logic.</h4>
-<p>The view logic for the default method handlers has been significantly simplified, due to the new serializers API.</p>
-<h4 id="changes-to-prepost-save-hooks">Changes to pre/post save hooks.</h4>
-<p>The <code>pre_save</code> and <code>post_save</code> hooks no longer exist, but are replaced with <code>perform_create(self, serializer)</code> and <code>perform_update(self, serializer)</code>.</p>
-<p>These methods should save the object instance by calling <code>serializer.save()</code>, adding in any additional arguments as required. They may also perform any custom pre-save or post-save behavior.</p>
-<p>For example:</p>
-<pre class="prettyprint lang-py"><code>def perform_create(self, serializer):
- # Include the owner attribute directly, rather than from request data.
- instance = serializer.save(owner=self.request.user)
- # Perform a custom post-save action.
- send_email(instance.to_email, instance.message)
-</code></pre>
-<p>The <code>pre_delete</code> and <code>post_delete</code> hooks no longer exist, and are replaced with <code>.perform_destroy(self, instance)</code>, which should delete the instance and perform any custom actions.</p>
-<pre class="prettyprint lang-py"><code>def perform_destroy(self, instance):
- # Perform a custom pre-delete action.
- send_deletion_alert(user=instance.created_by, deleted=instance)
- # Delete the object instance.
- instance.delete()
-</code></pre>
-<h4 id="removal-of-view-attributes">Removal of view attributes.</h4>
-<p>The <code>.object</code> and <code>.object_list</code> attributes are no longer set on the view instance. Treating views as mutable object instances that store state during the processing of the view tends to be poor design, and can lead to obscure flow logic.</p>
-<p>I would personally recommend that developers treat view instances as immutable objects in their application code.</p>
-<h4 id="put-as-create">PUT as create.</h4>
-<p>Allowing <code>PUT</code> as create operations is problematic, as it necessarily exposes information about the existence or non-existance of objects. It's also not obvious that transparently allowing re-creating of previously deleted instances is necessarily a better default behavior than simply returning <code>404</code> responses.</p>
-<p>Both styles "<code>PUT</code> as 404" and "<code>PUT</code> as create" can be valid in different circumstances, but we've now opted for the 404 behavior as the default, due to it being simpler and more obvious.</p>
-<p>If you need to restore the previous behavior you can include the <code>AllowPUTAsCreateMixin</code> class in your view. This class can be imported from <code>rest_framework.mixins</code>.</p>
-<h4 id="customizing-error-responses">Customizing error responses.</h4>
-<p>The generic views now raise <code>ValidationFailed</code> exception for invalid data. This exception is then dealt with by the exception handler, rather than the view returning a <code>400 Bad Request</code> response directly.</p>
-<p>This change means that you can now easily customize the style of error responses across your entire API, without having to modify any of the generic views.</p>
-<h2 id="the-metadata-api">The metadata API</h2>
-<p>Behavior for dealing with <code>OPTIONS</code> requests was previously built directly into the class based views. This has now been properly separated out into a Metadata API that allows the same pluggable style as other API policies in REST framework.</p>
-<p>This makes it far easier to use a different style for <code>OPTIONS</code> responses throughout your API, and makes it possible to create third-party metadata policies.</p>
-<h2 id="api-style">API style</h2>
-<p>There are some improvements in the default style we use in our API responses.</p>
-<h4 id="unicode-json-by-default">Unicode JSON by default.</h4>
-<p>Unicode JSON is now the default. The <code>UnicodeJSONRenderer</code> class no longer exists, and the <code>UNICODE_JSON</code> setting has been added. To revert this behavior use the new setting:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'UNICODE_JSON': False
-}
-</code></pre>
-<h4 id="compact-json-by-default">Compact JSON by default.</h4>
-<p>We now output compact JSON in responses by default. For example, we return:</p>
-<pre class="prettyprint lang-py"><code>{"email":"amy@example.com","is_admin":true}
-</code></pre>
-<p>Instead of the following:</p>
-<pre class="prettyprint lang-py"><code>{"email": "amy@example.com", "is_admin": true}
-</code></pre>
-<p>The <code>COMPACT_JSON</code> setting has been added, and can be used to revert this behavior if needed:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'COMPACT_JSON': False
-}
-</code></pre>
-<h4 id="file-fields-as-urls">File fields as URLs</h4>
-<p>The <code>FileField</code> and <code>ImageField</code> classes are now represented as URLs by default. You should ensure you set Django's <a href="https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-MEDIA_URL">standard <code>MEDIA_URL</code> setting</a> appropriately, and ensure your application <a href="https://docs.djangoproject.com/en/dev/howto/static-files/#serving-uploaded-files-in-development">serves the uploaded files</a>.</p>
-<p>You can revert this behavior, and display filenames in the representation by using the <code>UPLOADED_FILES_USE_URL</code> settings key:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'UPLOADED_FILES_USE_URL': False
-}
-</code></pre>
-<p>You can also modify serializer fields individually, using the <code>use_url</code> argument:</p>
-<pre class="prettyprint lang-py"><code>uploaded_file = serializers.FileField(user_url=False)
-</code></pre>
-<p>Also note that you should pass the <code>request</code> object to the serializer as context when instantiating it, so that a fully qualified URL can be returned. Returned URLs will then be of the form <code>https://example.com/url_path/filename.txt</code>. For example:</p>
-<pre class="prettyprint lang-py"><code>context = {'request': request}
-serializer = ExampleSerializer(instance, context=context)
-return Response(serializer.data)
-</code></pre>
-<p>If the request is omitted from the context, the returned URLs will be of the form <code>/url_path/filename.txt</code>.</p>
-<h4 id="throttle-headers-using-retry-after">Throttle headers using <code>Retry-After</code>.</h4>
-<p>The custom <code>X-Throttle-Wait-Second</code> header has now been dropped in favor of the standard <code>Retry-After</code> header. You can revert this behavior if needed by writing a custom exception handler for your application.</p>
-<h4 id="date-and-time-objects-as-iso-8859-1-strings-in-serializer-data">Date and time objects as ISO-8859-1 strings in serializer data.</h4>
-<p>Date and Time objects are now coerced to strings by default in the serializer output. Previously they were returned as <code>Date</code>, <code>Time</code> and <code>DateTime</code> objects, and later coerced to strings by the renderer.</p>
-<p>You can modify this behavior globally by settings the existing <code>DATE_FORMAT</code>, <code>DATETIME_FORMAT</code> and <code>TIME_FORMAT</code> settings keys. Setting these values to <code>None</code> instead of their default value of <code>'iso-8859-1'</code> will result in native objects being returned in serializer data.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- # Return native `Date` and `Time` objects in `serializer.data`
- 'DATETIME_FORMAT': None
- 'DATE_FORMAT': None
- 'TIME_FORMAT': None
-}
-</code></pre>
-<p>You can also modify serializer fields individually, using the <code>date_format</code>, <code>time_format</code> and <code>datetime_format</code> arguments:</p>
-<pre class="prettyprint lang-py"><code># Return `DateTime` instances in `serializer.data`, not strings.
-created = serializers.DateTimeField(format=None)
-</code></pre>
-<h4 id="decimals-as-strings-in-serializer-data">Decimals as strings in serializer data.</h4>
-<p>Decimals are now coerced to strings by default in the serializer output. Previously they were returned as <code>Decimal</code> objects, and later coerced to strings by the renderer.</p>
-<p>You can modify this behavior globally by using the <code>COERCE_DECIMAL_TO_STRING</code> settings key.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'COERCE_DECIMAL_TO_STRING': False
-}
-</code></pre>
-<p>Or modify it on an individual serializer field, using the <code>corece_to_string</code> keyword argument.</p>
-<pre class="prettyprint lang-py"><code># Return `Decimal` instances in `serializer.data`, not strings.
-amount = serializers.DecimalField(
- max_digits=10,
- decimal_places=2,
- coerce_to_string=False
-)
-</code></pre>
-<p>The default JSON renderer will return float objects for uncoerced <code>Decimal</code> instances. This allows you to easily switch between string or float representations for decimals depending on your API design needs.</p>
-<h2 id="whats-coming-next">What's coming next.</h2>
-<p>3.0 is an incremental release, and there are several upcoming features that will build on the baseline improvements that it makes.</p>
-<p>The 3.1 release is planned to address improvements in the following components:</p>
-<ul>
-<li>Request parsing, mediatypes &amp; the implementation of the browsable API.</li>
-<li>Introduction of a new pagination API.</li>
-<li>Better support for API versioning.</li>
-</ul>
-<p>The 3.2 release is planned to introduce an alternative admin-style interface to the browsable API.</p>
-<p>You can follow development on the GitHub site, where we use <a href="https://github.com/tomchristie/django-rest-framework/milestones">milestones to indicate planning timescales</a>.</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="file:///Users/tomchristie/GitHub/django-rest-framework/html//js/jquery-1.8.1-min.js"></script>
- <script src="file:///Users/tomchristie/GitHub/django-rest-framework/html//js/prettify-1.0.js"></script>
- <script src="file:///Users/tomchristie/GitHub/django-rest-framework/html//js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.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
deleted file mode 100644
index 85fb3ba8..00000000
--- a/topics/ajax-csrf-cors.html
+++ /dev/null
@@ -1,263 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Working with AJAX, CSRF & CORS - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/ajax-csrf-cors"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/documenting-your-api"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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 class="promo">
-
- </div>
-</ul>
-
- </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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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/index.html b/topics/ajax-csrf-cors/index.html
new file mode 100644
index 00000000..c7771456
--- /dev/null
+++ b/topics/ajax-csrf-cors/index.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>AJAX, CSRF & CORS - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/ajax-csrf-cors/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, AJAX, CSRF & CORS">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../browser-enhancements">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../documenting-your-api">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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 &amp; 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>
+
+
+
+
+
+
+ </ul>
+
+ </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/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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/browsable-api.html b/topics/browsable-api.html
deleted file mode 100644
index be0a07db..00000000
--- a/topics/browsable-api.html
+++ /dev/null
@@ -1,358 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>The Browsable API - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/browsable-api"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/browser-enhancements"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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 class="promo">
-
- </div>
-</ul>
-
- </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"><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://getbootstrap.com/2.3.2/customize.html">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>body</code> - The entire html <code>&lt;body&gt;</code>.</li>
-<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://getbootstrap.com/2.3.2/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://getbootstrap.com/2.3.2/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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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/index.html b/topics/browsable-api/index.html
new file mode 100644
index 00000000..b56b6426
--- /dev/null
+++ b/topics/browsable-api/index.html
@@ -0,0 +1,538 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>The Browsable API - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/browsable-api/" />
+ <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="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../rest-hypermedia-hateoas">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../browser-enhancements">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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>
+
+
+
+
+
+
+ </ul>
+
+ </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"><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><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><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://getbootstrap.com/2.3.2/customize.html">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><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>body</code> - The entire html <code>&lt;body&gt;</code>.</li>
+<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://getbootstrap.com/2.3.2/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://getbootstrap.com/2.3.2/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><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><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><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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/browser-enhancements.html b/topics/browser-enhancements.html
deleted file mode 100644
index 6453c5e9..00000000
--- a/topics/browser-enhancements.html
+++ /dev/null
@@ -1,297 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Browser enhancements - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/browser-enhancements"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/ajax-csrf-cors"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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 class="promo">
-
- </div>
-</ul>
-
- </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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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/index.html b/topics/browser-enhancements/index.html
new file mode 100644
index 00000000..399c1d27
--- /dev/null
+++ b/topics/browser-enhancements/index.html
@@ -0,0 +1,486 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Browser enhancements - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/browser-enhancements/" />
+ <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="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../browsable-api">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../ajax-csrf-cors">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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>
+
+
+
+
+
+
+ </ul>
+
+ </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><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><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><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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/contributing.html b/topics/contributing.html
deleted file mode 100644
index 85d9736d..00000000
--- a/topics/contributing.html
+++ /dev/null
@@ -1,399 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Contributing to REST framework - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/contributing"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Contributing to REST framework, Issues, Development, Documentation, Third party packages">
- <meta name="author" content="Tom Christie">
-
- <!-- Le styles -->
- <link href="http://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/third-party-resources"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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><a href="#community">Community</a></li>
-<li><a href="#code-of-conduct">Code of conduct</a></li>
-<li class="main"><a href="#issues">Issues</a></li>
-<li><a href="#triaging-issues">Triaging issues</a></li>
-<li class="main"><a href="#development">Development</a></li>
-<li><a href="#testing">Testing</a></li>
-<li><a href="#pull-requests">Pull requests</a></li>
-<li><a href="#managing-compatibility-issues">Managing compatibility issues</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><a href="#getting-started">Getting started</a></li>
-<li><a href="#linking-to-your-package">Linking to your package</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </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>
-<h2 id="community">Community</h2>
-<p>The most important thing you can do to help push the REST framework project forward is to be actively involved wherever possible. Code contributions are often overvalued as being the primary way to get involved in a project, we don't believe that needs to be the case.</p>
-<p>If you use REST framework, we'd love you to be vocal about your experiences with it - you might consider writing a blog post about using REST framework, or publishing a tutorial about building a project with a particular Javascript framework. Experiences from beginners can be particularly helpful because you'll be in the best position to assess which bits of REST framework are more difficult to understand and work with.</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>
-<h2 id="code-of-conduct">Code of conduct</h2>
-<p>Please keep the tone polite &amp; professional. For some users a discussion on the REST framework mailing list or ticket tracker may be their first engagement with the open source community. First impressions count, so let's try to make everyone feel welcome.</p>
-<p>Be mindful in the language you choose. As an example, in an environment that is heavily male-dominated, posts that start 'Hey guys,' can come across as unintentionally exclusive. It's just as easy, and more inclusive to use gender neutral language in those situations.</p>
-<p>The <a href="https://www.djangoproject.com/conduct/">Django code of conduct</a> gives a fuller set of guidelines for participating in community forums.</p>
-<h1 id="issues">Issues</h1>
-<p>It's really helpful if you can make sure to address issues on 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>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.</li>
-<li>Feature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintainence overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation.</li>
-<li>Closing an issue doesn't necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we'll consider if it needs to be reopened.</li>
-</ul>
-<h2 id="triaging-issues">Triaging issues</h2>
-<p>Getting involved in triaging incoming issues is a good way to start contributing. Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be. Anyone can help out with this, you just need to be willing to</p>
-<ul>
-<li>Read through the ticket - does it make sense, is it missing any context that would help explain it better?</li>
-<li>Is the ticket reported in the correct place, would it be better suited as a discussion on the discussion group?</li>
-<li>If the ticket is a bug report, can you reproduce it? Are you able to write a failing test case that demonstrates the issue and that can be submitted as a pull request?</li>
-<li>If the ticket is a feature request, do you agree with it, and could the feature request instead be implemented as a third party package?</li>
-<li>If a ticket hasn't had much activity and it addresses something you need, then comment on the ticket and try to find out what's needed to get it moving again.</li>
-</ul>
-<h1 id="development">Development</h1>
-<p>To start developing on Django REST framework, clone the repo:</p>
-<pre class="prettyprint lang-py"><code>git clone git@github.com:tomchristie/django-rest-framework.git
-</code></pre>
-<p>Changes should broadly follow the <a href="http://www.python.org/dev/peps/pep-0008/">PEP 8</a> style conventions, and we recommend you setup your editor to automatically indicated non-conforming styles.</p>
-<h2 id="testing">Testing</h2>
-<p>To run the tests, clone the repository, and then:</p>
-<pre class="prettyprint lang-py"><code># Setup the virtual environment
-virtualenv env
-source env/bin/activate
-pip install -r requirements.txt
-pip install -r requirements-test.txt
-
-# Run the tests
-./runtests.py
-</code></pre>
-<h3 id="test-options">Test options</h3>
-<p>Run using a more concise output style.</p>
-<pre class="prettyprint lang-py"><code>./runtests -q
-</code></pre>
-<p>Run the tests using a more concise output style, no coverage, no flake8.</p>
-<pre class="prettyprint lang-py"><code>./runtests --fast
-</code></pre>
-<p>Don't run the flake8 code linting.</p>
-<pre class="prettyprint lang-py"><code>./runtests --nolint
-</code></pre>
-<p>Only run the flake8 code linting, don't run the tests.</p>
-<pre class="prettyprint lang-py"><code>./runtests --lintonly
-</code></pre>
-<p>Run the tests for a given test case.</p>
-<pre class="prettyprint lang-py"><code>./runtests MyTestCase
-</code></pre>
-<p>Run the tests for a given test method.</p>
-<pre class="prettyprint lang-py"><code>./runtests MyTestCase.test_this_method
-</code></pre>
-<p>Shorter form to run the tests for a given test method.</p>
-<pre class="prettyprint lang-py"><code>./runtests test_this_method
-</code></pre>
-<p>Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.</p>
-<h3 id="running-against-multiple-environments">Running against multiple environments</h3>
-<p>You can also use the excellent <a href="http://tox.readthedocs.org/en/latest/">tox</a> testing tool to run the tests against all supported versions of Python and Django. Install <code>tox</code> globally, and then simply run:</p>
-<pre class="prettyprint lang-py"><code>tox
-</code></pre>
-<h2 id="pull-requests">Pull requests</h2>
-<p>It's a good idea to make pull requests early on. A pull request represents the start of a discussion, and doesn't necessarily need to be the final, finished submission.</p>
-<p>It's also always best to make a new branch before starting work on a pull request. This means that you'll be able to later switch back to working on another seperate issue without interfering with an ongoing pull requests.</p>
-<p>It's also useful to remember that if you have an outstanding pull request then pushing new commits to your GitHub repo will also automatically update the pull requests.</p>
-<p>GitHub's documentation for working on pull requests is <a href="https://help.github.com/articles/using-pull-requests">available here</a>.</p>
-<p>Always run the tests before submitting pull requests, and ideally run <code>tox</code> in order to check that your modifications are compatible with both Python 2 and Python 3, and that they run properly on all supported versions of Django.</p>
-<p>Once you've made a pull request take a look at the travis build status in the GitHub interface and make sure the tests are runnning as you'd expect.</p>
-<p><img alt="Travis status" src="../img/travis-status.png" /></p>
-<p><em>Above: Travis build notifications</em></p>
-<h2 id="managing-compatibility-issues">Managing compatibility issues</h2>
-<p>Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into the <code>compat.py</code> module, and should provide a single common interface that the rest of the codebase can use.</p>
-<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:** A useful documentation note.
-
----
-</code></pre>
-<h1 id="third-party-packages">Third party packages</h1>
-<p>New features to REST framework are generally recommended to be implemented as third party libraries that are developed outside of the core framework. Ideally third party libraries should be properly documented and packaged, and made available on PyPI.</p>
-<h2 id="getting-started">Getting started</h2>
-<p>If you have some functionality that you would like to implement as a third party package it's worth contacting the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">discussion group</a> as others may be willing to get involved. We strongly encourage third party package development and will always try to prioritize time spent helping their development, documentation and packaging.</p>
-<p>We recommend the <a href="https://github.com/dabapps/django-reusable-app"><code>django-reusable-app</code></a> template as a good resource for getting up and running with implementing a third party Django package.</p>
-<h2 id="linking-to-your-package">Linking to your package</h2>
-<p>Once your package is decently documented and available on PyPI open a pull request or issue, and we'll add a link to it from the main REST framework documentation. You can add your package under <strong>Third party packages</strong> of the API Guide section that best applies, like <a href="../api-guide/authentication">Authentication</a> or <a href="../api-guide/permissions">Permissions</a>. You can also link your package under the <a href="third-party-resources">Third Party Resources</a> section.</p>
-<p>We also suggest adding it to the <a href="https://www.djangopackages.com/grids/g/django-rest-framework/">REST Framework</a> grid on Django Packages.</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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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/index.html b/topics/contributing/index.html
new file mode 100644
index 00000000..0445597a
--- /dev/null
+++ b/topics/contributing/index.html
@@ -0,0 +1,631 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Contributing to REST framework - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/contributing/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Contributing to REST framework">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../rest-framework-2-announcement">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../third-party-resources">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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>
+ <a href="#community">Community</a>
+ </li>
+
+ <li>
+ <a href="#code-of-conduct">Code of conduct</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#issues">Issues</a>
+ </li>
+
+
+ <li>
+ <a href="#triaging-issues">Triaging issues</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#development">Development</a>
+ </li>
+
+
+ <li>
+ <a href="#testing">Testing</a>
+ </li>
+
+ <li>
+ <a href="#pull-requests">Pull requests</a>
+ </li>
+
+ <li>
+ <a href="#managing-compatibility-issues">Managing compatibility issues</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>
+ <a href="#getting-started">Getting started</a>
+ </li>
+
+ <li>
+ <a href="#linking-to-your-package">Linking to your package</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </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>
+<h2 id="community">Community</h2>
+<p>The most important thing you can do to help push the REST framework project forward is to be actively involved wherever possible. Code contributions are often overvalued as being the primary way to get involved in a project, we don't believe that needs to be the case.</p>
+<p>If you use REST framework, we'd love you to be vocal about your experiences with it - you might consider writing a blog post about using REST framework, or publishing a tutorial about building a project with a particular JavaScript framework. Experiences from beginners can be particularly helpful because you'll be in the best position to assess which bits of REST framework are more difficult to understand and work with.</p>
+<p>Other really great ways you can help move the community forward include helping to 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>
+<h2 id="code-of-conduct">Code of conduct</h2>
+<p>Please keep the tone polite &amp; professional. For some users a discussion on the REST framework mailing list or ticket tracker may be their first engagement with the open source community. First impressions count, so let's try to make everyone feel welcome.</p>
+<p>Be mindful in the language you choose. As an example, in an environment that is heavily male-dominated, posts that start 'Hey guys,' can come across as unintentionally exclusive. It's just as easy, and more inclusive to use gender neutral language in those situations.</p>
+<p>The <a href="https://www.djangoproject.com/conduct/">Django code of conduct</a> gives a fuller set of guidelines for participating in community forums.</p>
+<h1 id="issues">Issues</h1>
+<p>It's really helpful if you can make sure to address issues on 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>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.</li>
+<li>Feature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation.</li>
+<li>Closing an issue doesn't necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we'll consider if it needs to be reopened.</li>
+</ul>
+<h2 id="triaging-issues">Triaging issues</h2>
+<p>Getting involved in triaging incoming issues is a good way to start contributing. Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be. Anyone can help out with this, you just need to be willing to</p>
+<ul>
+<li>Read through the ticket - does it make sense, is it missing any context that would help explain it better?</li>
+<li>Is the ticket reported in the correct place, would it be better suited as a discussion on the discussion group?</li>
+<li>If the ticket is a bug report, can you reproduce it? Are you able to write a failing test case that demonstrates the issue and that can be submitted as a pull request?</li>
+<li>If the ticket is a feature request, do you agree with it, and could the feature request instead be implemented as a third party package?</li>
+<li>If a ticket hasn't had much activity and it addresses something you need, then comment on the ticket and try to find out what's needed to get it moving again.</li>
+</ul>
+<h1 id="development">Development</h1>
+<p>To start developing on Django REST framework, clone the repo:</p>
+<pre><code>git clone git@github.com:tomchristie/django-rest-framework.git
+</code></pre>
+<p>Changes should broadly follow the <a href="http://www.python.org/dev/peps/pep-0008/">PEP 8</a> style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.</p>
+<h2 id="testing">Testing</h2>
+<p>To run the tests, clone the repository, and then:</p>
+<pre><code># Setup the virtual environment
+virtualenv env
+source env/bin/activate
+pip install -r requirements.txt
+pip install -r requirements-test.txt
+
+# Run the tests
+./runtests.py
+</code></pre>
+<h3 id="test-options">Test options</h3>
+<p>Run using a more concise output style.</p>
+<pre><code>./runtests.py -q
+</code></pre>
+<p>Run the tests using a more concise output style, no coverage, no flake8.</p>
+<pre><code>./runtests.py --fast
+</code></pre>
+<p>Don't run the flake8 code linting.</p>
+<pre><code>./runtests.py --nolint
+</code></pre>
+<p>Only run the flake8 code linting, don't run the tests.</p>
+<pre><code>./runtests.py --lintonly
+</code></pre>
+<p>Run the tests for a given test case.</p>
+<pre><code>./runtests.py MyTestCase
+</code></pre>
+<p>Run the tests for a given test method.</p>
+<pre><code>./runtests.py MyTestCase.test_this_method
+</code></pre>
+<p>Shorter form to run the tests for a given test method.</p>
+<pre><code>./runtests.py test_this_method
+</code></pre>
+<p>Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.</p>
+<h3 id="running-against-multiple-environments">Running against multiple environments</h3>
+<p>You can also use the excellent <a href="http://tox.readthedocs.org/en/latest/">tox</a> testing tool to run the tests against all supported versions of Python and Django. Install <code>tox</code> globally, and then simply run:</p>
+<pre><code>tox
+</code></pre>
+<h2 id="pull-requests">Pull requests</h2>
+<p>It's a good idea to make pull requests early on. A pull request represents the start of a discussion, and doesn't necessarily need to be the final, finished submission.</p>
+<p>It's also always best to make a new branch before starting work on a pull request. This means that you'll be able to later switch back to working on another separate issue without interfering with an ongoing pull requests.</p>
+<p>It's also useful to remember that if you have an outstanding pull request then pushing new commits to your GitHub repo will also automatically update the pull requests.</p>
+<p>GitHub's documentation for working on pull requests is <a href="https://help.github.com/articles/using-pull-requests">available here</a>.</p>
+<p>Always run the tests before submitting pull requests, and ideally run <code>tox</code> in order to check that your modifications are compatible with both Python 2 and Python 3, and that they run properly on all supported versions of Django.</p>
+<p>Once you've made a pull request take a look at the Travis build status in the GitHub interface and make sure the tests are running as you'd expect.</p>
+<p><img alt="Travis status" src="../../../img/travis-status.png" /></p>
+<p><em>Above: Travis build notifications</em></p>
+<h2 id="managing-compatibility-issues">Managing compatibility issues</h2>
+<p>Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into the <code>compat.py</code> module, and should provide a single common interface that the rest of the codebase can use.</p>
+<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, install MkDocs with <code>pip install mkdocs</code> and then run the following command.</p>
+<pre><code>mkdocs build
+</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>serve</code> command.</p>
+<pre><code>mkdocs serve
+</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 abbreviations such as 'e.g.' but instead use the 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><code>### Some important topic
+</code></pre>
+<p>The underline style should not be used. <strong>Don't do this:</strong></p>
+<pre><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><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><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><code>---
+
+**Note:** A useful documentation note.
+
+---
+</code></pre>
+<h1 id="third-party-packages">Third party packages</h1>
+<p>New features to REST framework are generally recommended to be implemented as third party libraries that are developed outside of the core framework. Ideally third party libraries should be properly documented and packaged, and made available on PyPI.</p>
+<h2 id="getting-started">Getting started</h2>
+<p>If you have some functionality that you would like to implement as a third party package it's worth contacting the <a href="https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework">discussion group</a> as others may be willing to get involved. We strongly encourage third party package development and will always try to prioritize time spent helping their development, documentation and packaging.</p>
+<p>We recommend the <a href="https://github.com/dabapps/django-reusable-app"><code>django-reusable-app</code></a> template as a good resource for getting up and running with implementing a third party Django package.</p>
+<h2 id="linking-to-your-package">Linking to your package</h2>
+<p>Once your package is decently documented and available on PyPI open a pull request or issue, and we'll add a link to it from the main REST framework documentation. You can add your package under <strong>Third party packages</strong> of the API Guide section that best applies, like <a href="../../api-guide/authentication">Authentication</a> or <a href="../../api-guide/permissions">Permissions</a>. You can also link your package under the <a href="../third-party-resources">Third Party Resources</a> section.</p>
+<p>We also suggest adding it to the <a href="https://www.djangopackages.com/grids/g/django-rest-framework/">REST Framework</a> grid on Django Packages.</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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/credits.html b/topics/credits/index.html
index cd27da06..6be66631 100644
--- a/topics/credits.html
+++ b/topics/credits/index.html
@@ -1,65 +1,74 @@
<!DOCTYPE html>
<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Credits - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/credits"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </head>
- <body onload="prettyPrint()" class="credits-page">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Credits - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/credits/" />
+ <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="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-page">
<div class="wrapper">
- <div class="navbar navbar-inverse navbar-fixed-top">
+ <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"><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="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" rel="prev" >
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../release-notes">
+ <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>
@@ -67,80 +76,218 @@ a.fusion-poweredby {
</a>
<a class="brand" href="http://www.django-rest-framework.org">Django REST framework</a>
<div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
+
+ <li >
+ <a href="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
</ul>
</li>
+
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
</ul>
</li>
- <li class="dropdown">
+
+ <li class="dropdown active">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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>
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Credits</a>
+ </li>
+
</ul>
</li>
- -->
+
+
</ul>
- </div><!--/.nav-collapse -->
+
+ </div>
+ <!--/.nav-collapse -->
+
</div>
</div>
</div>
@@ -148,32 +295,34 @@ a.fusion-poweredby {
<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>
+ <!-- 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">
@@ -186,19 +335,37 @@ a.fusion-poweredby {
-->
<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 class="promo">
-
- </div>
-</ul>
+
+
+
+
+ <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>
+
+
+
+
+
+
+ </ul>
</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>
@@ -395,42 +562,52 @@ a.fusion-poweredby {
<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 -->
+ </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>
+ <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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- var shiftWindow = function() { scrollBy(0, -50) };
- if (location.hash) shiftWindow();
- window.addEventListener("hashchange", shiftWindow);
-
- $('.dropdown-menu').on('click touchstart', function(event) {
- event.stopPropagation();
- });
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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);
- // Dynamically force sidenav to no higher than browser window
- $('.side-nav').css('max-height', window.innerHeight - 130);
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
- $(function(){
- $(window).resize(function(){
- $('.side-nav').css('max-height', window.innerHeight - 130);
- });
+ // 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>
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/topics/documenting-your-api.html b/topics/documenting-your-api.html
deleted file mode 100644
index b0e81486..00000000
--- a/topics/documenting-your-api.html
+++ /dev/null
@@ -1,302 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Documenting your API - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/documenting-your-api"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/settings"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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 class="promo">
-
- </div>
-</ul>
-
- </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 that 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">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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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/index.html b/topics/documenting-your-api/index.html
new file mode 100644
index 00000000..cca66649
--- /dev/null
+++ b/topics/documenting-your-api/index.html
@@ -0,0 +1,482 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Documenting your API - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/documenting-your-api/" />
+ <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="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../ajax-csrf-cors">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../../api-guide/settings">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li class="active" >
+ <a href=".">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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>
+
+
+
+
+
+
+ </ul>
+
+ </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><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><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 that 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">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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/kickstarter-announcement.html b/topics/kickstarter-announcement/index.html
index 5022f1e0..90857a24 100644
--- a/topics/kickstarter-announcement.html
+++ b/topics/kickstarter-announcement/index.html
@@ -1,65 +1,74 @@
<!DOCTYPE html>
<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Kickstarting Django REST framework 3 - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/kickstarter-announcement"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Kickstarting Django REST framework 3">
- <meta name="author" content="Tom Christie">
-
- <!-- Le styles -->
- <link href="http://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </head>
- <body onload="prettyPrint()" class="kickstarter-announcement-page">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Kickstarter Announcement - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/kickstarter-announcement/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Kickstarter Announcement">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-page">
<div class="wrapper">
- <div class="navbar navbar-inverse navbar-fixed-top">
+ <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="repo-link btn btn-primary btn-small" href="https://github.com/tomchristie/django-rest-framework/tree/master">GitHub</a>
+ <a class="repo-link btn btn-inverse btn-small " rel="prev" href="../release-notes">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../2.4-announcement">
+ <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>
@@ -67,80 +76,218 @@ a.fusion-poweredby {
</a>
<a class="brand" href="http://www.django-rest-framework.org">Django REST framework</a>
<div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
+
+ <li >
+ <a href="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
</ul>
</li>
+
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
</ul>
</li>
- <li class="dropdown">
+
+ <li class="dropdown active">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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>
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</a>
+ </li>
+
</ul>
</li>
- -->
+
+
</ul>
- </div><!--/.nav-collapse -->
+
+ </div>
+ <!--/.nav-collapse -->
+
</div>
</div>
</div>
@@ -148,32 +295,34 @@ a.fusion-poweredby {
<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>
+ <!-- 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">
@@ -186,19 +335,37 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#kickstarting-django-rest-framework-3">Kickstarting Django REST framework 3</a></li>
-<li><a href="#project-details">Project details</a></li>
-<li><a href="#sponsors">Sponsors</a></li>
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+ <li class="main">
+ <a href="#kickstarting-django-rest-framework-3">Kickstarting Django REST framework 3</a>
+ </li>
+
+
+ <li>
+ <a href="#project-details">Project details</a>
+ </li>
+
+ <li>
+ <a href="#sponsors">Sponsors</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
+
+
<h1 id="kickstarting-django-rest-framework-3">Kickstarting Django REST framework 3</h1>
<hr />
<iframe width="480" height="360" src="https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3/widget/video.html" frameborder="0" scrolling="no"> </iframe>
@@ -332,42 +499,52 @@ a.fusion-poweredby {
<hr />
<h3 id="supporters">Supporters</h3>
<p>There were also almost 300 further individuals choosing to help fund the project at other levels or choosing to give anonymously. Again, thank you, thank you, thank you!</p>
- </div><!--/span-->
- </div><!--/row-->
- </div><!--/.fluid-container-->
- </div><!--/.body content-->
- <div id="push"></div>
- </div><!--/.wrapper -->
+ </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>
+ <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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- var shiftWindow = function() { scrollBy(0, -50) };
- if (location.hash) shiftWindow();
- window.addEventListener("hashchange", shiftWindow);
-
- $('.dropdown-menu').on('click touchstart', function(event) {
- event.stopPropagation();
- });
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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);
- // Dynamically force sidenav to no higher than browser window
- $('.side-nav').css('max-height', window.innerHeight - 130);
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
- $(function(){
- $(window).resize(function(){
- $('.side-nav').css('max-height', window.innerHeight - 130);
- });
+ // 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>
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/topics/release-notes.html b/topics/release-notes/index.html
index d3c6a059..e3b8b596 100644
--- a/topics/release-notes.html
+++ b/topics/release-notes/index.html
@@ -1,65 +1,74 @@
<!DOCTYPE html>
<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Release Notes - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/release-notes"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </head>
- <body onload="prettyPrint()" class="release-notes-page">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Release Notes - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/release-notes/" />
+ <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="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-page">
<div class="wrapper">
- <div class="navbar navbar-inverse navbar-fixed-top">
+ <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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/2.4-announcement"><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="repo-link btn btn-primary btn-small" href="https://github.com/tomchristie/django-rest-framework/tree/master">GitHub</a>
+ <a class="repo-link btn btn-inverse btn-small " rel="prev" href="../credits">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../kickstarter-announcement">
+ <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>
@@ -67,80 +76,218 @@ a.fusion-poweredby {
</a>
<a class="brand" href="http://www.django-rest-framework.org">Django REST framework</a>
<div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
+
+ <li >
+ <a href="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
</ul>
</li>
+
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
</ul>
</li>
- <li class="dropdown">
+
+ <li class="dropdown active">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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>
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</a>
+ </li>
+
</ul>
</li>
- -->
+
+
</ul>
- </div><!--/.nav-collapse -->
+
+ </div>
+ <!--/.nav-collapse -->
+
</div>
</div>
</div>
@@ -148,32 +295,34 @@ a.fusion-poweredby {
<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>
+ <!-- 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">
@@ -186,29 +335,77 @@ a.fusion-poweredby {
-->
<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="#24x-series">2.4.x series</a></li>
-<li><a href="#23x-series">2.3.x series</a></li>
-<li><a href="#22x-series">2.2.x series</a></li>
-<li><a href="#21x-series">2.1.x series</a></li>
-<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 class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <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="#24x-series">2.4.x series</a>
+ </li>
+
+ <li>
+ <a href="#23x-series">2.3.x series</a>
+ </li>
+
+ <li>
+ <a href="#22x-series">2.2.x series</a>
+ </li>
+
+ <li>
+ <a href="#21x-series">2.1.x series</a>
+ </li>
+
+ <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>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
+
+
<h1 id="release-notes">Release Notes</h1>
<blockquote>
<p>Release Early, Release Often</p>
@@ -235,10 +432,10 @@ a.fusion-poweredby {
<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
+<pre><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
+<pre><code>pip freeze | grep djangorestframework
</code></pre>
<hr />
<h2 id="24x-series">2.4.x series</h2>
@@ -263,7 +460,7 @@ a.fusion-poweredby {
<li>Bugfix: Fix migration in <code>authtoken</code> application.</li>
<li>Bugfix: Allow selection of integer keys in nested choices.</li>
<li>Bugfix: Return <code>None</code> instead of <code>'None'</code> in <code>CharField</code> with <code>allow_none=True</code>.</li>
-<li>Bugfix: Ensure custom model fields map to equivelent serializer fields more reliably. </li>
+<li>Bugfix: Ensure custom model fields map to equivelent serializer fields more reliably.</li>
<li>Bugfix: <code>DjangoFilterBackend</code> no longer quietly changes queryset ordering.</li>
</ul>
<h3 id="242">2.4.2</h3>
@@ -348,7 +545,7 @@ a.fusion-poweredby {
<li>Added <code>write_only_fields</code> option to <code>ModelSerializer</code> classes.</li>
<li>JSON renderer now deals with objects that implement a dict-like interface.</li>
<li>Fix compatiblity with newer versions of <code>django-oauth-plus</code>.</li>
-<li>Bugfix: Refine behavior that calls model manager <code>all()</code> across nested serializer relationships, preventing erronous behavior with some non-ORM objects, and preventing unneccessary queryset re-evaluations.</li>
+<li>Bugfix: Refine behavior that calls model manager <code>all()</code> across nested serializer relationships, preventing erronous behavior with some non-ORM objects, and preventing unnecessary queryset re-evaluations.</li>
<li>Bugfix: Allow defaults on BooleanFields to be properly honored when values are not supplied.</li>
<li>Bugfix: Prevent double-escaping of non-latin1 URL query params when appending <code>format=json</code> params.</li>
</ul>
@@ -395,7 +592,7 @@ a.fusion-poweredby {
</ul>
<hr />
<p>[*] Note that the change in <code>page_size=0</code> behaviour fixes what is considered to be a bug in how clients can effect the pagination size. However if you were relying on this behavior you will need to add the following mixin to your list views in order to preserve the existing behavior.</p>
-<pre class="prettyprint lang-py"><code>class DisablePaginationMixin(object):
+<pre><code>class DisablePaginationMixin(object):
def get_paginate_by(self, queryset=None):
if self.request.QUERY_PARAMS[self.paginate_by_param] == '0':
return None
@@ -486,7 +683,7 @@ a.fusion-poweredby {
<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">2.3 announcement</a> for full details.</p>
+<p><strong>Note</strong>: See the <a href="../2.3-announcement">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>
@@ -571,7 +768,7 @@ a.fusion-poweredby {
<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">2.2 announcement</a> for full details.</p>
+<p><strong>Note</strong>: See the <a href="../2.2-announcement">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>
@@ -741,7 +938,7 @@ a.fusion-poweredby {
<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">2.0 announcement</a>.</li>
+<li>For more information please see the <a href="../rest-framework-2-announcement">2.0 announcement</a>.</li>
</ul>
<hr />
<h2 id="04x-series">0.4.x series</h2>
@@ -861,42 +1058,52 @@ a.fusion-poweredby {
<ul>
<li>Initial release.</li>
</ul>
- </div><!--/span-->
- </div><!--/row-->
- </div><!--/.fluid-container-->
- </div><!--/.body content-->
- <div id="push"></div>
- </div><!--/.wrapper -->
+ </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>
+ <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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- var shiftWindow = function() { scrollBy(0, -50) };
- if (location.hash) shiftWindow();
- window.addEventListener("hashchange", shiftWindow);
-
- $('.dropdown-menu').on('click touchstart', function(event) {
- event.stopPropagation();
- });
+ <!-- Le javascript
+ ================================================== -->
+ <!-- Placed at the end of the document so the pages load faster -->
+ <script src="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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);
- // Dynamically force sidenav to no higher than browser window
- $('.side-nav').css('max-height', window.innerHeight - 130);
+ $('.dropdown-menu').on('click touchstart', function(event) {
+ event.stopPropagation();
+ });
- $(function(){
- $(window).resize(function(){
- $('.side-nav').css('max-height', window.innerHeight - 130);
- });
+ // 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>
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/topics/rest-framework-2-announcement.html b/topics/rest-framework-2-announcement.html
deleted file mode 100644
index 6ebab79b..00000000
--- a/topics/rest-framework-2-announcement.html
+++ /dev/null
@@ -1,298 +0,0 @@
-<!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 2 - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/contributing"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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 class="promo">
-
- </div>
-</ul>
-
- </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">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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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/index.html b/topics/rest-framework-2-announcement/index.html
new file mode 100644
index 00000000..011715d3
--- /dev/null
+++ b/topics/rest-framework-2-announcement/index.html
@@ -0,0 +1,493 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>2.0 Announcement - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, 2.0 Announcement">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../2.2-announcement">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../contributing">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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 &amp; 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>
+
+
+
+
+
+
+ </ul>
+
+ </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">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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/rest-hypermedia-hateoas.html b/topics/rest-hypermedia-hateoas.html
deleted file mode 100644
index ffe4d760..00000000
--- a/topics/rest-hypermedia-hateoas.html
+++ /dev/null
@@ -1,266 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>REST, Hypermedia & HATEOAS - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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/third-party-resources">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/browsable-api"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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 class="promo">
-
- </div>
-</ul>
-
- </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">serialization</a> and <a href="../api-guide/parsers">parser</a>/<a href="../api-guide/renderers">renderer</a> components that make it easy to build appropriate media types, <a href="../api-guide/fields">hyperlinked relations</a> for building well-connected systems, and great support for <a href="../api-guide/content-negotiation">content negotiation</a>.</p>
-<h2 id="what-rest-framework-doesnt-provide">What REST framework doesn't provide.</h2>
-<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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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/index.html b/topics/rest-hypermedia-hateoas/index.html
new file mode 100644
index 00000000..afe91552
--- /dev/null
+++ b/topics/rest-hypermedia-hateoas/index.html
@@ -0,0 +1,446 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>REST, Hypermedia & HATEOAS - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas/" />
+ <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="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../third-party-resources">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../browsable-api">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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 &amp; 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>
+
+
+
+
+
+
+ </ul>
+
+ </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; Mike Amundsen's <a href="http://restfulwebapis.org/">RESTful Web APIs</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">serialization</a> and <a href="../../api-guide/parsers">parser</a>/<a href="../../api-guide/renderers">renderer</a> components that make it easy to build appropriate media types, <a href="../../api-guide/fields">hyperlinked relations</a> for building well-connected systems, and great support for <a href="../../api-guide/content-negotiation">content negotiation</a>.</p>
+<h2 id="what-rest-framework-doesnt-provide">What REST framework doesn't provide.</h2>
+<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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/third-party-resources.html b/topics/third-party-resources.html
deleted file mode 100644
index a7f11af7..00000000
--- a/topics/third-party-resources.html
+++ /dev/null
@@ -1,330 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Third Party Resources - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/third-party-resources"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Third Party Resources">
- <meta name="author" content="Tom Christie">
-
- <!-- Le styles -->
- <link href="http://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </head>
- <body onload="prettyPrint()" class="third-party-resources-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">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../topics/rest-hypermedia-hateoas"><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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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="#third-party-resources">Third Party Resources</a></li>
-<li><a href="#libraries-and-extensions">Libraries and Extensions</a></li>
-<li><a href="#tutorials">Tutorials</a></li>
-<li><a href="#videos">Videos</a></li>
-<li><a href="#articles">Articles</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <h1 id="third-party-resources">Third Party Resources</h1>
-<p>Django REST Framework has a growing community of developers, packages, and resources.</p>
-<p>Check out a grid detailing all the packages and ecosystem around Django REST Framework at <a href="https://www.djangopackages.com/grids/g/django-rest-framework/">Django Packages</a>.</p>
-<p>To submit new content, <a href="https://github.com/tomchristie/django-rest-framework/issues/new">open an issue</a> or <a href="https://github.com/tomchristie/django-rest-framework/">create a pull request</a>.</p>
-<h2 id="libraries-and-extensions">Libraries and Extensions</h2>
-<h3 id="authentication">Authentication</h3>
-<ul>
-<li><a href="https://github.com/juanriaza/django-rest-framework-digestauth">djangorestframework-digestauth</a> - Provides Digest Access Authentication support.</li>
-<li><a href="https://github.com/evonove/django-oauth-toolkit">django-oauth-toolkit</a> - Provides OAuth 2.0 support.</li>
-<li><a href="https://github.com/Rediker-Software/doac">doac</a> - Provides OAuth 2.0 support.</li>
-<li><a href="https://github.com/GetBlimp/django-rest-framework-jwt">djangorestframework-jwt</a> - Provides JSON Web Token Authentication support.</li>
-<li><a href="https://github.com/kumar303/hawkrest">hawkrest</a> - Provides Hawk HTTP Authorization.</li>
-<li><a href="https://github.com/etoccalino/django-rest-framework-httpsignature">djangorestframework-httpsignature</a> - Provides an easy to use HTTP Signature Authentication mechanism.</li>
-<li><a href="https://github.com/sunscrapers/djoser">djoser</a> - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.</li>
-</ul>
-<h3 id="permissions">Permissions</h3>
-<ul>
-<li><a href="https://github.com/kevin-brown/drf-any-permissions">drf-any-permissions</a> - Provides alternative permission handling.</li>
-<li><a href="https://github.com/niwibe/djangorestframework-composed-permissions">djangorestframework-composed-permissions</a> - Provides a simple way to define complex permissions.</li>
-<li><a href="https://github.com/caxap/rest_condition">rest_condition</a> - Another extension for building complex permissions in a simple and convenient way.</li>
-</ul>
-<h3 id="serializers">Serializers</h3>
-<ul>
-<li><a href="https://github.com/umutbozkurt/django-rest-framework-mongoengine">django-rest-framework-mongoengine</a> - Serializer class that supports using MongoDB as the storage layer for Django REST framework.</li>
-<li><a href="https://github.com/djangonauts/django-rest-framework-gis">djangorestframework-gis</a> - Geographic add-ons</li>
-<li><a href="https://github.com/djangonauts/django-rest-framework-hstore">djangorestframework-hstore</a> - Serializer class to support django-hstore DictionaryField model field and its schema-mode feature.</li>
-</ul>
-<h3 id="serializer-fields">Serializer fields</h3>
-<ul>
-<li><a href="https://github.com/estebistec/drf-compound-fields">drf-compound-fields</a> - Provides "compound" serializer fields, such as lists of simple values.</li>
-<li><a href="https://github.com/Hipo/drf-extra-fields">django-extra-fields</a> - Provides extra serializer fields.</li>
-</ul>
-<h3 id="views">Views</h3>
-<ul>
-<li><a href="https://github.com/miki725/django-rest-framework-bulk">djangorestframework-bulk</a> - Implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.</li>
-</ul>
-<h3 id="routers">Routers</h3>
-<ul>
-<li><a href="https://github.com/alanjds/drf-nested-routers">drf-nested-routers</a> - Provides routers and relationship fields for working with nested resources.</li>
-<li><a href="http://wq.io/docs/about-rest">wq.db.rest</a> - Provides an admin-style model registration API with reasonable default URLs and viewsets.</li>
-</ul>
-<h3 id="parsers">Parsers</h3>
-<ul>
-<li><a href="https://github.com/juanriaza/django-rest-framework-msgpack">djangorestframework-msgpack</a> - Provides MessagePack renderer and parser support.</li>
-<li><a href="https://github.com/vbabiy/djangorestframework-camel-case">djangorestframework-camel-case</a> - Provides camel case JSON renderers and parsers.</li>
-</ul>
-<h3 id="renderers">Renderers</h3>
-<ul>
-<li><a href="https://github.com/mjumbewu/django-rest-framework-csv">djangorestframework-csv</a> - Provides CSV renderer support.</li>
-<li><a href="https://github.com/gizmag/drf-ujson-renderer">drf_ujson</a> - Implements JSON rendering using the UJSON package.</li>
-<li><a href="https://github.com/wq/django-rest-pandas">Django REST Pandas</a> - Pandas DataFrame-powered renderers including Excel, CSV, and SVG formats.</li>
-</ul>
-<h3 id="filtering">Filtering</h3>
-<ul>
-<li><a href="https://github.com/philipn/django-rest-framework-chain">djangorestframework-chain</a> - Allows arbitrary chaining of both relations and lookup filters.</li>
-</ul>
-<h3 id="misc">Misc</h3>
-<ul>
-<li><a href="https://github.com/fredkingham/django_rest_model_hyperlink_serializers_project">djangorestrelationalhyperlink</a> - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer.</li>
-<li><a href="https://github.com/marcgibbons/django-rest-swagger">django-rest-swagger</a> - An API documentation generator for Swagger UI.</li>
-<li><a href="https://github.com/eofs/django-rest-framework-proxy">django-rest-framework-proxy </a> - Proxy to redirect incoming request to another API server.</li>
-<li><a href="https://github.com/AppsFuel/gaiarestframework">gaiarestframework</a> - Utils for django-rest-framewok</li>
-<li><a href="https://github.com/chibisov/drf-extensions">drf-extensions</a> - A collection of custom extensions</li>
-<li><a href="https://github.com/toranb/ember-data-django-rest-adapter">ember-data-django-rest-adapter</a> - An ember-data adapter</li>
-</ul>
-<h2 id="tutorials">Tutorials</h2>
-<ul>
-<li><a href="http://code.tutsplus.com/tutorials/beginners-guide-to-the-django-rest-framework--cms-19786">Beginner's Guide to the Django Rest Framework</a></li>
-<li><a href="http://blog.kevinastone.com/getting-started-with-django-rest-framework-and-angularjs.html">Getting Started with Django Rest Framework and AngularJS</a></li>
-<li><a href="http://blog.mourafiq.com/post/55034504632/end-to-end-web-app-with-django-rest-framework">End to end web app with Django-Rest-Framework &amp; AngularJS</a></li>
-<li><a href="https://godjango.com/41-start-your-api-django-rest-framework-part-1/">Start Your API - django-rest-framework part 1</a></li>
-<li><a href="https://godjango.com/43-permissions-authentication-django-rest-framework-part-2/">Permissions &amp; Authentication - django-rest-framework part 2</a></li>
-<li><a href="https://godjango.com/45-viewsets-and-routers-django-rest-framework-part-3/">ViewSets and Routers - django-rest-framework part 3</a></li>
-<li><a href="http://richardtier.com/2014/02/25/django-rest-framework-user-endpoint/">Django Rest Framework User Endpoint</a></li>
-<li><a href="http://richardtier.com/2014/03/06/110/">Check credentials using Django Rest Framework</a></li>
-</ul>
-<h2 id="videos">Videos</h2>
-<ul>
-<li><a href="http://www.neckbeardrepublic.com/screencasts/ember-and-django-part-1">Ember and Django Part 1 (Video)</a></li>
-<li><a href="http://www.neckbeardrepublic.com/screencasts/django-rest-framework-part-1">Django Rest Framework Part 1 (Video)</a></li>
-<li><a href="http://www.youtube.com/watch?v=E1ZrehVxpBo">Pyowa July 2013 - Django Rest Framework (Video)</a></li>
-<li><a href="http://www.youtube.com/watch?v=Q8FRBGTJ020">django-rest-framework and angularjs (Video)</a></li>
-</ul>
-<h2 id="articles">Articles</h2>
-<ul>
-<li><a href="http://dabapps.com/blog/api-performance-profiling-django-rest-framework/">Web API performance: profiling Django REST framework</a></li>
-<li><a href="https://bnotions.com/api-development-with-django-and-django-rest-framework/">API Development with Django and Django REST Framework</a></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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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/third-party-resources/index.html b/topics/third-party-resources/index.html
new file mode 100644
index 00000000..3c6ed5c2
--- /dev/null
+++ b/topics/third-party-resources/index.html
@@ -0,0 +1,622 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Third Party Resources - Django REST framework</title>
+ <link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
+ <link rel="canonical" href="http://www.django-rest-framework.org/topics/third-party-resources/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Third Party Resources">
+ <meta name="author" content="Tom Christie">
+
+ <!-- Le styles -->
+ <link href="../../css/prettify.css" rel="stylesheet">
+ <link href="../../css/bootstrap.css" rel="stylesheet">
+ <link href="../../css/bootstrap-responsive.css" rel="stylesheet">
+ <link href="../../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>
+
+ <style>
+ span.fusion-wrap a {
+ display: block;
+ margin-top: 10px;
+ color: black;
+ }
+ a.fusion-poweredby {
+ display: block;
+ margin-top: 10px;
+ }
+ @media (max-width: 767px) {
+ div.promo {
+ display: none;
+ }
+ }
+ </style>
+</head>
+<body onload="prettyPrint()" class="-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 " rel="prev" href="../contributing">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../rest-hypermedia-hateoas">
+ <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://www.django-rest-framework.org">Django REST framework</a>
+ <div class="nav-collapse collapse">
+
+ <!-- Main navigation -->
+ <ul class="nav navbar-nav">
+ <li ><a href="/">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="../../tutorial/quickstart">Quickstart</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/1-serialization">1 - Serialization</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/2-requests-and-responses">2 - Requests and responses</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/3-class-based-views">3 - Class based views</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a>
+ </li>
+
+ <li >
+ <a href="../../tutorial/6-viewsets-and-routers">6- Viewsets and routers</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../../api-guide/requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/views">Views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../../api-guide/settings">Settings</a>
+ </li>
+
+ </ul>
+ </li>
+
+ <li class="dropdown active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../credits">Credits</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="#third-party-resources">Third Party Resources</a>
+ </li>
+
+
+ <li>
+ <a href="#about-third-party-packages">About Third Party Packages</a>
+ </li>
+
+ <li>
+ <a href="#how-to-create-a-third-party-package">How to create a Third Party Package</a>
+ </li>
+
+ <li>
+ <a href="#existing-third-party-packages">Existing Third Party Packages</a>
+ </li>
+
+ <li>
+ <a href="#other-resources">Other Resources</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <h1 id="third-party-resources">Third Party Resources</h1>
+<h2 id="about-third-party-packages">About Third Party Packages</h2>
+<p>Third Party Packages allow developers to share code that extends the functionality of Django REST framework, in order to support additional use-cases.</p>
+<p>We <strong>support</strong>, <strong>encourage</strong> and <strong>strongly favour</strong> the creation of Third Party Packages to encapsulate new behaviour rather than adding additional functionality directly to Django REST Framework.</p>
+<p>We aim to make creating Third Party Packages as easy as possible, whilst keeping the <strong>simplicity</strong> of the core API and ensuring that <strong>maintenance</strong> of the main project remains under control. If a Third Party Package proves popular it is relatively easy to move it into the main project; removing features is much more problematic.</p>
+<p>If you have an idea for a new feature please consider how it may be packaged as a Third Party Package. We're always happy to dicuss ideas on the <a href="https://groups.google.com/forum/#!forum/django-rest-framework">Mailing List</a>.</p>
+<h2 id="how-to-create-a-third-party-package">How to create a Third Party Package</h2>
+<h3 id="creating-your-package">Creating your package</h3>
+<p>You can use <a href="https://github.com/jpadilla/cookiecutter-django-rest-framework">this cookiecutter template</a> for creating reusable Django REST Framework packages quickly. Cookiecutter creates projects from project templates. While optional, this cookiecutter template includes best practices from Django REST framework and other packages, as well as a Travis CI configuration, Tox configuration, and a sane setup.py for easy PyPI registration/distribution.</p>
+<p>Note: Let us know if you have an alternate cookiecuter package so we can also link to it.</p>
+<h4 id="running-the-initial-cookiecutter-command">Running the initial cookiecutter command</h4>
+<p>To run the initial cookiecutter command, you'll first need to install the Python <code>cookiecutter</code> package.</p>
+<pre><code>$ pip install cookiecutter
+</code></pre>
+<p>Once <code>cookiecutter</code> is installed just run the following to create a new project.</p>
+<pre><code>$ cookiecutter gh:jpadilla/cookiecutter-django-rest-framework
+</code></pre>
+<p>You'll be prompted for some questions, answer them, then it'll create your Python package in the current working directory based on those values.</p>
+<pre><code>full_name (default is "Your full name here")? Johnny Appleseed
+email (default is "you@example.com")? jappleseed@example.com
+github_username (default is "yourname")? jappleseed
+pypi_project_name (default is "dj-package")? djangorestframework-custom-auth
+repo_name (default is "dj-package")? django-rest-framework-custom-auth
+app_name (default is "djpackage")? custom_auth
+project_short_description (default is "Your project description goes here")?
+year (default is "2014")?
+version (default is "0.1.0")?
+</code></pre>
+<h4 id="getting-it-onto-github">Getting it onto GitHub</h4>
+<p>To put your project up on GitHub, you'll need a repository for it to live in. You can create a new repository <a href="https://github.com/new">here</a>. If you need help, check out the <a href="https://help.github.com/articles/create-a-repo/">Create A Repo</a> article on GitHub.</p>
+<h4 id="adding-to-travis-ci">Adding to Travis CI</h4>
+<p>We recommend using <a href="https://travis-ci.org">Travis CI</a>, a hosted continuous integration service which integrates well with GitHub and is free for public repositories.</p>
+<p>To get started with Travis CI, <a href="https://travis-ci.org">sign in</a> with your GitHub account. Once you're signed in, go to your <a href="https://travis-ci.org/profile">profile page</a> and enable the service hook for the repository you want.</p>
+<p>If you use the cookiecutter template, your project will already contain a <code>.travis.yml</code> file which Travis CI will use to build your project and run tests. By default, builds are triggered everytime you push to your repository or create Pull Request.</p>
+<h4 id="uploading-to-pypi">Uploading to PyPI</h4>
+<p>Once you've got at least a prototype working and tests running, you should publish it on PyPI to allow others to install it via <code>pip</code>.</p>
+<p>You must <a href="https://pypi.python.org/pypi?%3Aaction=register_form">register</a> an account before publishing to PyPI.</p>
+<p>To register your package on PyPI run the following command.</p>
+<pre><code>$ python setup.py register
+</code></pre>
+<p>If this is the first time publishing to PyPI, you'll be prompted to login.</p>
+<p>Note: Before publishing you'll need to make sure you have the latest pip that supports <code>wheel</code> as well as install the <code>wheel</code> package.</p>
+<pre><code>$ pip install --upgrade pip
+$ pip install wheel
+</code></pre>
+<p>After this, every time you want to release a new version on PyPI just run the following command.</p>
+<pre><code>$ python setup.py publish
+You probably want to also tag the version now:
+ git tag -a {0} -m 'version 0.1.0'
+ git push --tags
+</code></pre>
+<p>After releasing a new version to PyPI, it's always a good idea to tag the version and make available as a GitHub Release.</p>
+<p>We recommend to follow <a href="http://semver.org/">Semantic Versioning</a> for your package's versions.</p>
+<h3 id="development">Development</h3>
+<h4 id="version-requirements">Version requirements</h4>
+<p>The cookiecutter template assumes a set of supported versions will be provided for Python and Django. Make sure you correctly update your requirements, docs, <code>tox.ini</code>, <code>.travis.yml</code>, and <code>setup.py</code> to match the set of versions you wish to support.</p>
+<h4 id="tests">Tests</h4>
+<p>The cookiecutter template includes a <code>runtests.py</code> which uses the <code>pytest</code> package as a test runner.</p>
+<p>Before running, you'll need to install a couple test requirements.</p>
+<pre><code>$ pip install -r requirements-test.txt
+</code></pre>
+<p>Once requirements installed, you can run <code>runtests.py</code>.</p>
+<pre><code>$ ./runtests.py
+</code></pre>
+<p>Run using a more concise output style.</p>
+<pre><code>$ ./runtests.py -q
+</code></pre>
+<p>Run the tests using a more concise output style, no coverage, no flake8.</p>
+<pre><code>$ ./runtests.py --fast
+</code></pre>
+<p>Don't run the flake8 code linting.</p>
+<pre><code>$ ./runtests.py --nolint
+</code></pre>
+<p>Only run the flake8 code linting, don't run the tests.</p>
+<pre><code>$ ./runtests.py --lintonly
+</code></pre>
+<p>Run the tests for a given test case.</p>
+<pre><code>$ ./runtests.py MyTestCase
+</code></pre>
+<p>Run the tests for a given test method.</p>
+<pre><code>$ ./runtests.py MyTestCase.test_this_method
+</code></pre>
+<p>Shorter form to run the tests for a given test method.</p>
+<pre><code>$ ./runtests.py test_this_method
+</code></pre>
+<p>To run your tests against multiple versions of Python as different versions of requirements such as Django we recommend using <code>tox</code>. <a href="https://tox.readthedocs.org/en/latest/">Tox</a> is a generic virtualenv management and test command line tool.</p>
+<p>First, install <code>tox</code> globally.</p>
+<pre><code>$ pip install tox
+</code></pre>
+<p>To run <code>tox</code>, just simply run:</p>
+<pre><code>$ tox
+</code></pre>
+<p>To run a particular <code>tox</code> environment:</p>
+<pre><code>$ tox -e envlist
+</code></pre>
+<p><code>envlist</code> is a comma-separated value to that specifies the environments to run tests against. To view a list of all possible test environments, run:</p>
+<pre><code>$ tox -l
+</code></pre>
+<h4 id="version-compatibility">Version compatibility</h4>
+<p>Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into a <code>compat.py</code> module, and should provide a single common interface that the rest of the codebase can use.</p>
+<p>Check out Django REST framework's <a href="https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/compat.py">compat.py</a> for an example.</p>
+<h3 id="once-your-package-is-available">Once your package is available</h3>
+<p>Once your package is decently documented and available on PyPI, you might want share it with others that might find it useful.</p>
+<h4 id="adding-to-the-django-rest-framework-grid">Adding to the Django REST framework grid</h4>
+<p>We suggest adding your package to the <a href="https://www.djangopackages.com/grids/g/django-rest-framework/">REST Framework</a> grid on Django Packages.</p>
+<h4 id="adding-to-the-django-rest-framework-docs">Adding to the Django REST framework docs</h4>
+<p>Create a <a href="https://github.com/tomchristie/django-rest-framework/compare">Pull Request</a> or <a href="https://github.com/tomchristie/django-rest-framework/issues/new">Issue</a> on GitHub, and we'll add a link to it from the main REST framework documentation. You can add your package under <strong>Third party packages</strong> of the API Guide section that best applies, like <a href="../../api-guide/authentication">Authentication</a> or <a href="../../api-guide/permissions">Permissions</a>. You can also link your package under the [Third Party Resources][third-party-resources] section.</p>
+<h4 id="announce-on-the-discussion-group">Announce on the discussion group.</h4>
+<p>You can also let others know about your package through the <a href="https://groups.google.com/forum/#!forum/django-rest-framework">discussion group</a>.</p>
+<h2 id="existing-third-party-packages">Existing Third Party Packages</h2>
+<p>Django REST Framework has a growing community of developers, packages, and resources.</p>
+<p>Check out a grid detailing all the packages and ecosystem around Django REST Framework at <a href="https://www.djangopackages.com/grids/g/django-rest-framework/">Django Packages</a>.</p>
+<p>To submit new content, <a href="https://github.com/tomchristie/django-rest-framework/issues/new">open an issue</a> or <a href="https://github.com/tomchristie/django-rest-framework/compare">create a pull request</a>.</p>
+<h3 id="authentication">Authentication</h3>
+<ul>
+<li><a href="https://github.com/juanriaza/django-rest-framework-digestauth">djangorestframework-digestauth</a> - Provides Digest Access Authentication support.</li>
+<li><a href="https://github.com/evonove/django-oauth-toolkit">django-oauth-toolkit</a> - Provides OAuth 2.0 support.</li>
+<li><a href="https://github.com/Rediker-Software/doac">doac</a> - Provides OAuth 2.0 support.</li>
+<li><a href="https://github.com/GetBlimp/django-rest-framework-jwt">djangorestframework-jwt</a> - Provides JSON Web Token Authentication support.</li>
+<li><a href="https://github.com/kumar303/hawkrest">hawkrest</a> - Provides Hawk HTTP Authorization.</li>
+<li><a href="https://github.com/etoccalino/django-rest-framework-httpsignature">djangorestframework-httpsignature</a> - Provides an easy to use HTTP Signature Authentication mechanism.</li>
+<li><a href="https://github.com/sunscrapers/djoser">djoser</a> - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.</li>
+</ul>
+<h3 id="permissions">Permissions</h3>
+<ul>
+<li><a href="https://github.com/kevin-brown/drf-any-permissions">drf-any-permissions</a> - Provides alternative permission handling.</li>
+<li><a href="https://github.com/niwibe/djangorestframework-composed-permissions">djangorestframework-composed-permissions</a> - Provides a simple way to define complex permissions.</li>
+<li><a href="https://github.com/caxap/rest_condition">rest_condition</a> - Another extension for building complex permissions in a simple and convenient way.</li>
+</ul>
+<h3 id="serializers">Serializers</h3>
+<ul>
+<li><a href="https://github.com/umutbozkurt/django-rest-framework-mongoengine">django-rest-framework-mongoengine</a> - Serializer class that supports using MongoDB as the storage layer for Django REST framework.</li>
+<li><a href="https://github.com/djangonauts/django-rest-framework-gis">djangorestframework-gis</a> - Geographic add-ons</li>
+<li><a href="https://github.com/djangonauts/django-rest-framework-hstore">djangorestframework-hstore</a> - Serializer class to support django-hstore DictionaryField model field and its schema-mode feature.</li>
+</ul>
+<h3 id="serializer-fields">Serializer fields</h3>
+<ul>
+<li><a href="https://github.com/estebistec/drf-compound-fields">drf-compound-fields</a> - Provides "compound" serializer fields, such as lists of simple values.</li>
+<li><a href="https://github.com/Hipo/drf-extra-fields">django-extra-fields</a> - Provides extra serializer fields.</li>
+</ul>
+<h3 id="views">Views</h3>
+<ul>
+<li><a href="https://github.com/miki725/django-rest-framework-bulk">djangorestframework-bulk</a> - Implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.</li>
+</ul>
+<h3 id="routers">Routers</h3>
+<ul>
+<li><a href="https://github.com/alanjds/drf-nested-routers">drf-nested-routers</a> - Provides routers and relationship fields for working with nested resources.</li>
+<li><a href="http://wq.io/docs/about-rest">wq.db.rest</a> - Provides an admin-style model registration API with reasonable default URLs and viewsets.</li>
+</ul>
+<h3 id="parsers">Parsers</h3>
+<ul>
+<li><a href="https://github.com/juanriaza/django-rest-framework-msgpack">djangorestframework-msgpack</a> - Provides MessagePack renderer and parser support.</li>
+<li><a href="https://github.com/vbabiy/djangorestframework-camel-case">djangorestframework-camel-case</a> - Provides camel case JSON renderers and parsers.</li>
+</ul>
+<h3 id="renderers">Renderers</h3>
+<ul>
+<li><a href="https://github.com/mjumbewu/django-rest-framework-csv">djangorestframework-csv</a> - Provides CSV renderer support.</li>
+<li><a href="https://github.com/gizmag/drf-ujson-renderer">drf_ujson</a> - Implements JSON rendering using the UJSON package.</li>
+<li><a href="https://github.com/wq/django-rest-pandas">rest-pandas</a> - Pandas DataFrame-powered renderers including Excel, CSV, and SVG formats.</li>
+</ul>
+<h3 id="filtering">Filtering</h3>
+<ul>
+<li><a href="https://github.com/philipn/django-rest-framework-chain">djangorestframework-chain</a> - Allows arbitrary chaining of both relations and lookup filters.</li>
+</ul>
+<h3 id="misc">Misc</h3>
+<ul>
+<li><a href="https://github.com/fredkingham/django_rest_model_hyperlink_serializers_project">djangorestrelationalhyperlink</a> - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer.</li>
+<li><a href="https://github.com/marcgibbons/django-rest-swagger">django-rest-swagger</a> - An API documentation generator for Swagger UI.</li>
+<li><a href="https://github.com/eofs/django-rest-framework-proxy">django-rest-framework-proxy</a> - Proxy to redirect incoming request to another API server.</li>
+<li><a href="https://github.com/AppsFuel/gaiarestframework">gaiarestframework</a> - Utils for django-rest-framewok</li>
+<li><a href="https://github.com/chibisov/drf-extensions">drf-extensions</a> - A collection of custom extensions</li>
+<li><a href="https://github.com/toranb/ember-data-django-rest-adapter">ember-data-django-rest-adapter</a> - An ember-data adapter</li>
+</ul>
+<h2 id="other-resources">Other Resources</h2>
+<h3 id="tutorials">Tutorials</h3>
+<ul>
+<li><a href="http://code.tutsplus.com/tutorials/beginners-guide-to-the-django-rest-framework--cms-19786">Beginner's Guide to the Django Rest Framework</a></li>
+<li><a href="http://blog.kevinastone.com/getting-started-with-django-rest-framework-and-angularjs.html">Getting Started with Django Rest Framework and AngularJS</a></li>
+<li><a href="http://blog.mourafiq.com/post/55034504632/end-to-end-web-app-with-django-rest-framework">End to end web app with Django-Rest-Framework &amp; AngularJS</a></li>
+<li><a href="https://godjango.com/41-start-your-api-django-rest-framework-part-1/">Start Your API - django-rest-framework part 1</a></li>
+<li><a href="https://godjango.com/43-permissions-authentication-django-rest-framework-part-2/">Permissions &amp; Authentication - django-rest-framework part 2</a></li>
+<li><a href="https://godjango.com/45-viewsets-and-routers-django-rest-framework-part-3/">ViewSets and Routers - django-rest-framework part 3</a></li>
+<li><a href="http://richardtier.com/2014/02/25/django-rest-framework-user-endpoint/">Django Rest Framework User Endpoint</a></li>
+<li><a href="http://richardtier.com/2014/03/06/110/">Check credentials using Django Rest Framework</a></li>
+</ul>
+<h3 id="videos">Videos</h3>
+<ul>
+<li><a href="http://www.neckbeardrepublic.com/screencasts/ember-and-django-part-1">Ember and Django Part 1 (Video)</a></li>
+<li><a href="http://www.neckbeardrepublic.com/screencasts/django-rest-framework-part-1">Django Rest Framework Part 1 (Video)</a></li>
+<li><a href="http://www.youtube.com/watch?v=e1zrehvxpbo">Pyowa July 2013 - Django Rest Framework (Video)</a></li>
+<li><a href="http://www.youtube.com/watch?v=q8frbgtj020">django-rest-framework and angularjs (Video)</a></li>
+</ul>
+<h3 id="articles">Articles</h3>
+<ul>
+<li><a href="http://dabapps.com/blog/api-performance-profiling-django-rest-framework/">Web API performance: profiling Django REST framework</a></li>
+<li><a href="https://bnotions.com/api-development-with-django-and-django-rest-framework/">API Development with Django and Django REST Framework</a></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="../../js/jquery-1.8.1-min.js"></script>
+ <script src="../../js/prettify-1.0.js"></script>
+ <script src="../../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> \ No newline at end of file
diff --git a/topics/writable-nested-serializers.html b/topics/writable-nested-serializers.html
deleted file mode 100644
index eb349413..00000000
--- a/topics/writable-nested-serializers.html
+++ /dev/null
@@ -1,274 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Writable nested serializers - Django REST framework</title>
- <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
- <link rel="canonical" href="http://www.django-rest-framework.org/topics/writable-nested-serializers"/>
- <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://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
- <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">
-
- <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
- <!--[if lt IE 9]>
- <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>
- <style>
-span.fusion-wrap a {
- display: block;
- margin-top: 10px;
- color: black;
-}
-
-a.fusion-poweredby {
- display: block;
- margin-top: 10px;
-}
-@media (max-width: 767px) {
- div.promo {display: none;}
-}
-</style>
- </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://www.django-rest-framework.org">Django REST framework</a>
- <div class="nav-collapse collapse">
- <ul class="nav">
- <li><a href="http://www.django-rest-framework.org">Home</a></li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
- <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
- <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
- <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
- </ul>
- </li>
- </ul>
- <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 class="promo">
-
- </div>
-</ul>
-
- </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://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
- <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
- <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
-
- <script>
- //$('.side-nav').scrollspy()
- 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>