aboutsummaryrefslogtreecommitdiffstats
path: root/api-guide
diff options
context:
space:
mode:
authorTom Christie2014-11-25 16:04:38 +0000
committerTom Christie2014-11-25 16:04:38 +0000
commit330c13296de35d4055c30b5b3642421707565e2b (patch)
treeb0e568ab66ebd3eef1aad36f104068b90aca8047 /api-guide
parent5769306c10a6ad7a809f2e96b1c82dc61935b9eb (diff)
downloaddjango-rest-framework-330c13296de35d4055c30b5b3642421707565e2b.tar.bz2
Update documentation
Diffstat (limited to 'api-guide')
-rw-r--r--api-guide/authentication/index.html (renamed from api-guide/authentication.html)704
-rw-r--r--api-guide/content-negotiation.html315
-rw-r--r--api-guide/content-negotiation/index.html507
-rw-r--r--api-guide/exceptions.html352
-rw-r--r--api-guide/exceptions/index.html565
-rw-r--r--api-guide/fields/index.html (renamed from api-guide/fields.html)731
-rw-r--r--api-guide/filtering/index.html (renamed from api-guide/filtering.html)696
-rw-r--r--api-guide/format-suffixes.html291
-rw-r--r--api-guide/format-suffixes/index.html473
-rw-r--r--api-guide/generic-views/index.html (renamed from api-guide/generic-views.html)719
-rw-r--r--api-guide/metadata.html324
-rw-r--r--api-guide/pagination.html373
-rw-r--r--api-guide/pagination/index.html581
-rw-r--r--api-guide/parsers.html379
-rw-r--r--api-guide/parsers/index.html621
-rw-r--r--api-guide/permissions.html429
-rw-r--r--api-guide/permissions/index.html673
-rw-r--r--api-guide/relations/index.html (renamed from api-guide/relations.html)702
-rw-r--r--api-guide/renderers/index.html (renamed from api-guide/renderers.html)767
-rw-r--r--api-guide/requests.html321
-rw-r--r--api-guide/requests/index.html578
-rw-r--r--api-guide/responses.html304
-rw-r--r--api-guide/responses/index.html528
-rw-r--r--api-guide/reverse.html279
-rw-r--r--api-guide/reverse/index.html461
-rw-r--r--api-guide/routers/index.html (renamed from api-guide/routers.html)632
-rw-r--r--api-guide/serializers/index.html (renamed from api-guide/serializers.html)774
-rw-r--r--api-guide/settings/index.html (renamed from api-guide/settings.html)657
-rw-r--r--api-guide/status-codes.html339
-rw-r--r--api-guide/status-codes/index.html533
-rw-r--r--api-guide/testing.html451
-rw-r--r--api-guide/testing/index.html695
-rw-r--r--api-guide/throttling.html388
-rw-r--r--api-guide/throttling/index.html604
-rw-r--r--api-guide/validators.html388
-rw-r--r--api-guide/validators/index.html635
-rw-r--r--api-guide/views.html360
-rw-r--r--api-guide/views/index.html565
-rw-r--r--api-guide/viewsets.html445
-rw-r--r--api-guide/viewsets/index.html656
40 files changed, 13035 insertions, 7760 deletions
diff --git a/api-guide/authentication.html b/api-guide/authentication/index.html
index 420a1874..e55e4ddd 100644
--- a/api-guide/authentication.html
+++ b/api-guide/authentication/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>Authentication - 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/api-guide/authentication"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Authentication, API Reference, Custom authentication, 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="authentication-page">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Authentication - 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/api-guide/authentication/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Authentication">
+ <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="../api-guide/permissions">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/relations"><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="../permissions">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../validators">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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,51 +335,140 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#authentication">Authentication</a></li>
-<li><a href="#how-authentication-is-determined">How authentication is determined</a></li>
-<li><a href="#setting-the-authentication-scheme">Setting the authentication scheme</a></li>
-<li><a href="#unauthorized-and-forbidden-responses">Unauthorized and Forbidden responses</a></li>
-<li><a href="#apache-mod_wsgi-specific-configuration">Apache mod_wsgi specific configuration</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#basicauthentication">BasicAuthentication</a></li>
-<li><a href="#tokenauthentication">TokenAuthentication</a></li>
-<li><a href="#sessionauthentication">SessionAuthentication</a></li>
-<li><a href="#oauthauthentication">OAuthAuthentication</a></li>
-<li><a href="#oauth2authentication">OAuth2Authentication</a></li>
-<li class="main"><a href="#custom-authentication">Custom authentication</a></li>
-<li><a href="#example">Example</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#digest-authentication">Digest Authentication</a></li>
-<li><a href="#django-oauth-toolkit">Django OAuth Toolkit</a></li>
-<li><a href="#django-oauth2-consumer">Django OAuth2 Consumer</a></li>
-<li><a href="#json-web-token-authentication">JSON Web Token Authentication</a></li>
-<li><a href="#hawk-http-authentication">Hawk HTTP Authentication</a></li>
-<li><a href="#http-signature-authentication">HTTP Signature Authentication</a></li>
-<li><a href="#djoser">Djoser</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#authentication">Authentication</a>
+ </li>
+
+
+ <li>
+ <a href="#how-authentication-is-determined">How authentication is determined</a>
+ </li>
+
+ <li>
+ <a href="#setting-the-authentication-scheme">Setting the authentication scheme</a>
+ </li>
+
+ <li>
+ <a href="#unauthorized-and-forbidden-responses">Unauthorized and Forbidden responses</a>
+ </li>
+
+ <li>
+ <a href="#apache-mod_wsgi-specific-configuration">Apache mod_wsgi specific configuration</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#basicauthentication">BasicAuthentication</a>
+ </li>
+
+ <li>
+ <a href="#tokenauthentication">TokenAuthentication</a>
+ </li>
+
+ <li>
+ <a href="#sessionauthentication">SessionAuthentication</a>
+ </li>
+
+ <li>
+ <a href="#oauthauthentication">OAuthAuthentication</a>
+ </li>
+
+ <li>
+ <a href="#oauth2authentication">OAuth2Authentication</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-authentication">Custom authentication</a>
+ </li>
+
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#digest-authentication">Digest Authentication</a>
+ </li>
+
+ <li>
+ <a href="#django-oauth-toolkit">Django OAuth Toolkit</a>
+ </li>
+
+ <li>
+ <a href="#django-oauth2-consumer">Django OAuth2 Consumer</a>
+ </li>
+
+ <li>
+ <a href="#json-web-token-authentication">JSON Web Token Authentication</a>
+ </li>
+
+ <li>
+ <a href="#hawk-http-authentication">Hawk HTTP Authentication</a>
+ </li>
+
+ <li>
+ <a href="#http-signature-authentication">HTTP Signature Authentication</a>
+ </li>
+
+ <li>
+ <a href="#djoser">Djoser</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/authentication.py"><span class="label label-info">authentication.py</span></a></p>
-<h1 id="authentication">Authentication</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/authentication.py">
+ <span class="label label-info">authentication.py</span>
+ </a>
+
+
+
+ <h1 id="authentication">Authentication</h1>
<blockquote>
<p>Auth needs to be pluggable.</p>
<p>&mdash; Jacob Kaplan-Moss, <a href="http://jacobian.org/writing/rest-worst-practices/">"REST worst practices"</a></p>
</blockquote>
-<p>Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The <a href="permissions">permission</a> and <a href="throttling">throttling</a> policies can then use those credentials to determine if the request should be permitted.</p>
+<p>Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The <a href="../permissions">permission</a> and <a href="../throttling">throttling</a> policies can then use those credentials to determine if the request should be permitted.</p>
<p>REST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes.</p>
<p>Authentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.</p>
<p>The <code>request.user</code> property will typically be set to an instance of the <code>contrib.auth</code> package's <code>User</code> class.</p>
<p>The <code>request.auth</code> property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with.</p>
<hr />
<p><strong>Note:</strong> Don't forget that <strong>authentication by itself won't allow or disallow an incoming request</strong>, it simply identifies the credentials that the request was made with.</p>
-<p>For information on how to setup the permission polices for your API please see the <a href="permissions">permissions documentation</a>.</p>
+<p>For information on how to setup the permission polices for your API please see the <a href="../permissions">permissions documentation</a>.</p>
<hr />
<h2 id="how-authentication-is-determined">How authentication is determined</h2>
<p>The authentication schemes are always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set <code>request.user</code> and <code>request.auth</code> using the return value of the first class that successfully authenticates.</p>
@@ -238,7 +476,7 @@ a.fusion-poweredby {
<p>The value of <code>request.user</code> and <code>request.auth</code> for unauthenticated requests can be modified using the <code>UNAUTHENTICATED_USER</code> and <code>UNAUTHENTICATED_TOKEN</code> settings.</p>
<h2 id="setting-the-authentication-scheme">Setting the authentication scheme</h2>
<p>The default authentication schemes may be set globally, using the <code>DEFAULT_AUTHENTICATION</code> setting. For example.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
+<pre><code>REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
@@ -247,7 +485,7 @@ a.fusion-poweredby {
</code></pre>
<p>You can also set the authentication scheme on a per-view or per-viewset basis,
using the <code>APIView</code> class based views.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.authentication import SessionAuthentication, BasicAuthentication
+<pre><code>from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
@@ -264,7 +502,7 @@ class ExampleView(APIView):
return Response(content)
</code></pre>
<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
-<pre class="prettyprint lang-py"><code>@api_view(['GET'])
+<pre><code>@api_view(['GET'])
@authentication_classes((SessionAuthentication, BasicAuthentication))
@permission_classes((IsAuthenticated,))
def example_view(request, format=None):
@@ -286,7 +524,7 @@ def example_view(request, format=None):
<h2 id="apache-mod_wsgi-specific-configuration">Apache mod_wsgi specific configuration</h2>
<p>Note that if deploying to <a href="http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization">Apache using mod_wsgi</a>, the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level.</p>
<p>If you are deploying to Apache, and using any non-session based authentication, you will need to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the <code>WSGIPassAuthorization</code> directive in the appropriate context and setting it to <code>'On'</code>.</p>
-<pre class="prettyprint lang-py"><code># this can go in either server config, virtual host, directory or .htaccess
+<pre><code># this can go in either server config, virtual host, directory or .htaccess
WSGIPassAuthorization On
</code></pre>
<hr />
@@ -299,13 +537,13 @@ WSGIPassAuthorization On
<li><code>request.auth</code> will be <code>None</code>.</li>
</ul>
<p>Unauthenticated responses that are denied permission will result in an <code>HTTP 401 Unauthorized</code> response with an appropriate WWW-Authenticate header. For example:</p>
-<pre class="prettyprint lang-py"><code>WWW-Authenticate: Basic realm="api"
+<pre><code>WWW-Authenticate: Basic realm="api"
</code></pre>
<p><strong>Note:</strong> If you use <code>BasicAuthentication</code> in production you must ensure that your API is only available over <code>https</code>. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.</p>
<h2 id="tokenauthentication">TokenAuthentication</h2>
<p>This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.</p>
<p>To use the <code>TokenAuthentication</code> scheme you'll need to <a href="#setting-the-authentication-scheme">configure the authentication classes</a> to include <code>TokenAuthentication</code>, and additionally include <code>rest_framework.authtoken</code> in your <code>INSTALLED_APPS</code> setting:</p>
-<pre class="prettyprint lang-py"><code>INSTALLED_APPS = (
+<pre><code>INSTALLED_APPS = (
...
'rest_framework.authtoken'
)
@@ -314,13 +552,13 @@ WSGIPassAuthorization On
<p><strong>Note:</strong> Make sure to run <code>manage.py syncdb</code> after changing your settings. The <code>rest_framework.authtoken</code> app provides both Django (from v1.7) and South database migrations. See <a href="#schema-migrations">Schema migrations</a> below.</p>
<hr />
<p>You'll also need to create tokens for your users.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.authtoken.models import Token
+<pre><code>from rest_framework.authtoken.models import Token
token = Token.objects.create(user=...)
print token.key
</code></pre>
<p>For clients to authenticate, the token key should be included in the <code>Authorization</code> HTTP header. The key should be prefixed by the string literal "Token", with whitespace separating the two strings. For example:</p>
-<pre class="prettyprint lang-py"><code>Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
+<pre><code>Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
</code></pre>
<p>If successfully authenticated, <code>TokenAuthentication</code> provides the following credentials.</p>
<ul>
@@ -328,17 +566,17 @@ print token.key
<li><code>request.auth</code> will be a <code>rest_framework.authtoken.models.BasicToken</code> instance.</li>
</ul>
<p>Unauthenticated responses that are denied permission will result in an <code>HTTP 401 Unauthorized</code> response with an appropriate WWW-Authenticate header. For example:</p>
-<pre class="prettyprint lang-py"><code>WWW-Authenticate: Token
+<pre><code>WWW-Authenticate: Token
</code></pre>
<p>The <code>curl</code> command line tool may be useful for testing token authenticated APIs. For example:</p>
-<pre class="prettyprint lang-py"><code>curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
+<pre><code>curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
</code></pre>
<hr />
<p><strong>Note:</strong> If you use <code>TokenAuthentication</code> in production you must ensure that your API is only available over <code>https</code>.</p>
<hr />
<h4 id="generating-tokens">Generating Tokens</h4>
<p>If you want every user to have an automatically generated Token, you can simply catch the User's <code>post_save</code> signal.</p>
-<pre class="prettyprint lang-py"><code>from django.conf import settings
+<pre><code>from django.conf import settings
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
@@ -351,21 +589,21 @@ def create_auth_token(sender, instance=None, created=False, **kwargs):
</code></pre>
<p>Note that you'll want to ensure you place this code snippet in an installed <code>models.py</code> module, or some other location that will be imported by Django on startup.</p>
<p>If you've already created some users, you can generate tokens for all existing users like this:</p>
-<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
+<pre><code>from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
for user in User.objects.all():
Token.objects.get_or_create(user=user)
</code></pre>
<p>When using <code>TokenAuthentication</code>, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the <code>obtain_auth_token</code> view to your URLconf:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.authtoken import views
+<pre><code>from rest_framework.authtoken import views
urlpatterns += [
url(r'^api-token-auth/', views.obtain_auth_token)
]
</code></pre>
<p>Note that the URL part of the pattern can be whatever you want to use.</p>
<p>The <code>obtain_auth_token</code> view will return a JSON response when valid <code>username</code> and <code>password</code> fields are POSTed to the view using form data or JSON:</p>
-<pre class="prettyprint lang-py"><code>{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }
+<pre><code>{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }
</code></pre>
<p>Note that the default <code>obtain_auth_token</code> view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the <code>obtain_auth_token</code> view, you can do so by overriding the <code>ObtainAuthToken</code> view class, and using that in your url conf instead.</p>
<h4 id="schema-migrations">Schema migrations</h4>
@@ -375,7 +613,7 @@ urlpatterns += [
<hr />
<p>If you're using a <a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model">custom user model</a> you'll need to make sure that any initial migration that creates the user table runs before the authtoken table is created.</p>
<p>You can do so by inserting a <code>needed_by</code> attribute in your user migration:</p>
-<pre class="prettyprint lang-py"><code>class Migration:
+<pre><code>class Migration:
needed_by = (
('authtoken', '0001_initial'),
@@ -386,7 +624,7 @@ urlpatterns += [
</code></pre>
<p>For more details, see the <a href="http://south.readthedocs.org/en/latest/dependencies.html">south documentation on dependencies</a>.</p>
<p>Also note that if you're using a <code>post_save</code> signal to create tokens, then the first time you create the database tables, you'll need to ensure any migrations are run prior to creating any superusers. For example:</p>
-<pre class="prettyprint lang-py"><code>python manage.py syncdb --noinput # Won't create a superuser just yet, due to `--noinput`.
+<pre><code>python manage.py syncdb --noinput # Won't create a superuser just yet, due to `--noinput`.
python manage.py migrate
python manage.py createsuperuser
</code></pre>
@@ -402,13 +640,13 @@ python manage.py createsuperuser
<h2 id="oauthauthentication">OAuthAuthentication</h2>
<p>This authentication uses <a href="http://oauth.net/core/1.0a">OAuth 1.0a</a> authentication scheme. OAuth 1.0a provides signature validation which provides a reasonable level of security over plain non-HTTPS connections. However, it may also be considered more complicated than OAuth2, as it requires clients to sign their requests.</p>
<p>This authentication class depends on the optional <code>django-oauth-plus</code> and <code>oauth2</code> packages. In order to make it work you must install these packages and add <code>oauth_provider</code> to your <code>INSTALLED_APPS</code>:</p>
-<pre class="prettyprint lang-py"><code>INSTALLED_APPS = (
+<pre><code>INSTALLED_APPS = (
...
`oauth_provider`,
)
</code></pre>
<p>Don't forget to run <code>syncdb</code> once you've added the package.</p>
-<pre class="prettyprint lang-py"><code>python manage.py syncdb
+<pre><code>python manage.py syncdb
</code></pre>
<h4 id="getting-started-with-django-oauth-plus">Getting started with django-oauth-plus</h4>
<p>The OAuthAuthentication class only provides token verification and signature validation for requests. It doesn't provide authorization flow for your clients. You still need to implement your own views for accessing and authorizing tokens.</p>
@@ -416,23 +654,23 @@ python manage.py createsuperuser
<h2 id="oauth2authentication">OAuth2Authentication</h2>
<p>This authentication uses <a href="http://tools.ietf.org/html/rfc6749">OAuth 2.0</a> authentication scheme. OAuth2 is more simple to work with than OAuth1, and provides much better security than simple token authentication. It is an unauthenticated scheme, and requires you to use an HTTPS connection.</p>
<p>This authentication class depends on the optional <a href="https://github.com/caffeinehit/django-oauth2-provider">django-oauth2-provider</a> project. In order to make it work you must install this package and add <code>provider</code> and <code>provider.oauth2</code> to your <code>INSTALLED_APPS</code>:</p>
-<pre class="prettyprint lang-py"><code>INSTALLED_APPS = (
+<pre><code>INSTALLED_APPS = (
...
'provider',
'provider.oauth2',
)
</code></pre>
<p>Then add <code>OAuth2Authentication</code> to your global <code>DEFAULT_AUTHENTICATION</code> setting:</p>
-<pre class="prettyprint lang-py"><code>'DEFAULT_AUTHENTICATION_CLASSES': (
+<pre><code>'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.OAuth2Authentication',
),
</code></pre>
<p>You must also include the following in your root <code>urls.py</code> module:</p>
-<pre class="prettyprint lang-py"><code>url(r'^oauth2/', include('provider.oauth2.urls', namespace='oauth2')),
+<pre><code>url(r'^oauth2/', include('provider.oauth2.urls', namespace='oauth2')),
</code></pre>
<p>Note that the <code>namespace='oauth2'</code> argument is required.</p>
<p>Finally, sync your database.</p>
-<pre class="prettyprint lang-py"><code>python manage.py syncdb
+<pre><code>python manage.py syncdb
python manage.py migrate
</code></pre>
<hr />
@@ -454,15 +692,15 @@ python manage.py migrate
<li><code>password</code> well, that speaks for itself.</li>
</ul>
<p>You can use the command line to test that your local configuration is working:</p>
-<pre class="prettyprint lang-py"><code>curl -X POST -d "client_id=YOUR_CLIENT_ID&amp;client_secret=YOUR_CLIENT_SECRET&amp;grant_type=password&amp;username=YOUR_USERNAME&amp;password=YOUR_PASSWORD" http://localhost:8000/oauth2/access_token/
+<pre><code>curl -X POST -d "client_id=YOUR_CLIENT_ID&amp;client_secret=YOUR_CLIENT_SECRET&amp;grant_type=password&amp;username=YOUR_USERNAME&amp;password=YOUR_PASSWORD" http://localhost:8000/oauth2/access_token/
</code></pre>
<p>You should get a response that looks something like this:</p>
-<pre class="prettyprint lang-py"><code>{"access_token": "&lt;your-access-token&gt;", "scope": "read", "expires_in": 86399, "refresh_token": "&lt;your-refresh-token&gt;"}
+<pre><code>{"access_token": "&lt;your-access-token&gt;", "scope": "read", "expires_in": 86399, "refresh_token": "&lt;your-refresh-token&gt;"}
</code></pre>
<h5 id="3-access-the-api">3. Access the API</h5>
<p>The only thing needed to make the <code>OAuth2Authentication</code> class work is to insert the <code>access_token</code> you've received in the <code>Authorization</code> request header.</p>
<p>The command line to test the authentication looks like:</p>
-<pre class="prettyprint lang-py"><code>curl -H "Authorization: Bearer &lt;your-access-token&gt;" http://localhost:8000/api/
+<pre><code>curl -H "Authorization: Bearer &lt;your-access-token&gt;" http://localhost:8000/api/
</code></pre>
<h3 id="alternative-oauth-2-implementations">Alternative OAuth 2 implementations</h3>
<p>Note that <a href="https://github.com/evonove/django-oauth-toolkit">Django OAuth Toolkit</a> is an alternative external package that also includes OAuth 2.0 support for REST framework.</p>
@@ -479,7 +717,7 @@ python manage.py migrate
<p>If the <code>.authenticate_header()</code> method is not overridden, the authentication scheme will return <code>HTTP 403 Forbidden</code> responses when an unauthenticated request is denied access.</p>
<h2 id="example">Example</h2>
<p>The following example will authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'.</p>
-<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
+<pre><code>from django.contrib.auth.models import User
from rest_framework import authentication
from rest_framework import exceptions
@@ -502,7 +740,7 @@ class ExampleAuthentication(authentication.BaseAuthentication):
<h2 id="digest-authentication">Digest Authentication</h2>
<p>HTTP digest authentication is a widely implemented scheme that was intended to replace HTTP basic authentication, and which provides a simple encrypted authentication mechanism. <a href="https://github.com/juanriaza">Juan Riaza</a> maintains the <a href="https://github.com/juanriaza/django-rest-framework-digestauth">djangorestframework-digestauth</a> package which provides HTTP digest authentication support for REST framework.</p>
<h2 id="django-oauth-toolkit">Django OAuth Toolkit</h2>
-<p>The <a href="https://github.com/evonove/django-oauth-toolkit">Django OAuth Toolkit</a> package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by <a href="https://github.com/evonove/">Evonove</a> and uses the excelllent <a href="https://github.com/idan/oauthlib">OAuthLib</a>. The package is well documented, and comes as a recommended alternative for OAuth 2.0 support.</p>
+<p>The <a href="https://github.com/evonove/django-oauth-toolkit">Django OAuth Toolkit</a> package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by <a href="https://github.com/evonove/">Evonove</a> and uses the excellent <a href="https://github.com/idan/oauthlib">OAuthLib</a>. The package is well documented, and comes as a recommended alternative for OAuth 2.0 support.</p>
<h2 id="django-oauth2-consumer">Django OAuth2 Consumer</h2>
<p>The <a href="https://github.com/Rediker-Software/doac">Django OAuth2 Consumer</a> library from <a href="https://github.com/Rediker-Software">Rediker Software</a> is another package that provides <a href="https://github.com/Rediker-Software/doac/blob/master/docs/integrations.md#">OAuth 2.0 support for REST framework</a>. The package includes token scoping permissions on tokens, which allows finer-grained access to your API.</p>
<h2 id="json-web-token-authentication">JSON Web Token Authentication</h2>
@@ -513,42 +751,52 @@ class ExampleAuthentication(authentication.BaseAuthentication):
<p>HTTP Signature (currently a <a href="https://datatracker.ietf.org/doc/draft-cavage-http-signatures/">IETF draft</a>) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to <a href="http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html">Amazon's HTTP Signature scheme</a>, used by many of its services, it permits stateless, per-request authentication. <a href="https://github.com/etoccalino/">Elvio Toccalino</a> maintains the <a href="https://github.com/etoccalino/django-rest-framework-httpsignature">djangorestframework-httpsignature</a> package which provides an easy to use HTTP Signature Authentication mechanism.</p>
<h2 id="djoser">Djoser</h2>
<p><a href="https://github.com/sunscrapers/djoser">Djoser</a> library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and it uses token based authentication. This is a ready to use REST implementation of Django authentication system.</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/api-guide/content-negotiation.html b/api-guide/content-negotiation.html
deleted file mode 100644
index abb639f4..00000000
--- a/api-guide/content-negotiation.html
+++ /dev/null
@@ -1,315 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Content negotiation - 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/api-guide/content-negotiation"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Content negotiation, Custom content negotiation">
- <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="content-negotiation-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="../api-guide/format-suffixes">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/pagination"><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="#content-negotiation">Content negotiation</a></li>
-<li><a href="#determining-the-accepted-renderer">Determining the accepted renderer</a></li>
-<li class="main"><a href="#custom-content-negotiation">Custom content negotiation</a></li>
-<li><a href="#example">Example</a></li>
-<li><a href="#setting-the-content-negotiation">Setting the content negotiation</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/negotiation.py"><span class="label label-info">negotiation.py</span></a></p>
-<h1 id="content-negotiation">Content negotiation</h1>
-<blockquote>
-<p>HTTP has provisions for several mechanisms for "content negotiation" - the process of selecting the best representation for a given response when there are multiple representations available.</p>
-<p>&mdash; <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html">RFC 2616</a>, Fielding et al.</p>
-</blockquote>
-<p>Content negotiation is the process of selecting one of multiple possible representations to return to a client, based on client or server preferences.</p>
-<h2 id="determining-the-accepted-renderer">Determining the accepted renderer</h2>
-<p>REST framework uses a simple style of content negotiation to determine which media type should be returned to a client, based on the available renderers, the priorities of each of those renderers, and the client's <code>Accept:</code> header. The style used is partly client-driven, and partly server-driven.</p>
-<ol>
-<li>More specific media types are given preference to less specific media types.</li>
-<li>If multiple media types have the same specificity, then preference is given to based on the ordering of the renderers configured for the given view.</li>
-</ol>
-<p>For example, given the following <code>Accept</code> header:</p>
-<pre class="prettyprint lang-py"><code>application/json; indent=4, application/json, application/yaml, text/html, */*
-</code></pre>
-<p>The priorities for each of the given media types would be:</p>
-<ul>
-<li><code>application/json; indent=4</code></li>
-<li><code>application/json</code>, <code>application/yaml</code> and <code>text/html</code></li>
-<li><code>*/*</code></li>
-</ul>
-<p>If the requested view was only configured with renderers for <code>YAML</code> and <code>HTML</code>, then REST framework would select whichever renderer was listed first in the <code>renderer_classes</code> list or <code>DEFAULT_RENDERER_CLASSES</code> setting.</p>
-<p>For more information on the <code>HTTP Accept</code> header, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">RFC 2616</a> </p>
-<hr />
-<p><strong>Note</strong>: "q" values are not taken into account by REST framework when determining preference. The use of "q" values negatively impacts caching, and in the author's opinion they are an unnecessary and overcomplicated approach to content negotiation.</p>
-<p>This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.</p>
-<hr />
-<h1 id="custom-content-negotiation">Custom content negotiation</h1>
-<p>It's unlikely that you'll want to provide a custom content negotiation scheme for REST framework, but you can do so if needed. To implement a custom content negotiation scheme override <code>BaseContentNegotiation</code>.</p>
-<p>REST framework's content negotiation classes handle selection of both the appropriate parser for the request, and the appropriate renderer for the response, so you should implement both the <code>.select_parser(request, parsers)</code> and <code>.select_renderer(request, renderers, format_suffix)</code> methods.</p>
-<p>The <code>select_parser()</code> method should return one of the parser instances from the list of available parsers, or <code>None</code> if none of the parsers can handle the incoming request.</p>
-<p>The <code>select_renderer()</code> method should return a two-tuple of (renderer instance, media type), or raise a <code>NotAcceptable</code> exception.</p>
-<h2 id="example">Example</h2>
-<p>The following is a custom content negotiation class which ignores the client
-request when selecting the appropriate parser or renderer.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.negotiation import BaseContentNegotiation
-
-class IgnoreClientContentNegotiation(BaseContentNegotiation):
- def select_parser(self, request, parsers):
- """
- Select the first parser in the `.parser_classes` list.
- """
- return parsers[0]
-
- def select_renderer(self, request, renderers, format_suffix):
- """
- Select the first renderer in the `.renderer_classes` list.
- """
- return (renderers[0], renderers[0].media_type)
-</code></pre>
-<h2 id="setting-the-content-negotiation">Setting the content negotiation</h2>
-<p>The default content negotiation class may be set globally, using the <code>DEFAULT_CONTENT_NEGOTIATION_CLASS</code> setting. For example, the following settings would use our example <code>IgnoreClientContentNegotiation</code> class.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'myapp.negotiation.IgnoreClientContentNegotiation',
-}
-</code></pre>
-<p>You can also set the content negotiation used for an individual view, or viewset, using the <code>APIView</code> class based views.</p>
-<pre class="prettyprint lang-py"><code>from myapp.negotiation import IgnoreClientContentNegotiation
-from rest_framework.response import Response
-from rest_framework.views import APIView
-
-class NoNegotiationView(APIView):
- """
- An example view that does not perform content negotiation.
- """
- content_negotiation_class = IgnoreClientContentNegotiation
-
- def get(self, request, format=None):
- return Response({
- 'accepted media type': request.accepted_renderer.media_type
- })
-</code></pre>
- </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/api-guide/content-negotiation/index.html b/api-guide/content-negotiation/index.html
new file mode 100644
index 00000000..160ef261
--- /dev/null
+++ b/api-guide/content-negotiation/index.html
@@ -0,0 +1,507 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Content negotiation - 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/api-guide/content-negotiation/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Content negotiation">
+ <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="../format-suffixes">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../pagination">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#content-negotiation">Content negotiation</a>
+ </li>
+
+
+ <li>
+ <a href="#determining-the-accepted-renderer">Determining the accepted renderer</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-content-negotiation">Custom content negotiation</a>
+ </li>
+
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+ <li>
+ <a href="#setting-the-content-negotiation">Setting the content negotiation</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/negotiation.py">
+ <span class="label label-info">negotiation.py</span>
+ </a>
+
+
+
+ <h1 id="content-negotiation">Content negotiation</h1>
+<blockquote>
+<p>HTTP has provisions for several mechanisms for "content negotiation" - the process of selecting the best representation for a given response when there are multiple representations available.</p>
+<p>&mdash; <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html">RFC 2616</a>, Fielding et al.</p>
+</blockquote>
+<p>Content negotiation is the process of selecting one of multiple possible representations to return to a client, based on client or server preferences.</p>
+<h2 id="determining-the-accepted-renderer">Determining the accepted renderer</h2>
+<p>REST framework uses a simple style of content negotiation to determine which media type should be returned to a client, based on the available renderers, the priorities of each of those renderers, and the client's <code>Accept:</code> header. The style used is partly client-driven, and partly server-driven.</p>
+<ol>
+<li>More specific media types are given preference to less specific media types.</li>
+<li>If multiple media types have the same specificity, then preference is given to based on the ordering of the renderers configured for the given view.</li>
+</ol>
+<p>For example, given the following <code>Accept</code> header:</p>
+<pre><code>application/json; indent=4, application/json, application/yaml, text/html, */*
+</code></pre>
+<p>The priorities for each of the given media types would be:</p>
+<ul>
+<li><code>application/json; indent=4</code></li>
+<li><code>application/json</code>, <code>application/yaml</code> and <code>text/html</code></li>
+<li><code>*/*</code></li>
+</ul>
+<p>If the requested view was only configured with renderers for <code>YAML</code> and <code>HTML</code>, then REST framework would select whichever renderer was listed first in the <code>renderer_classes</code> list or <code>DEFAULT_RENDERER_CLASSES</code> setting.</p>
+<p>For more information on the <code>HTTP Accept</code> header, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">RFC 2616</a></p>
+<hr />
+<p><strong>Note</strong>: "q" values are not taken into account by REST framework when determining preference. The use of "q" values negatively impacts caching, and in the author's opinion they are an unnecessary and overcomplicated approach to content negotiation.</p>
+<p>This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences.</p>
+<hr />
+<h1 id="custom-content-negotiation">Custom content negotiation</h1>
+<p>It's unlikely that you'll want to provide a custom content negotiation scheme for REST framework, but you can do so if needed. To implement a custom content negotiation scheme override <code>BaseContentNegotiation</code>.</p>
+<p>REST framework's content negotiation classes handle selection of both the appropriate parser for the request, and the appropriate renderer for the response, so you should implement both the <code>.select_parser(request, parsers)</code> and <code>.select_renderer(request, renderers, format_suffix)</code> methods.</p>
+<p>The <code>select_parser()</code> method should return one of the parser instances from the list of available parsers, or <code>None</code> if none of the parsers can handle the incoming request.</p>
+<p>The <code>select_renderer()</code> method should return a two-tuple of (renderer instance, media type), or raise a <code>NotAcceptable</code> exception.</p>
+<h2 id="example">Example</h2>
+<p>The following is a custom content negotiation class which ignores the client
+request when selecting the appropriate parser or renderer.</p>
+<pre><code>from rest_framework.negotiation import BaseContentNegotiation
+
+class IgnoreClientContentNegotiation(BaseContentNegotiation):
+ def select_parser(self, request, parsers):
+ """
+ Select the first parser in the `.parser_classes` list.
+ """
+ return parsers[0]
+
+ def select_renderer(self, request, renderers, format_suffix):
+ """
+ Select the first renderer in the `.renderer_classes` list.
+ """
+ return (renderers[0], renderers[0].media_type)
+</code></pre>
+<h2 id="setting-the-content-negotiation">Setting the content negotiation</h2>
+<p>The default content negotiation class may be set globally, using the <code>DEFAULT_CONTENT_NEGOTIATION_CLASS</code> setting. For example, the following settings would use our example <code>IgnoreClientContentNegotiation</code> class.</p>
+<pre><code>REST_FRAMEWORK = {
+ 'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'myapp.negotiation.IgnoreClientContentNegotiation',
+}
+</code></pre>
+<p>You can also set the content negotiation used for an individual view, or viewset, using the <code>APIView</code> class based views.</p>
+<pre><code>from myapp.negotiation import IgnoreClientContentNegotiation
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+class NoNegotiationView(APIView):
+ """
+ An example view that does not perform content negotiation.
+ """
+ content_negotiation_class = IgnoreClientContentNegotiation
+
+ def get(self, request, format=None):
+ return Response({
+ 'accepted media type': request.accepted_renderer.media_type
+ })
+</code></pre>
+
+ </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/api-guide/exceptions.html b/api-guide/exceptions.html
deleted file mode 100644
index adbf5b88..00000000
--- a/api-guide/exceptions.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Exceptions - 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/api-guide/exceptions"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Exceptions, API Reference">
- <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="exceptions-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="../api-guide/status-codes">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/reverse"><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="#exceptions">Exceptions</a></li>
-<li><a href="#exception-handling-in-rest-framework-views">Exception handling in REST framework views</a></li>
-<li><a href="#custom-exception-handling">Custom exception handling</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#apiexception">APIException</a></li>
-<li><a href="#parseerror">ParseError</a></li>
-<li><a href="#authenticationfailed">AuthenticationFailed</a></li>
-<li><a href="#notauthenticated">NotAuthenticated</a></li>
-<li><a href="#permissiondenied">PermissionDenied</a></li>
-<li><a href="#methodnotallowed">MethodNotAllowed</a></li>
-<li><a href="#unsupportedmediatype">UnsupportedMediaType</a></li>
-<li><a href="#throttled">Throttled</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/exceptions.py"><span class="label label-info">exceptions.py</span></a></p>
-<h1 id="exceptions">Exceptions</h1>
-<blockquote>
-<p>Exceptions… allow error handling to be organized cleanly in a central or high-level place within the program structure.</p>
-<p>&mdash; Doug Hellmann, <a href="http://www.doughellmann.com/articles/how-tos/python-exception-handling/index.html">Python Exception Handling Techniques</a></p>
-</blockquote>
-<h2 id="exception-handling-in-rest-framework-views">Exception handling in REST framework views</h2>
-<p>REST framework's views handle various exceptions, and deal with returning appropriate error responses.</p>
-<p>The handled exceptions are:</p>
-<ul>
-<li>Subclasses of <code>APIException</code> raised inside REST framework.</li>
-<li>Django's <code>Http404</code> exception.</li>
-<li>Django's <code>PermissionDenied</code> exception.</li>
-</ul>
-<p>In each case, REST framework will return a response with an appropriate status code and content-type. The body of the response will include any additional details regarding the nature of the error.</p>
-<p>By default all error responses will include a key <code>detail</code> in the body of the response, but other keys may also be included.</p>
-<p>For example, the following request:</p>
-<pre class="prettyprint lang-py"><code>DELETE http://api.example.com/foo/bar HTTP/1.1
-Accept: application/json
-</code></pre>
-<p>Might receive an error response indicating that the <code>DELETE</code> method is not allowed on that resource:</p>
-<pre class="prettyprint lang-py"><code>HTTP/1.1 405 Method Not Allowed
-Content-Type: application/json
-Content-Length: 42
-
-{"detail": "Method 'DELETE' not allowed."}
-</code></pre>
-<h2 id="custom-exception-handling">Custom exception handling</h2>
-<p>You can implement custom exception handling by creating a handler function that converts exceptions raised in your API views into response objects. This allows you to control the style of error responses used by your API.</p>
-<p>The function must take a single argument, which is the exception to be handled, and should either return a <code>Response</code> object, or return <code>None</code> if the exception cannot be handled. If the handler returns <code>None</code> then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.</p>
-<p>For example, you might want to ensure that all error responses include the HTTP status code in the body of the response, like so:</p>
-<pre class="prettyprint lang-py"><code>HTTP/1.1 405 Method Not Allowed
-Content-Type: application/json
-Content-Length: 62
-
-{"status_code": 405, "detail": "Method 'DELETE' not allowed."}
-</code></pre>
-<p>In order to alter the style of the response, you could write the following custom exception handler:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.views import exception_handler
-
-def custom_exception_handler(exc):
- # Call REST framework's default exception handler first,
- # to get the standard error response.
- response = exception_handler(exc)
-
- # Now add the HTTP status code to the response.
- if response is not None:
- response.data['status_code'] = response.status_code
-
- return response
-</code></pre>
-<p>The exception handler must also be configured in your settings, using the <code>EXCEPTION_HANDLER</code> setting key. For example:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
-}
-</code></pre>
-<p>If not specified, the <code>'EXCEPTION_HANDLER'</code> setting defaults to the standard exception handler provided by REST framework:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
-}
-</code></pre>
-<p>Note that the exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the <code>HTTP_400_BAD_REQUEST</code> responses that are returned by the generic views when serializer validation fails.</p>
-<hr />
-<h1 id="api-reference">API Reference</h1>
-<h2 id="apiexception">APIException</h2>
-<p><strong>Signature:</strong> <code>APIException()</code></p>
-<p>The <strong>base class</strong> for all exceptions raised inside an <code>APIView</code> class or <code>@api_view</code>.</p>
-<p>To provide a custom exception, subclass <code>APIException</code> and set the <code>.status_code</code> and <code>.default_detail</code> properties on the class.</p>
-<p>For example, if your API relies on a third party service that may sometimes be unreachable, you might want to implement an exception for the "503 Service Unavailable" HTTP response code. You could do this like so:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.exceptions import APIException
-
-class ServiceUnavailable(APIException):
- status_code = 503
- default_detail = 'Service temporarily unavailable, try again later.'
-</code></pre>
-<h2 id="parseerror">ParseError</h2>
-<p><strong>Signature:</strong> <code>ParseError(detail=None)</code></p>
-<p>Raised if the request contains malformed data when accessing <code>request.DATA</code> or <code>request.FILES</code>.</p>
-<p>By default this exception results in a response with the HTTP status code "400 Bad Request".</p>
-<h2 id="authenticationfailed">AuthenticationFailed</h2>
-<p><strong>Signature:</strong> <code>AuthenticationFailed(detail=None)</code></p>
-<p>Raised when an incoming request includes incorrect authentication.</p>
-<p>By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the <a href="authentication">authentication documentation</a> for more details.</p>
-<h2 id="notauthenticated">NotAuthenticated</h2>
-<p><strong>Signature:</strong> <code>NotAuthenticated(detail=None)</code></p>
-<p>Raised when an unauthenticated request fails the permission checks.</p>
-<p>By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the <a href="authentication">authentication documentation</a> for more details.</p>
-<h2 id="permissiondenied">PermissionDenied</h2>
-<p><strong>Signature:</strong> <code>PermissionDenied(detail=None)</code></p>
-<p>Raised when an authenticated request fails the permission checks.</p>
-<p>By default this exception results in a response with the HTTP status code "403 Forbidden".</p>
-<h2 id="methodnotallowed">MethodNotAllowed</h2>
-<p><strong>Signature:</strong> <code>MethodNotAllowed(method, detail=None)</code></p>
-<p>Raised when an incoming request occurs that does not map to a handler method on the view.</p>
-<p>By default this exception results in a response with the HTTP status code "405 Method Not Allowed".</p>
-<h2 id="unsupportedmediatype">UnsupportedMediaType</h2>
-<p><strong>Signature:</strong> <code>UnsupportedMediaType(media_type, detail=None)</code></p>
-<p>Raised if there are no parsers that can handle the content type of the request data when accessing <code>request.DATA</code> or <code>request.FILES</code>.</p>
-<p>By default this exception results in a response with the HTTP status code "415 Unsupported Media Type".</p>
-<h2 id="throttled">Throttled</h2>
-<p><strong>Signature:</strong> <code>Throttled(wait=None, detail=None)</code></p>
-<p>Raised when an incoming request fails the throttling checks.</p>
-<p>By default this exception results in a response with the HTTP status code "429 Too Many Requests".</p>
- </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/api-guide/exceptions/index.html b/api-guide/exceptions/index.html
new file mode 100644
index 00000000..4857a7d4
--- /dev/null
+++ b/api-guide/exceptions/index.html
@@ -0,0 +1,565 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Exceptions - 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/api-guide/exceptions/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Exceptions">
+ <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="../status-codes">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../reverse">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#exceptions">Exceptions</a>
+ </li>
+
+
+ <li>
+ <a href="#exception-handling-in-rest-framework-views">Exception handling in REST framework views</a>
+ </li>
+
+ <li>
+ <a href="#custom-exception-handling">Custom exception handling</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#apiexception">APIException</a>
+ </li>
+
+ <li>
+ <a href="#parseerror">ParseError</a>
+ </li>
+
+ <li>
+ <a href="#authenticationfailed">AuthenticationFailed</a>
+ </li>
+
+ <li>
+ <a href="#notauthenticated">NotAuthenticated</a>
+ </li>
+
+ <li>
+ <a href="#permissiondenied">PermissionDenied</a>
+ </li>
+
+ <li>
+ <a href="#methodnotallowed">MethodNotAllowed</a>
+ </li>
+
+ <li>
+ <a href="#unsupportedmediatype">UnsupportedMediaType</a>
+ </li>
+
+ <li>
+ <a href="#throttled">Throttled</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/exceptions.py">
+ <span class="label label-info">exceptions.py</span>
+ </a>
+
+
+
+ <h1 id="exceptions">Exceptions</h1>
+<blockquote>
+<p>Exceptions… allow error handling to be organized cleanly in a central or high-level place within the program structure.</p>
+<p>&mdash; Doug Hellmann, <a href="http://www.doughellmann.com/articles/how-tos/python-exception-handling/index.html">Python Exception Handling Techniques</a></p>
+</blockquote>
+<h2 id="exception-handling-in-rest-framework-views">Exception handling in REST framework views</h2>
+<p>REST framework's views handle various exceptions, and deal with returning appropriate error responses.</p>
+<p>The handled exceptions are:</p>
+<ul>
+<li>Subclasses of <code>APIException</code> raised inside REST framework.</li>
+<li>Django's <code>Http404</code> exception.</li>
+<li>Django's <code>PermissionDenied</code> exception.</li>
+</ul>
+<p>In each case, REST framework will return a response with an appropriate status code and content-type. The body of the response will include any additional details regarding the nature of the error.</p>
+<p>By default all error responses will include a key <code>detail</code> in the body of the response, but other keys may also be included.</p>
+<p>For example, the following request:</p>
+<pre><code>DELETE http://api.example.com/foo/bar HTTP/1.1
+Accept: application/json
+</code></pre>
+<p>Might receive an error response indicating that the <code>DELETE</code> method is not allowed on that resource:</p>
+<pre><code>HTTP/1.1 405 Method Not Allowed
+Content-Type: application/json
+Content-Length: 42
+
+{"detail": "Method 'DELETE' not allowed."}
+</code></pre>
+<h2 id="custom-exception-handling">Custom exception handling</h2>
+<p>You can implement custom exception handling by creating a handler function that converts exceptions raised in your API views into response objects. This allows you to control the style of error responses used by your API.</p>
+<p>The function must take a single argument, which is the exception to be handled, and should either return a <code>Response</code> object, or return <code>None</code> if the exception cannot be handled. If the handler returns <code>None</code> then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.</p>
+<p>For example, you might want to ensure that all error responses include the HTTP status code in the body of the response, like so:</p>
+<pre><code>HTTP/1.1 405 Method Not Allowed
+Content-Type: application/json
+Content-Length: 62
+
+{"status_code": 405, "detail": "Method 'DELETE' not allowed."}
+</code></pre>
+<p>In order to alter the style of the response, you could write the following custom exception handler:</p>
+<pre><code>from rest_framework.views import exception_handler
+
+def custom_exception_handler(exc):
+ # Call REST framework's default exception handler first,
+ # to get the standard error response.
+ response = exception_handler(exc)
+
+ # Now add the HTTP status code to the response.
+ if response is not None:
+ response.data['status_code'] = response.status_code
+
+ return response
+</code></pre>
+<p>The exception handler must also be configured in your settings, using the <code>EXCEPTION_HANDLER</code> setting key. For example:</p>
+<pre><code>REST_FRAMEWORK = {
+ 'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
+}
+</code></pre>
+<p>If not specified, the <code>'EXCEPTION_HANDLER'</code> setting defaults to the standard exception handler provided by REST framework:</p>
+<pre><code>REST_FRAMEWORK = {
+ 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
+}
+</code></pre>
+<p>Note that the exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the <code>HTTP_400_BAD_REQUEST</code> responses that are returned by the generic views when serializer validation fails.</p>
+<hr />
+<h1 id="api-reference">API Reference</h1>
+<h2 id="apiexception">APIException</h2>
+<p><strong>Signature:</strong> <code>APIException()</code></p>
+<p>The <strong>base class</strong> for all exceptions raised inside an <code>APIView</code> class or <code>@api_view</code>.</p>
+<p>To provide a custom exception, subclass <code>APIException</code> and set the <code>.status_code</code> and <code>.default_detail</code> properties on the class.</p>
+<p>For example, if your API relies on a third party service that may sometimes be unreachable, you might want to implement an exception for the "503 Service Unavailable" HTTP response code. You could do this like so:</p>
+<pre><code>from rest_framework.exceptions import APIException
+
+class ServiceUnavailable(APIException):
+ status_code = 503
+ default_detail = 'Service temporarily unavailable, try again later.'
+</code></pre>
+<h2 id="parseerror">ParseError</h2>
+<p><strong>Signature:</strong> <code>ParseError(detail=None)</code></p>
+<p>Raised if the request contains malformed data when accessing <code>request.DATA</code> or <code>request.FILES</code>.</p>
+<p>By default this exception results in a response with the HTTP status code "400 Bad Request".</p>
+<h2 id="authenticationfailed">AuthenticationFailed</h2>
+<p><strong>Signature:</strong> <code>AuthenticationFailed(detail=None)</code></p>
+<p>Raised when an incoming request includes incorrect authentication.</p>
+<p>By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the <a href="../authentication">authentication documentation</a> for more details.</p>
+<h2 id="notauthenticated">NotAuthenticated</h2>
+<p><strong>Signature:</strong> <code>NotAuthenticated(detail=None)</code></p>
+<p>Raised when an unauthenticated request fails the permission checks.</p>
+<p>By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the <a href="../authentication">authentication documentation</a> for more details.</p>
+<h2 id="permissiondenied">PermissionDenied</h2>
+<p><strong>Signature:</strong> <code>PermissionDenied(detail=None)</code></p>
+<p>Raised when an authenticated request fails the permission checks.</p>
+<p>By default this exception results in a response with the HTTP status code "403 Forbidden".</p>
+<h2 id="methodnotallowed">MethodNotAllowed</h2>
+<p><strong>Signature:</strong> <code>MethodNotAllowed(method, detail=None)</code></p>
+<p>Raised when an incoming request occurs that does not map to a handler method on the view.</p>
+<p>By default this exception results in a response with the HTTP status code "405 Method Not Allowed".</p>
+<h2 id="unsupportedmediatype">UnsupportedMediaType</h2>
+<p><strong>Signature:</strong> <code>UnsupportedMediaType(media_type, detail=None)</code></p>
+<p>Raised if there are no parsers that can handle the content type of the request data when accessing <code>request.DATA</code> or <code>request.FILES</code>.</p>
+<p>By default this exception results in a response with the HTTP status code "415 Unsupported Media Type".</p>
+<h2 id="throttled">Throttled</h2>
+<p><strong>Signature:</strong> <code>Throttled(wait=None, detail=None)</code></p>
+<p>Raised when an incoming request fails the throttling checks.</p>
+<p>By default this exception results in a response with the HTTP status code "429 Too Many Requests".</p>
+
+ </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/api-guide/fields.html b/api-guide/fields/index.html
index 7ba5ac31..c27962bc 100644
--- a/api-guide/fields.html
+++ b/api-guide/fields/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>Serializer fields - 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/api-guide/fields"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Serializer fields, Generic Fields, Typed Fields, Custom fields, 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="fields-page">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Serializer fields - 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/api-guide/fields/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Serializer fields">
+ <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="../api-guide/relations">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/serializers"><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="../relations">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../serializers">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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,48 +335,168 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#serializer-fields">Serializer fields</a></li>
-<li><a href="#core-arguments">Core arguments</a></li>
-<li class="main"><a href="#generic-fields">Generic Fields</a></li>
-<li><a href="#field">Field</a></li>
-<li><a href="#writablefield">WritableField</a></li>
-<li><a href="#modelfield">ModelField</a></li>
-<li><a href="#serializermethodfield">SerializerMethodField</a></li>
-<li class="main"><a href="#typed-fields">Typed Fields</a></li>
-<li><a href="#booleanfield">BooleanField</a></li>
-<li><a href="#charfield">CharField</a></li>
-<li><a href="#urlfield">URLField</a></li>
-<li><a href="#slugfield">SlugField</a></li>
-<li><a href="#choicefield">ChoiceField</a></li>
-<li><a href="#emailfield">EmailField</a></li>
-<li><a href="#regexfield">RegexField</a></li>
-<li><a href="#datetimefield">DateTimeField</a></li>
-<li><a href="#datefield">DateField</a></li>
-<li><a href="#timefield">TimeField</a></li>
-<li><a href="#integerfield">IntegerField</a></li>
-<li><a href="#floatfield">FloatField</a></li>
-<li><a href="#decimalfield">DecimalField</a></li>
-<li><a href="#filefield">FileField</a></li>
-<li><a href="#imagefield">ImageField</a></li>
-<li class="main"><a href="#custom-fields">Custom fields</a></li>
-<li><a href="#examples">Examples</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#drf-compound-fields">DRF Compound Fields</a></li>
-<li><a href="#drf-extra-fields">DRF Extra Fields</a></li>
-<li><a href="#django-rest-framework-gis">django-rest-framework-gis</a></li>
-<li><a href="#django-rest-framework-hstore">django-rest-framework-hstore</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#serializer-fields">Serializer fields</a>
+ </li>
+
+
+ <li>
+ <a href="#core-arguments">Core arguments</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#generic-fields">Generic Fields</a>
+ </li>
+
+
+ <li>
+ <a href="#field">Field</a>
+ </li>
+
+ <li>
+ <a href="#writablefield">WritableField</a>
+ </li>
+
+ <li>
+ <a href="#modelfield">ModelField</a>
+ </li>
+
+ <li>
+ <a href="#serializermethodfield">SerializerMethodField</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#typed-fields">Typed Fields</a>
+ </li>
+
+
+ <li>
+ <a href="#booleanfield">BooleanField</a>
+ </li>
+
+ <li>
+ <a href="#charfield">CharField</a>
+ </li>
+
+ <li>
+ <a href="#urlfield">URLField</a>
+ </li>
+
+ <li>
+ <a href="#slugfield">SlugField</a>
+ </li>
+
+ <li>
+ <a href="#choicefield">ChoiceField</a>
+ </li>
+
+ <li>
+ <a href="#emailfield">EmailField</a>
+ </li>
+
+ <li>
+ <a href="#regexfield">RegexField</a>
+ </li>
+
+ <li>
+ <a href="#datetimefield">DateTimeField</a>
+ </li>
+
+ <li>
+ <a href="#datefield">DateField</a>
+ </li>
+
+ <li>
+ <a href="#timefield">TimeField</a>
+ </li>
+
+ <li>
+ <a href="#integerfield">IntegerField</a>
+ </li>
+
+ <li>
+ <a href="#floatfield">FloatField</a>
+ </li>
+
+ <li>
+ <a href="#decimalfield">DecimalField</a>
+ </li>
+
+ <li>
+ <a href="#filefield">FileField</a>
+ </li>
+
+ <li>
+ <a href="#imagefield">ImageField</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-fields">Custom fields</a>
+ </li>
+
+
+ <li>
+ <a href="#examples">Examples</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#drf-compound-fields">DRF Compound Fields</a>
+ </li>
+
+ <li>
+ <a href="#drf-extra-fields">DRF Extra Fields</a>
+ </li>
+
+ <li>
+ <a href="#django-rest-framework-gis">django-rest-framework-gis</a>
+ </li>
+
+ <li>
+ <a href="#django-rest-framework-hstore">django-rest-framework-hstore</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/fields.py"><span class="label label-info">fields.py</span></a></p>
-<h1 id="serializer-fields">Serializer fields</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/fields.py">
+ <span class="label label-info">fields.py</span>
+ </a>
+
+
+
+ <h1 id="serializer-fields">Serializer fields</h1>
<blockquote>
<p>Each field in a Form class is responsible not only for validating data, but also for "cleaning" it &mdash; normalizing it to a consistent format.</p>
<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.cleaned_data">Django documentation</a></p>
@@ -261,7 +530,7 @@ Set to false if this field is not required to be present during deserialization.
<p>A dictionary of error codes to error messages.</p>
<h3 id="widget"><code>widget</code></h3>
<p>Used only if rendering the field to HTML.
-This argument sets the widget that should be used to render the field. For more details, and a list of available widgets, see <a href="https://docs.djangoproject.com/en/dev/ref/forms/widgets/">the Django documentation on form widgets</a>. </p>
+This argument sets the widget that should be used to render the field. For more details, and a list of available widgets, see <a href="https://docs.djangoproject.com/en/dev/ref/forms/widgets/">the Django documentation on form widgets</a>.</p>
<h3 id="label"><code>label</code></h3>
<p>A short text string that may be used as the name of the field in HTML form fields or other descriptive elements.</p>
<h3 id="help_text"><code>help_text</code></h3>
@@ -272,7 +541,7 @@ This argument sets the widget that should be used to render the field. For more
<h2 id="field">Field</h2>
<p>A generic, <strong>read-only</strong> field. You can use this field for any attribute that does not need to support write operations.</p>
<p>For example, using the following model.</p>
-<pre class="prettyprint lang-py"><code>from django.db import models
+<pre><code>from django.db import models
from django.utils.timezone import now
class Account(models.Model):
@@ -285,7 +554,7 @@ class Account(models.Model):
return now() &gt; self.payment_expiry
</code></pre>
<p>A serializer definition that looked like this:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import serializers
+<pre><code>from rest_framework import serializers
class AccountSerializer(serializers.HyperlinkedModelSerializer):
expired = serializers.Field(source='has_expired')
@@ -295,7 +564,7 @@ class AccountSerializer(serializers.HyperlinkedModelSerializer):
fields = ('url', 'owner', 'name', 'expired')
</code></pre>
<p>Would produce output similar to:</p>
-<pre class="prettyprint lang-py"><code>{
+<pre><code>{
'url': 'http://example.com/api/accounts/3/',
'owner': 'http://example.com/api/users/12/',
'name': 'FooCorp business account',
@@ -312,7 +581,7 @@ class AccountSerializer(serializers.HyperlinkedModelSerializer):
<p><strong>Signature:</strong> <code>ModelField(model_field=&lt;Django ModelField instance&gt;)</code></p>
<h2 id="serializermethodfield">SerializerMethodField</h2>
<p>This is a read-only field. It gets its value by calling a method on the serializer class it is attached to. It can be used to add any sort of data to the serialized representation of your object. The field's constructor accepts a single argument, which is the name of the method on the serializer to be called. The method should accept a single argument (in addition to <code>self</code>), which is the object being serialized. It should return whatever you want to be included in the serialized representation of the object. For example:</p>
-<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
+<pre><code>from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
@@ -359,7 +628,7 @@ or <code>django.db.models.fields.TextField</code>.</p>
<p>Corresponds to <code>django.db.models.fields.DateTimeField</code></p>
<p>When using <code>ModelSerializer</code> or <code>HyperlinkedModelSerializer</code>, note that any model fields with <code>auto_now=True</code> or <code>auto_now_add=True</code> will use serializer fields that are <code>read_only=True</code> by default.</p>
<p>If you want to override this behavior, you'll need to declare the <code>DateTimeField</code> explicitly on the serializer. For example:</p>
-<pre class="prettyprint lang-py"><code>class CommentSerializer(serializers.ModelSerializer):
+<pre><code>class CommentSerializer(serializers.ModelSerializer):
created = serializers.DateTimeField()
class Meta:
@@ -399,7 +668,25 @@ or <code>django.db.models.fields.TextField</code>.</p>
<p>A floating point representation.</p>
<p>Corresponds to <code>django.db.models.fields.FloatField</code>.</p>
<h2 id="decimalfield">DecimalField</h2>
-<p>A decimal representation.</p>
+<p>A decimal representation, represented in Python by a Decimal instance.</p>
+<p>Has two required arguments:</p>
+<ul>
+<li>
+<p><code>max_digits</code> The maximum number of digits allowed in the number. Note that this number must be greater than or equal to decimal_places.</p>
+</li>
+<li>
+<p><code>decimal_places</code> The number of decimal places to store with the number.</p>
+</li>
+</ul>
+<p>For example, to validate numbers up to 999 with a resolution of 2 decimal places, you would use:</p>
+<pre><code>serializers.DecimalField(max_digits=5, decimal_places=2)
+</code></pre>
+<p>And to validate numbers up to anything less than one billion with a resolution of 10 decimal places:</p>
+<pre><code>serializers.DecimalField(max_digits=19, decimal_places=10)
+</code></pre>
+<p>This field also takes an optional argument, <code>coerce_to_string</code>. If set to <code>True</code> the representation will be output as a string. If set to <code>False</code> the representation will be left as a <code>Decimal</code> instance and the final representation will be determined by the renderer.</p>
+<p>If unset, this will default to the same value as the <code>COERCE_DECIMAL_TO_STRING</code> setting, which is <code>True</code> unless set otherwise.</p>
+<p><strong>Signature:</strong> <code>DecimalField(max_digits, decimal_places, coerce_to_string=None)</code></p>
<p>Corresponds to <code>django.db.models.fields.DecimalField</code>.</p>
<h2 id="filefield">FileField</h2>
<p>A file representation. Performs Django's standard FileField validation.</p>
@@ -427,7 +714,7 @@ Django's regular <a href="https://docs.djangoproject.com/en/dev/ref/settings/#st
<p>The <code>.to_native()</code> method is called to convert the initial datatype into a primitive, serializable datatype. The <code>from_native()</code> method is called to restore a primitive datatype into its initial representation.</p>
<h2 id="examples">Examples</h2>
<p>Let's look at an example of serializing a class that represents an RGB color value:</p>
-<pre class="prettyprint lang-py"><code>class Color(object):
+<pre><code>class Color(object):
"""
A color represented in the RGB colorspace.
"""
@@ -450,7 +737,7 @@ class ColourField(serializers.WritableField):
</code></pre>
<p>By default field values are treated as mapping to an attribute on the object. If you need to customize how the field value is accessed and set you need to override <code>.field_to_native()</code> and/or <code>.field_from_native()</code>.</p>
<p>As an example, let's create a field that can be used represent the class name of the object being serialized:</p>
-<pre class="prettyprint lang-py"><code>class ClassNameField(serializers.Field):
+<pre><code>class ClassNameField(serializers.Field):
def field_to_native(self, obj, field_name):
"""
Serialize the object's class name.
@@ -467,42 +754,52 @@ class ColourField(serializers.WritableField):
<p>The <a href="https://github.com/djangonauts/django-rest-framework-gis">django-rest-framework-gis</a> package provides geographic addons for django rest framework like a <code>GeometryField</code> field and a GeoJSON serializer.</p>
<h2 id="django-rest-framework-hstore">django-rest-framework-hstore</h2>
<p>The <a href="https://github.com/djangonauts/django-rest-framework-hstore">django-rest-framework-hstore</a> package provides an <code>HStoreField</code> to support <a href="https://github.com/djangonauts/django-hstore">django-hstore</a> <code>DictionaryField</code> model field.</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/api-guide/filtering.html b/api-guide/filtering/index.html
index fe7da879..eb56e051 100644
--- a/api-guide/filtering.html
+++ b/api-guide/filtering/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>Filtering - 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/api-guide/filtering"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Filtering, Generic Filtering, API Guide, Custom generic filtering, 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="filtering-page">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Filtering - 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/api-guide/filtering/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Filtering">
+ <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="../api-guide/pagination">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/throttling"><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="../pagination">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../throttling">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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,35 +335,116 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#filtering">Filtering</a></li>
-<li><a href="#filtering-against-the-current-user">Filtering against the current user</a></li>
-<li><a href="#filtering-against-the-url">Filtering against the URL</a></li>
-<li><a href="#filtering-against-query-parameters">Filtering against query parameters</a></li>
-<li class="main"><a href="#generic-filtering">Generic Filtering</a></li>
-<li><a href="#setting-filter-backends">Setting filter backends</a></li>
-<li><a href="#filtering-and-object-lookups">Filtering and object lookups</a></li>
-<li><a href="#overriding-the-initial-queryset">Overriding the initial queryset</a></li>
-<li class="main"><a href="#api-guide">API Guide</a></li>
-<li><a href="#djangofilterbackend">DjangoFilterBackend</a></li>
-<li><a href="#searchfilter">SearchFilter</a></li>
-<li><a href="#orderingfilter">OrderingFilter</a></li>
-<li><a href="#djangoobjectpermissionsfilter">DjangoObjectPermissionsFilter</a></li>
-<li class="main"><a href="#custom-generic-filtering">Custom generic filtering</a></li>
-<li><a href="#example">Example</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#django-rest-framework-chain">Django REST framework chain</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#filtering">Filtering</a>
+ </li>
+
+
+ <li>
+ <a href="#filtering-against-the-current-user">Filtering against the current user</a>
+ </li>
+
+ <li>
+ <a href="#filtering-against-the-url">Filtering against the URL</a>
+ </li>
+
+ <li>
+ <a href="#filtering-against-query-parameters">Filtering against query parameters</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#generic-filtering">Generic Filtering</a>
+ </li>
+
+
+ <li>
+ <a href="#setting-filter-backends">Setting filter backends</a>
+ </li>
+
+ <li>
+ <a href="#filtering-and-object-lookups">Filtering and object lookups</a>
+ </li>
+
+ <li>
+ <a href="#overriding-the-initial-queryset">Overriding the initial queryset</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-guide">API Guide</a>
+ </li>
+
+
+ <li>
+ <a href="#djangofilterbackend">DjangoFilterBackend</a>
+ </li>
+
+ <li>
+ <a href="#searchfilter">SearchFilter</a>
+ </li>
+
+ <li>
+ <a href="#orderingfilter">OrderingFilter</a>
+ </li>
+
+ <li>
+ <a href="#djangoobjectpermissionsfilter">DjangoObjectPermissionsFilter</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-generic-filtering">Custom generic filtering</a>
+ </li>
+
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#django-rest-framework-chain">Django REST framework chain</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/filters.py"><span class="label label-info">filters.py</span></a></p>
-<h1 id="filtering">Filtering</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/filters.py">
+ <span class="label label-info">filters.py</span>
+ </a>
+
+
+
+ <h1 id="filtering">Filtering</h1>
<blockquote>
<p>The root QuerySet provided by the Manager describes all objects in the database table. Usually, though, you'll need to select only a subset of the complete set of objects.</p>
<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/topics/db/queries/#retrieving-specific-objects-with-filters">Django documentation</a></p>
@@ -226,7 +456,7 @@ a.fusion-poweredby {
<p>You might want to filter the queryset to ensure that only results relevant to the currently authenticated user making the request are returned.</p>
<p>You can do so by filtering based on the value of <code>request.user</code>.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>from myapp.models import Purchase
+<pre><code>from myapp.models import Purchase
from myapp.serializers import PurchaseSerializer
from rest_framework import generics
@@ -242,12 +472,12 @@ class PurchaseList(generics.ListAPIView):
return Purchase.objects.filter(purchaser=user)
</code></pre>
<h2 id="filtering-against-the-url">Filtering against the URL</h2>
-<p>Another style of filtering might involve restricting the queryset based on some part of the URL. </p>
+<p>Another style of filtering might involve restricting the queryset based on some part of the URL.</p>
<p>For example if your URL config contained an entry like this:</p>
-<pre class="prettyprint lang-py"><code>url('^purchases/(?P&lt;username&gt;.+)/$', PurchaseList.as_view()),
+<pre><code>url('^purchases/(?P&lt;username&gt;.+)/$', PurchaseList.as_view()),
</code></pre>
<p>You could then write a view that returned a purchase queryset filtered by the username portion of the URL:</p>
-<pre class="prettyprint lang-py"><code>class PurchaseList(generics.ListAPIView):
+<pre><code>class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
@@ -261,7 +491,7 @@ class PurchaseList(generics.ListAPIView):
<h2 id="filtering-against-query-parameters">Filtering against query parameters</h2>
<p>A final example of filtering the initial queryset would be to determine the initial queryset based on query parameters in the url.</p>
<p>We can override <code>.get_queryset()</code> to deal with URLs such as <code>http://example.com/api/purchases?username=denvercoder9</code>, and filter the queryset only if the <code>username</code> parameter is included in the URL:</p>
-<pre class="prettyprint lang-py"><code>class PurchaseList(generics.ListAPIView):
+<pre><code>class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
@@ -280,13 +510,13 @@ class PurchaseList(generics.ListAPIView):
<p>As well as being able to override the default queryset, REST framework also includes support for generic filtering backends that allow you to easily construct complex searches and filters.</p>
<h2 id="setting-filter-backends">Setting filter backends</h2>
<p>The default filter backends may be set globally, using the <code>DEFAULT_FILTER_BACKENDS</code> setting. For example.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
+<pre><code>REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)
}
</code></pre>
<p>You can also set the filter backends on a per-view, or per-viewset basis,
using the <code>GenericAPIView</code> class based views.</p>
-<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
+<pre><code>from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import filters
from rest_framework import generics
@@ -299,11 +529,11 @@ class UserListView(generics.ListAPIView):
<h2 id="filtering-and-object-lookups">Filtering and object lookups</h2>
<p>Note that if a filter backend is configured for a view, then as well as being used to filter list views, it will also be used to filter the querysets used for returning a single object.</p>
<p>For instance, given the previous example, and a product with an id of <code>4675</code>, the following URL would either return the corresponding object, or return a 404 response, depending on if the filtering conditions were met by the given product instance:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/products/4675/?category=clothing&amp;max_price=10.00
+<pre><code>http://example.com/api/products/4675/?category=clothing&amp;max_price=10.00
</code></pre>
<h2 id="overriding-the-initial-queryset">Overriding the initial queryset</h2>
<p>Note that you can use both an overridden <code>.get_queryset()</code> and generic filtering together, and everything will work as expected. For example, if <code>Product</code> had a many-to-many relationship with <code>User</code>, named <code>purchase</code>, you might want to write a view like this:</p>
-<pre class="prettyprint lang-py"><code>class PurchasedProductsList(generics.ListAPIView):
+<pre><code>class PurchasedProductsList(generics.ListAPIView):
"""
Return a list of all the products that the authenticated
user has ever purchased, with optional filtering.
@@ -319,23 +549,23 @@ class UserListView(generics.ListAPIView):
<hr />
<h1 id="api-guide">API Guide</h1>
<h2 id="djangofilterbackend">DjangoFilterBackend</h2>
-<p>The <code>DjangoFilterBackend</code> class supports highly customizable field filtering, using the <a href="https://github.com/alex/django-filter">django-filter package</a>. </p>
+<p>The <code>DjangoFilterBackend</code> class supports highly customizable field filtering, using the <a href="https://github.com/alex/django-filter">django-filter package</a>.</p>
<p>To use REST framework's <code>DjangoFilterBackend</code>, first install <code>django-filter</code>.</p>
-<pre class="prettyprint lang-py"><code>pip install django-filter
+<pre><code>pip install django-filter
</code></pre>
<h4 id="specifying-filter-fields">Specifying filter fields</h4>
<p>If all you need is simple equality-based filtering, you can set a <code>filter_fields</code> attribute on the view, or viewset, listing the set of fields you wish to filter against.</p>
-<pre class="prettyprint lang-py"><code>class ProductList(generics.ListAPIView):
+<pre><code>class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_fields = ('category', 'in_stock')
</code></pre>
<p>This will automatically create a <code>FilterSet</code> class for the given fields, and will allow you to make requests such as:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/products?category=clothing&amp;in_stock=True
+<pre><code>http://example.com/api/products?category=clothing&amp;in_stock=True
</code></pre>
<h4 id="specifying-a-filterset">Specifying a FilterSet</h4>
<p>For more advanced filtering requirements you can specify a <code>FilterSet</code> class that should be used by the view. For example:</p>
-<pre class="prettyprint lang-py"><code>import django_filters
+<pre><code>import django_filters
from myapp.models import Product
from myapp.serializers import ProductSerializer
from rest_framework import generics
@@ -353,12 +583,12 @@ class ProductList(generics.ListAPIView):
filter_class = ProductFilter
</code></pre>
<p>Which will allow you to make requests such as:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/products?category=clothing&amp;max_price=10.00
+<pre><code>http://example.com/api/products?category=clothing&amp;max_price=10.00
</code></pre>
<p>You can also span relationships using <code>django-filter</code>, let's assume that each
product has foreign key to <code>Manufacturer</code> model, so we create filter that
filters using <code>Manufacturer</code> name. For example:</p>
-<pre class="prettyprint lang-py"><code>import django_filters
+<pre><code>import django_filters
from myapp.models import Product
from myapp.serializers import ProductSerializer
from rest_framework import generics
@@ -369,10 +599,10 @@ class ProductFilter(django_filters.FilterSet):
fields = ['category', 'in_stock', 'manufacturer__name']
</code></pre>
<p>This enables us to make queries like:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/products?manufacturer__name=foo
+<pre><code>http://example.com/api/products?manufacturer__name=foo
</code></pre>
<p>This is nice, but it exposes the Django's double underscore convention as part of the API. If you instead want to explicitly name the filter argument you can instead explicitly include it on the <code>FilterSet</code> class:</p>
-<pre class="prettyprint lang-py"><code>import django_filters
+<pre><code>import django_filters
from myapp.models import Product
from myapp.serializers import ProductSerializer
from rest_framework import generics
@@ -385,14 +615,14 @@ class ProductFilter(django_filters.FilterSet):
fields = ['category', 'in_stock', 'manufacturer']
</code></pre>
<p>And now you can execute:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/products?manufacturer=foo
+<pre><code>http://example.com/api/products?manufacturer=foo
</code></pre>
<p>For more details on using filter sets see the <a href="https://django-filter.readthedocs.org/en/latest/index.html">django-filter documentation</a>.</p>
<hr />
<p><strong>Hints &amp; Tips</strong></p>
<ul>
<li>By default filtering is not enabled. If you want to use <code>DjangoFilterBackend</code> remember to make sure it is installed by using the <code>'DEFAULT_FILTER_BACKENDS'</code> setting.</li>
-<li>When using boolean fields, you should use the values <code>True</code> and <code>False</code> in the URL query parameters, rather than <code>0</code>, <code>1</code>, <code>true</code> or <code>false</code>. (The allowed boolean values are currently hardwired in Django's <a href="https://github.com/django/django/blob/master/django/forms/widgets.py">NullBooleanSelect implementation</a>.) </li>
+<li>When using boolean fields, you should use the values <code>True</code> and <code>False</code> in the URL query parameters, rather than <code>0</code>, <code>1</code>, <code>true</code> or <code>false</code>. (The allowed boolean values are currently hardwired in Django's <a href="https://github.com/django/django/blob/master/django/forms/widgets.py">NullBooleanSelect implementation</a>.)</li>
<li><code>django-filter</code> supports filtering across relationships, using Django's double-underscore syntax.</li>
<li>For Django 1.3 support, make sure to install <code>django-filter</code> version 0.5.4, as later versions drop support for 1.3.</li>
</ul>
@@ -400,17 +630,17 @@ class ProductFilter(django_filters.FilterSet):
<h2 id="searchfilter">SearchFilter</h2>
<p>The <code>SearchFilter</code> class supports simple single query parameter based searching, and is based on the <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields">Django admin's search functionality</a>.</p>
<p>The <code>SearchFilter</code> class will only be applied if the view has a <code>search_fields</code> attribute set. The <code>search_fields</code> attribute should be a list of names of text type fields on the model, such as <code>CharField</code> or <code>TextField</code>.</p>
-<pre class="prettyprint lang-py"><code>class UserListView(generics.ListAPIView):
+<pre><code>class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer = UserSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('username', 'email')
</code></pre>
<p>This will allow the client to filter the items in the list by making queries such as:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/users?search=russell
+<pre><code>http://example.com/api/users?search=russell
</code></pre>
<p>You can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation:</p>
-<pre class="prettyprint lang-py"><code>search_fields = ('username', 'email', 'profile__profession')
+<pre><code>search_fields = ('username', 'email', 'profile__profession')
</code></pre>
<p>By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched.</p>
<p>The search behavior may be restricted by prepending various characters to the <code>search_fields</code>.</p>
@@ -420,7 +650,7 @@ class ProductFilter(django_filters.FilterSet):
<li>'@' Full-text search. (Currently only supported Django's MySQL backend.)</li>
</ul>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>search_fields = ('=username', '=email')
+<pre><code>search_fields = ('=username', '=email')
</code></pre>
<p>By default, the search parameter is named <code>'search</code>', but this may be overridden with the <code>SEARCH_PARAM</code> setting.</p>
<p>For more details, see the <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields">Django documentation</a>.</p>
@@ -428,17 +658,17 @@ class ProductFilter(django_filters.FilterSet):
<h2 id="orderingfilter">OrderingFilter</h2>
<p>The <code>OrderingFilter</code> class supports simple query parameter controlled ordering of results. By default, the query parameter is named <code>'ordering'</code>, but this may by overridden with the <code>ORDERING_PARAM</code> setting.</p>
<p>For example, to order users by username:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/users?ordering=username
+<pre><code>http://example.com/api/users?ordering=username
</code></pre>
<p>The client may also specify reverse orderings by prefixing the field name with '-', like so:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/users?ordering=-username
+<pre><code>http://example.com/api/users?ordering=-username
</code></pre>
<p>Multiple orderings may also be specified:</p>
-<pre class="prettyprint lang-py"><code>http://example.com/api/users?ordering=account,username
+<pre><code>http://example.com/api/users?ordering=account,username
</code></pre>
<h3 id="specifying-which-fields-may-be-ordered-against">Specifying which fields may be ordered against</h3>
<p>It's recommended that you explicitly specify which fields the API should allowing in the ordering filter. You can do this by setting an <code>ordering_fields</code> attribute on the view, like so:</p>
-<pre class="prettyprint lang-py"><code>class UserListView(generics.ListAPIView):
+<pre><code>class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
@@ -447,7 +677,7 @@ class ProductFilter(django_filters.FilterSet):
<p>This helps prevent unexpected data leakage, such as allowing users to order against a password hash field or other sensitive data.</p>
<p>If you <em>don't</em> specify an <code>ordering_fields</code> attribute on the view, the filter class will default to allowing the user to filter on any readable fields on the serializer specified by the <code>serializer_class</code> attribute.</p>
<p>If you are confident that the queryset being used by the view doesn't contain any sensitive data, you can also explicitly specify that a view should allow ordering on <em>any</em> model field or queryset aggregate, by using the special value <code>'__all__'</code>.</p>
-<pre class="prettyprint lang-py"><code>class BookingsListView(generics.ListAPIView):
+<pre><code>class BookingsListView(generics.ListAPIView):
queryset = Booking.objects.all()
serializer_class = BookingSerializer
filter_backends = (filters.OrderingFilter,)
@@ -456,7 +686,7 @@ class ProductFilter(django_filters.FilterSet):
<h3 id="specifying-a-default-ordering">Specifying a default ordering</h3>
<p>If an <code>ordering</code> attribute is set on the view, this will be used as the default ordering.</p>
<p>Typically you'd instead control this by setting <code>order_by</code> on the initial queryset, but using the <code>ordering</code> parameter on the view allows you to specify the ordering in a way that it can then be passed automatically as context to a rendered template. This makes it possible to automatically render column headers differently if they are being used to order the results.</p>
-<pre class="prettyprint lang-py"><code>class UserListView(generics.ListAPIView):
+<pre><code>class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
@@ -470,7 +700,7 @@ class ProductFilter(django_filters.FilterSet):
<p>If you're using <code>DjangoObjectPermissionsFilter</code>, you'll probably also want to add an appropriate object permissions class, to ensure that users can only operate on instances if they have the appropriate object permissions. The easiest way to do this is to subclass <code>DjangoObjectPermissions</code> and add <code>'view'</code> permissions to the <code>perms_map</code> attribute.</p>
<p>A complete example using both <code>DjangoObjectPermissionsFilter</code> and <code>DjangoObjectPermissions</code> might look something like this.</p>
<p><strong>permissions.py</strong>:</p>
-<pre class="prettyprint lang-py"><code>class CustomObjectPermissions(permissions.DjangoObjectPermissions):
+<pre><code>class CustomObjectPermissions(permissions.DjangoObjectPermissions):
"""
Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
"""
@@ -485,7 +715,7 @@ class ProductFilter(django_filters.FilterSet):
}
</code></pre>
<p><strong>views.py</strong>:</p>
-<pre class="prettyprint lang-py"><code>class EventViewSet(viewsets.ModelViewSet):
+<pre><code>class EventViewSet(viewsets.ModelViewSet):
"""
Viewset that only lists events if user has 'view' permissions, and only
allows operations on individual events if user has appropriate 'view', 'add',
@@ -504,7 +734,7 @@ class ProductFilter(django_filters.FilterSet):
<p>As well as allowing clients to perform searches and filtering, generic filter backends can be useful for restricting which objects should be visible to any given request or user.</p>
<h2 id="example">Example</h2>
<p>For example, you might need to restrict users to only being able to see objects they created.</p>
-<pre class="prettyprint lang-py"><code>class IsOwnerFilterBackend(filters.BaseFilterBackend):
+<pre><code>class IsOwnerFilterBackend(filters.BaseFilterBackend):
"""
Filter that only allows users to see their own objects.
"""
@@ -516,42 +746,52 @@ class ProductFilter(django_filters.FilterSet):
<p>The following third party packages provide additional filter implementations.</p>
<h2 id="django-rest-framework-chain">Django REST framework chain</h2>
<p>The <a href="https://github.com/philipn/django-rest-framework-chain">django-rest-framework-chain package</a> works together with the <code>DjangoFilterBackend</code> class, and allows you to easily create filters across relationships, or create multiple filter lookup types for a given field.</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/api-guide/format-suffixes.html b/api-guide/format-suffixes.html
deleted file mode 100644
index 0531f75c..00000000
--- a/api-guide/format-suffixes.html
+++ /dev/null
@@ -1,291 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Format suffixes - 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/api-guide/format-suffixes"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Format suffixes">
- <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="format-suffixes-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="../api-guide/reverse">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/content-negotiation"><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="#format-suffixes">Format suffixes</a></li>
-<li><a href="#format_suffix_patterns">format_suffix_patterns</a></li>
-<li><a href="#accept-headers-vs-format-suffixes">Accept headers vs. format suffixes</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/urlpatterns.py"><span class="label label-info">urlpatterns.py</span></a></p>
-<h1 id="format-suffixes">Format suffixes</h1>
-<blockquote>
-<p>Section 6.2.1 does not say that content negotiation should be
-used all the time.</p>
-<p>&mdash; Roy Fielding, <a href="http://tech.groups.yahoo.com/group/rest-discuss/message/5857">REST discuss mailing list</a></p>
-</blockquote>
-<p>A common pattern for Web APIs is to use filename extensions on URLs to provide an endpoint for a given media type. For example, 'http://example.com/api/users.json' to serve a JSON representation. </p>
-<p>Adding format-suffix patterns to each individual entry in the URLconf for your API is error-prone and non-DRY, so REST framework provides a shortcut to adding these patterns to your URLConf.</p>
-<h2 id="format_suffix_patterns">format_suffix_patterns</h2>
-<p><strong>Signature</strong>: format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None)</p>
-<p>Returns a URL pattern list which includes format suffix patterns appended to each of the URL patterns provided.</p>
-<p>Arguments:</p>
-<ul>
-<li><strong>urlpatterns</strong>: Required. A URL pattern list.</li>
-<li><strong>suffix_required</strong>: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to <code>False</code>, meaning that suffixes are optional by default.</li>
-<li><strong>allowed</strong>: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used. </li>
-</ul>
-<p>Example:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.urlpatterns import format_suffix_patterns
-from blog import views
-
-urlpatterns = [
- url(r'^/$', views.apt_root),
- url(r'^comments/$', views.comment_list),
- url(r'^comments/(?P&lt;pk&gt;[0-9]+)/$', views.comment_detail)
-]
-
-urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
-</code></pre>
-<p>When using <code>format_suffix_patterns</code>, you must make sure to add the <code>'format'</code> keyword argument to the corresponding views. For example:</p>
-<pre class="prettyprint lang-py"><code>@api_view(('GET', 'POST'))
-def comment_list(request, format=None):
- # do stuff...
-</code></pre>
-<p>Or with class based views:</p>
-<pre class="prettyprint lang-py"><code>class CommentList(APIView):
- def get(self, request, format=None):
- # do stuff...
-
- def post(self, request, format=None):
- # do stuff...
-</code></pre>
-<p>The name of the kwarg used may be modified by using the <code>FORMAT_SUFFIX_KWARG</code> setting.</p>
-<p>Also note that <code>format_suffix_patterns</code> does not support descending into <code>include</code> URL patterns.</p>
-<hr />
-<h2 id="accept-headers-vs-format-suffixes">Accept headers vs. format suffixes</h2>
-<p>There seems to be a view among some of the Web community that filename extensions are not a RESTful pattern, and that <code>HTTP Accept</code> headers should always be used instead.</p>
-<p>It is actually a misconception. For example, take the following quote from Roy Fielding discussing the relative merits of query parameter media-type indicators vs. file extension media-type indicators: </p>
-<p>&ldquo;That's why I always prefer extensions. Neither choice has anything to do with REST.&rdquo; &mdash; Roy Fielding, <a href="http://tech.groups.yahoo.com/group/rest-discuss/message/14844">REST discuss mailing list</a></p>
-<p>The quote does not mention Accept headers, but it does make it clear that format suffixes should be considered an acceptable pattern.</p>
- </div><!--/span-->
- </div><!--/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/api-guide/format-suffixes/index.html b/api-guide/format-suffixes/index.html
new file mode 100644
index 00000000..7e73503f
--- /dev/null
+++ b/api-guide/format-suffixes/index.html
@@ -0,0 +1,473 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Format suffixes - 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/api-guide/format-suffixes/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Format suffixes">
+ <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="../reverse">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../content-negotiation">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#format-suffixes">Format suffixes</a>
+ </li>
+
+
+ <li>
+ <a href="#format_suffix_patterns">format_suffix_patterns</a>
+ </li>
+
+ <li>
+ <a href="#accept-headers-vs-format-suffixes">Accept headers vs. format suffixes</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/urlpatterns.py">
+ <span class="label label-info">urlpatterns.py</span>
+ </a>
+
+
+
+ <h1 id="format-suffixes">Format suffixes</h1>
+<blockquote>
+<p>Section 6.2.1 does not say that content negotiation should be
+used all the time.</p>
+<p>&mdash; Roy Fielding, <a href="http://tech.groups.yahoo.com/group/rest-discuss/message/5857">REST discuss mailing list</a></p>
+</blockquote>
+<p>A common pattern for Web APIs is to use filename extensions on URLs to provide an endpoint for a given media type. For example, 'http://example.com/api/users.json' to serve a JSON representation.</p>
+<p>Adding format-suffix patterns to each individual entry in the URLconf for your API is error-prone and non-DRY, so REST framework provides a shortcut to adding these patterns to your URLConf.</p>
+<h2 id="format_suffix_patterns">format_suffix_patterns</h2>
+<p><strong>Signature</strong>: format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None)</p>
+<p>Returns a URL pattern list which includes format suffix patterns appended to each of the URL patterns provided.</p>
+<p>Arguments:</p>
+<ul>
+<li><strong>urlpatterns</strong>: Required. A URL pattern list.</li>
+<li><strong>suffix_required</strong>: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to <code>False</code>, meaning that suffixes are optional by default.</li>
+<li><strong>allowed</strong>: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used.</li>
+</ul>
+<p>Example:</p>
+<pre><code>from rest_framework.urlpatterns import format_suffix_patterns
+from blog import views
+
+urlpatterns = [
+ url(r'^/$', views.apt_root),
+ url(r'^comments/$', views.comment_list),
+ url(r'^comments/(?P&lt;pk&gt;[0-9]+)/$', views.comment_detail)
+]
+
+urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
+</code></pre>
+<p>When using <code>format_suffix_patterns</code>, you must make sure to add the <code>'format'</code> keyword argument to the corresponding views. For example:</p>
+<pre><code>@api_view(('GET', 'POST'))
+def comment_list(request, format=None):
+ # do stuff...
+</code></pre>
+<p>Or with class based views:</p>
+<pre><code>class CommentList(APIView):
+ def get(self, request, format=None):
+ # do stuff...
+
+ def post(self, request, format=None):
+ # do stuff...
+</code></pre>
+<p>The name of the kwarg used may be modified by using the <code>FORMAT_SUFFIX_KWARG</code> setting.</p>
+<p>Also note that <code>format_suffix_patterns</code> does not support descending into <code>include</code> URL patterns.</p>
+<hr />
+<h2 id="accept-headers-vs-format-suffixes">Accept headers vs. format suffixes</h2>
+<p>There seems to be a view among some of the Web community that filename extensions are not a RESTful pattern, and that <code>HTTP Accept</code> headers should always be used instead.</p>
+<p>It is actually a misconception. For example, take the following quote from Roy Fielding discussing the relative merits of query parameter media-type indicators vs. file extension media-type indicators:</p>
+<p>&ldquo;That's why I always prefer extensions. Neither choice has anything to do with REST.&rdquo; &mdash; Roy Fielding, <a href="http://tech.groups.yahoo.com/group/rest-discuss/message/14844">REST discuss mailing list</a></p>
+<p>The quote does not mention Accept headers, but it does make it clear that format suffixes should be considered an acceptable pattern.</p>
+
+ </div>
+ <!--/span-->
+ </div>
+ <!--/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/api-guide/generic-views.html b/api-guide/generic-views/index.html
index af3f445c..57c1649a 100644
--- a/api-guide/generic-views.html
+++ b/api-guide/generic-views/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>Generic views - 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/api-guide/generic-views"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Generic views, API Reference, Mixins, Concrete View Classes, Customizing the generic views, 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="generic-views-page">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Generic views - 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/api-guide/generic-views/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Generic views">
+ <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="../api-guide/viewsets">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/views"><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="../viewsets">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../views">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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>
+ <!--/.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,44 +335,164 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#generic-views">Generic views</a></li>
-<li><a href="#examples">Examples</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#genericapiview">GenericAPIView</a></li>
-<li class="main"><a href="#mixins">Mixins</a></li>
-<li><a href="#listmodelmixin">ListModelMixin</a></li>
-<li><a href="#createmodelmixin">CreateModelMixin</a></li>
-<li><a href="#retrievemodelmixin">RetrieveModelMixin</a></li>
-<li><a href="#updatemodelmixin">UpdateModelMixin</a></li>
-<li><a href="#destroymodelmixin">DestroyModelMixin</a></li>
-<li class="main"><a href="#concrete-view-classes">Concrete View Classes</a></li>
-<li><a href="#createapiview">CreateAPIView</a></li>
-<li><a href="#listapiview">ListAPIView</a></li>
-<li><a href="#retrieveapiview">RetrieveAPIView</a></li>
-<li><a href="#destroyapiview">DestroyAPIView</a></li>
-<li><a href="#updateapiview">UpdateAPIView</a></li>
-<li><a href="#listcreateapiview">ListCreateAPIView</a></li>
-<li><a href="#retrieveupdateapiview">RetrieveUpdateAPIView</a></li>
-<li><a href="#retrievedestroyapiview">RetrieveDestroyAPIView</a></li>
-<li><a href="#retrieveupdatedestroyapiview">RetrieveUpdateDestroyAPIView</a></li>
-<li class="main"><a href="#customizing-the-generic-views">Customizing the generic views</a></li>
-<li><a href="#creating-custom-mixins">Creating custom mixins</a></li>
-<li><a href="#creating-custom-base-classes">Creating custom base classes</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#django-rest-framework-bulk">Django REST Framework bulk</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#generic-views">Generic views</a>
+ </li>
+
+
+ <li>
+ <a href="#examples">Examples</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#genericapiview">GenericAPIView</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#mixins">Mixins</a>
+ </li>
+
+
+ <li>
+ <a href="#listmodelmixin">ListModelMixin</a>
+ </li>
+
+ <li>
+ <a href="#createmodelmixin">CreateModelMixin</a>
+ </li>
+
+ <li>
+ <a href="#retrievemodelmixin">RetrieveModelMixin</a>
+ </li>
+
+ <li>
+ <a href="#updatemodelmixin">UpdateModelMixin</a>
+ </li>
+
+ <li>
+ <a href="#destroymodelmixin">DestroyModelMixin</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#concrete-view-classes">Concrete View Classes</a>
+ </li>
+
+
+ <li>
+ <a href="#createapiview">CreateAPIView</a>
+ </li>
+
+ <li>
+ <a href="#listapiview">ListAPIView</a>
+ </li>
+
+ <li>
+ <a href="#retrieveapiview">RetrieveAPIView</a>
+ </li>
+
+ <li>
+ <a href="#destroyapiview">DestroyAPIView</a>
+ </li>
+
+ <li>
+ <a href="#updateapiview">UpdateAPIView</a>
+ </li>
+
+ <li>
+ <a href="#listcreateapiview">ListCreateAPIView</a>
+ </li>
+
+ <li>
+ <a href="#retrieveupdateapiview">RetrieveUpdateAPIView</a>
+ </li>
+
+ <li>
+ <a href="#retrievedestroyapiview">RetrieveDestroyAPIView</a>
+ </li>
+
+ <li>
+ <a href="#retrieveupdatedestroyapiview">RetrieveUpdateDestroyAPIView</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#customizing-the-generic-views">Customizing the generic views</a>
+ </li>
+
+
+ <li>
+ <a href="#creating-custom-mixins">Creating custom mixins</a>
+ </li>
+
+ <li>
+ <a href="#creating-custom-base-classes">Creating custom base classes</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#put-as-create">PUT as create</a>
+ </li>
+
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#django-rest-framework-bulk">Django REST Framework bulk</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/mixins.py"><span class="label label-info">mixins.py</span></a>
-<a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/generics.py"><span class="label label-info">generics.py</span></a></p>
-<h1 id="generic-views">Generic views</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/mixins.py">
+ <span class="label label-info">mixins.py</span>
+ </a>
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/generics.py">
+ <span class="label label-info">generics.py</span>
+ </a>
+
+
+
+ <h1 id="generic-views">Generic views</h1>
<blockquote>
<p>Django’s generic views... were developed as a shortcut for common usage patterns... They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to repeat yourself.</p>
<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/class-based-views/#base-vs-generic-views">Django Documentation</a></p>
@@ -233,7 +502,7 @@ a.fusion-poweredby {
<p>If the generic views don't suit the needs of your API, you can drop down to using the regular <code>APIView</code> class, or reuse the mixins and base classes used by the generic views to compose your own set of reusable generic views.</p>
<h2 id="examples">Examples</h2>
<p>Typically when using the generic views, you'll override the view, and set several class attributes.</p>
-<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
+<pre><code>from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from rest_framework.permissions import IsAdminUser
@@ -245,7 +514,7 @@ class UserList(generics.ListCreateAPIView):
paginate_by = 100
</code></pre>
<p>For more complex cases you might also want to override various methods on the view class. For example.</p>
-<pre class="prettyprint lang-py"><code>class UserList(generics.ListCreateAPIView):
+<pre><code>class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
@@ -265,7 +534,7 @@ class UserList(generics.ListCreateAPIView):
return Response(serializer.data)
</code></pre>
<p>For very simple cases you might want to pass through any class attributes using the <code>.as_view()</code> method. For example, your URLconf might include something like the following entry:</p>
-<pre class="prettyprint lang-py"><code>url(r'^/users/', ListCreateAPIView.as_view(model=User), name='user-list')
+<pre><code>url(r'^/users/', ListCreateAPIView.as_view(model=User), name='user-list')
</code></pre>
<hr />
<h1 id="api-reference">API Reference</h1>
@@ -304,7 +573,7 @@ class UserList(generics.ListCreateAPIView):
<p>This method should always be used rather than accessing <code>self.queryset</code> directly, as <code>self.queryset</code> gets evaluated only once, and those results are cached for all subsequent requests.</p>
<p>May be overridden to provide dynamic behavior, such as returning a queryset, that is specific to the user making the request.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>def get_queryset(self):
+<pre><code>def get_queryset(self):
user = self.request.user
return user.accounts.all()
</code></pre>
@@ -312,7 +581,7 @@ class UserList(generics.ListCreateAPIView):
<p>Returns an object instance that should be used for detail views. Defaults to using the <code>lookup_field</code> parameter to filter the base queryset.</p>
<p>May be overridden to provide more complex behavior, such as object lookups based on more than one URL kwarg.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>def get_object(self):
+<pre><code>def get_object(self):
queryset = self.get_queryset()
filter = {}
for field in self.multiple_lookup_fields:
@@ -327,7 +596,7 @@ class UserList(generics.ListCreateAPIView):
<p>Returns the classes that should be used to filter the queryset. Defaults to returning the <code>filter_backends</code> attribute.</p>
<p>May be overridden to provide more complex behavior with filters, such as using different (or even exlusive) lists of filter_backends depending on different criteria.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>def get_filter_backends(self):
+<pre><code>def get_filter_backends(self):
if "geo_route" in self.request.QUERY_PARAMS:
return (GeoRouteFilter, CategoryFilter)
elif "geo_point" in self.request.QUERY_PARAMS:
@@ -339,7 +608,7 @@ class UserList(generics.ListCreateAPIView):
<p>Returns the class that should be used for the serializer. Defaults to returning the <code>serializer_class</code> attribute, or dynamically generating a serializer class if the <code>model</code> shortcut is being used.</p>
<p>May be overridden to provide dynamic behavior, such as using different serializers for read and write operations, or providing different serializers to different types of users.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>def get_serializer_class(self):
+<pre><code>def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
@@ -348,7 +617,7 @@ class UserList(generics.ListCreateAPIView):
<p>Returns the page size to use with pagination. By default this uses the <code>paginate_by</code> attribute, and may be overridden by the client if the <code>paginate_by_param</code> attribute is set.</p>
<p>You may want to override this method to provide more complex behavior, such as modifying page sizes based on the media type of the response.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>def get_paginate_by(self):
+<pre><code>def get_paginate_by(self):
if self.request.accepted_renderer.format == 'html':
return 20
return 100
@@ -362,7 +631,7 @@ class UserList(generics.ListCreateAPIView):
<li><code>post_delete(self, obj)</code> - A hook that is called after deleting an object.</li>
</ul>
<p>The <code>pre_save</code> method in particular is a useful hook for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument.</p>
-<pre class="prettyprint lang-py"><code>def pre_save(self, obj):
+<pre><code>def pre_save(self, obj):
"""
Set the object's owner, based on the incoming request.
"""
@@ -384,7 +653,6 @@ class UserList(generics.ListCreateAPIView):
<h2 id="listmodelmixin">ListModelMixin</h2>
<p>Provides a <code>.list(request, *args, **kwargs)</code> method, that implements listing a queryset.</p>
<p>If the queryset is populated, this returns a <code>200 OK</code> response, with a serialized representation of the queryset as the body of the response. The response data may optionally be paginated.</p>
-<p>If the queryset is empty this returns a <code>200 OK</code> response, unless the <code>.allow_empty</code> attribute on the view is set to <code>False</code>, in which case it will return a <code>404 Not Found</code>.</p>
<h2 id="createmodelmixin">CreateModelMixin</h2>
<p>Provides a <code>.create(request, *args, **kwargs)</code> method, that implements creating and saving a new model instance.</p>
<p>If an object is created this returns a <code>201 Created</code> response, with a serialized representation of the object as the body of the response. If the representation contains a key named <code>url</code>, then the <code>Location</code> header of the response will be populated with that value.</p>
@@ -445,7 +713,7 @@ class UserList(generics.ListCreateAPIView):
<p>Often you'll want to use the existing generic views, but use some slightly customized behavior. If you find yourself reusing some bit of customized behavior in multiple places, you might want to refactor the behavior into a common class that you can then just apply to any view or viewset as needed.</p>
<h2 id="creating-custom-mixins">Creating custom mixins</h2>
<p>For example, if you need to lookup objects based on multiple fields in the URL conf, you could create a mixin class like the following:</p>
-<pre class="prettyprint lang-py"><code>class MultipleFieldLookupMixin(object):
+<pre><code>class MultipleFieldLookupMixin(object):
"""
Apply this mixin to any view or viewset to get multiple field filtering
based on a `lookup_fields` attribute, instead of the default single field filtering.
@@ -459,7 +727,7 @@ class UserList(generics.ListCreateAPIView):
return get_object_or_404(queryset, **filter) # Lookup the object
</code></pre>
<p>You can then simply apply this mixin to a view or viewset anytime you need to apply the custom behavior.</p>
-<pre class="prettyprint lang-py"><code>class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
+<pre><code>class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_fields = ('account', 'username')
@@ -467,7 +735,7 @@ class UserList(generics.ListCreateAPIView):
<p>Using custom mixins is a good option if you have custom behavior that needs to be used</p>
<h2 id="creating-custom-base-classes">Creating custom base classes</h2>
<p>If you are using a mixin across multiple views, you can take this a step further and create your own set of base views that can then be used throughout your project. For example:</p>
-<pre class="prettyprint lang-py"><code>class BaseRetrieveView(MultipleFieldLookupMixin,
+<pre><code>class BaseRetrieveView(MultipleFieldLookupMixin,
generics.RetrieveAPIView):
pass
@@ -476,46 +744,63 @@ class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
pass
</code></pre>
<p>Using custom base classes is a good option if you have custom behavior that consistently needs to be repeated across a large number of views throughout your project.</p>
+<hr />
+<h1 id="put-as-create">PUT as create</h1>
+<p>Prior to version 3.0 the REST framework mixins treated <code>PUT</code> as either an update or a create operation, depending on if the object already existed or not.</p>
+<p>Allowing <code>PUT</code> as create operations is problematic, as it necessarily exposes information about the existence or non-existence 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 from version 3.0 onwards we now use 404 behavior as the default, due to it being simpler and more obvious.</p>
+<p>If you need to generic PUT-as-create behavior you may want to include something like <a href="https://gist.github.com/tomchristie/a2ace4577eff2c603b1b">this <code>AllowPUTAsCreateMixin</code> class</a> as a mixin to your views.</p>
+<hr />
<h1 id="third-party-packages">Third party packages</h1>
<p>The following third party packages provide additional generic view implementations.</p>
<h2 id="django-rest-framework-bulk">Django REST Framework bulk</h2>
<p>The <a href="https://github.com/miki725/django-rest-framework-bulk">django-rest-framework-bulk package</a> implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.</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/api-guide/metadata.html b/api-guide/metadata.html
deleted file mode 100644
index 1ca656b7..00000000
--- a/api-guide/metadata.html
+++ /dev/null
@@ -1,324 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Metadata - 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//api-guide/metadata.html"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Metadata, Custom metadata classes">
- <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="metadata-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 class="main"><a href="#metadata">Metadata</a></li>
-<li><a href="#setting-the-metadata-scheme">Setting the metadata scheme</a></li>
-<li><a href="#creating-schema-endpoints">Creating schema endpoints</a></li>
-<li class="main"><a href="#custom-metadata-classes">Custom metadata classes</a></li>
-<li><a href="#example">Example</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/metadata.py"><span class="label label-info">metadata.py</span></a></p>
-<h1 id="metadata">Metadata</h1>
-<blockquote>
-<p>[The <code>OPTIONS</code>] method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.</p>
-<p>&mdash; <a href="http://tools.ietf.org/html/rfc7231#section-4.3.7">RFC7231, Section 4.3.7.</a></p>
-</blockquote>
-<p>REST framework includes a configurable mechanism for determining how your API should respond to <code>OPTIONS</code> requests. This allows you to return API schema or other resource information.</p>
-<p>There are not currently any widely adopted conventions for exactly what style of response should be returned for HTTP <code>OPTIONS</code> requests, so we provide an ad-hoc style that returns some useful information.</p>
-<p>Here's an example response that demonstrates the information that is returned by default.</p>
-<pre class="prettyprint lang-py"><code>HTTP 200 OK
-Allow: GET, POST, HEAD, OPTIONS
-Content-Type: application/json
-
-{
- "name": "To Do List",
- "description": "List existing 'To Do' items, or create a new item.",
- "renders": [
- "application/json",
- "text/html"
- ],
- "parses": [
- "application/json",
- "application/x-www-form-urlencoded",
- "multipart/form-data"
- ],
- "actions": {
- "POST": {
- "note": {
- "type": "string",
- "required": false,
- "read_only": false,
- "label": "title",
- "max_length": 100
- }
- }
- }
-}
-</code></pre>
-<h2 id="setting-the-metadata-scheme">Setting the metadata scheme</h2>
-<p>You can set the metadata class globally using the <code>'DEFAULT_METADATA_CLASS'</code> settings key:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata'
-}
-</code></pre>
-<p>Or you can set the metadata class individually for a view:</p>
-<pre class="prettyprint lang-py"><code>class APIRoot(APIView):
- metadata_class = APIRootMetadata
-
- def get(self, request, format=None):
- return Response({
- ...
- })
-</code></pre>
-<p>The REST framework package only includes a single metadata class implementation, named <code>SimpleMetadata</code>. If you want to use an alternative style you'll need to implement a custom metadata class.</p>
-<h2 id="creating-schema-endpoints">Creating schema endpoints</h2>
-<p>If you have specific requirements for creating schema endpoints that are accessed with regular <code>GET</code> requests, you might consider re-using the metadata API for doing so.</p>
-<p>For example, the following additional route could be used on a viewset to provide a linkable schema endpoint.</p>
-<pre class="prettyprint lang-py"><code>@list_route(methods=['GET'])
-def schema(self, request):
- meta = self.metadata_class()
- data = meta.determine_metadata(request, self)
- return Response(data)
-</code></pre>
-<p>There are a couple of reasons that you might choose to take this approach, including that <code>OPTIONS</code> responses <a href="https://www.mnot.net/blog/2012/10/29/NO_OPTIONS">are not cacheable</a>.</p>
-<hr />
-<h1 id="custom-metadata-classes">Custom metadata classes</h1>
-<p>If you want to provide a custom metadata class you should override <code>BaseMetadata</code> and implement the <code>determine_metadata(self, request, view)</code> method.</p>
-<p>Useful things that you might want to do could include returning schema information, using a format such as <a href="http://json-schema.org/">JSON schema</a>, or returning debug information to admin users.</p>
-<h2 id="example">Example</h2>
-<p>The following class could be used to limit the information that is returned to <code>OPTIONS</code> requests.</p>
-<pre class="prettyprint lang-py"><code>class MinimalMetadata(BaseMetadata):
- """
- Don't include field and other information for `OPTIONS` requests.
- Just return the name and description.
- """
- def determine_metadata(self, request, view):
- return {
- 'name': view.get_view_name(),
- 'description': view.get_view_description()
- }
-</code></pre>
- </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/api-guide/pagination.html b/api-guide/pagination.html
deleted file mode 100644
index 0f236582..00000000
--- a/api-guide/pagination.html
+++ /dev/null
@@ -1,373 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Pagination - 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/api-guide/pagination"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Pagination, Custom pagination serializers, 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="pagination-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="../api-guide/content-negotiation">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/filtering"><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="#pagination">Pagination</a></li>
-<li><a href="#paginating-basic-data">Paginating basic data</a></li>
-<li><a href="#paginating-querysets">Paginating QuerySets</a></li>
-<li><a href="#pagination-in-the-generic-views">Pagination in the generic views</a></li>
-<li class="main"><a href="#custom-pagination-serializers">Custom pagination serializers</a></li>
-<li><a href="#example">Example</a></li>
-<li><a href="#using-your-custom-pagination-serializer">Using your custom pagination serializer</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#drf-extensions">DRF-extensions</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/pagination.py"><span class="label label-info">pagination.py</span></a></p>
-<h1 id="pagination">Pagination</h1>
-<blockquote>
-<p>Django provides a few classes that help you manage paginated data – that is, data that’s split across several pages, with “Previous/Next” links.</p>
-<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/topics/pagination/">Django documentation</a></p>
-</blockquote>
-<p>REST framework includes a <code>PaginationSerializer</code> class that makes it easy to return paginated data in a way that can then be rendered to arbitrary media types. </p>
-<h2 id="paginating-basic-data">Paginating basic data</h2>
-<p>Let's start by taking a look at an example from the Django documentation.</p>
-<pre class="prettyprint lang-py"><code>from django.core.paginator import Paginator
-
-objects = ['john', 'paul', 'george', 'ringo']
-paginator = Paginator(objects, 2)
-page = paginator.page(1)
-page.object_list
-# ['john', 'paul']
-</code></pre>
-<p>At this point we've got a page object. If we wanted to return this page object as a JSON response, we'd need to provide the client with context such as next and previous links, so that it would be able to page through the remaining results.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.pagination import PaginationSerializer
-
-serializer = PaginationSerializer(instance=page)
-serializer.data
-# {'count': 4, 'next': '?page=2', 'previous': None, 'results': [u'john', u'paul']}
-</code></pre>
-<p>The <code>context</code> argument of the <code>PaginationSerializer</code> class may optionally include the request. If the request is included in the context then the next and previous links returned by the serializer will use absolute URLs instead of relative URLs.</p>
-<pre class="prettyprint lang-py"><code>request = RequestFactory().get('/foobar')
-serializer = PaginationSerializer(instance=page, context={'request': request})
-serializer.data
-# {'count': 4, 'next': 'http://testserver/foobar?page=2', 'previous': None, 'results': [u'john', u'paul']}
-</code></pre>
-<p>We could now return that data in a <code>Response</code> object, and it would be rendered into the correct media type.</p>
-<h2 id="paginating-querysets">Paginating QuerySets</h2>
-<p>Our first example worked because we were using primitive objects. If we wanted to paginate a queryset or other complex data, we'd need to specify a serializer to use to serialize the result set itself.</p>
-<p>We can do this using the <code>object_serializer_class</code> attribute on the inner <code>Meta</code> class of the pagination serializer. For example.</p>
-<pre class="prettyprint lang-py"><code>class UserSerializer(serializers.ModelSerializer):
- """
- Serializes user querysets.
- """
- class Meta:
- model = User
- fields = ('username', 'email')
-
-class PaginatedUserSerializer(pagination.PaginationSerializer):
- """
- Serializes page objects of user querysets.
- """
- class Meta:
- object_serializer_class = UserSerializer
-</code></pre>
-<p>We could now use our pagination serializer in a view like this.</p>
-<pre class="prettyprint lang-py"><code>@api_view('GET')
-def user_list(request):
- queryset = User.objects.all()
- paginator = Paginator(queryset, 20)
-
- page = request.QUERY_PARAMS.get('page')
- try:
- users = paginator.page(page)
- except PageNotAnInteger:
- # If page is not an integer, deliver first page.
- users = paginator.page(1)
- except EmptyPage:
- # If page is out of range (e.g. 9999),
- # deliver last page of results.
- users = paginator.page(paginator.num_pages)
-
- serializer_context = {'request': request}
- serializer = PaginatedUserSerializer(users,
- context=serializer_context)
- return Response(serializer.data)
-</code></pre>
-<h2 id="pagination-in-the-generic-views">Pagination in the generic views</h2>
-<p>The generic class based views <code>ListAPIView</code> and <code>ListCreateAPIView</code> provide pagination of the returned querysets by default. You can customise this behaviour by altering the pagination style, by modifying the default number of results, by allowing clients to override the page size using a query parameter, or by turning pagination off completely.</p>
-<p>The default pagination style may be set globally, using the <code>DEFAULT_PAGINATION_SERIALIZER_CLASS</code>, <code>PAGINATE_BY</code>, <code>PAGINATE_BY_PARAM</code>, and <code>MAX_PAGINATE_BY</code> settings. For example.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'PAGINATE_BY': 10, # Default to 10
- 'PAGINATE_BY_PARAM': 'page_size', # Allow client to override, using `?page_size=xxx`.
- 'MAX_PAGINATE_BY': 100 # Maximum limit allowed when using `?page_size=xxx`.
-}
-</code></pre>
-<p>You can also set the pagination style on a per-view basis, using the <code>ListAPIView</code> generic class-based view.</p>
-<pre class="prettyprint lang-py"><code>class PaginatedListView(ListAPIView):
- queryset = ExampleModel.objects.all()
- serializer_class = ExampleModelSerializer
- paginate_by = 10
- paginate_by_param = 'page_size'
- max_paginate_by = 100
-</code></pre>
-<p>Note that using a <code>paginate_by</code> value of <code>None</code> will turn off pagination for the view.
-Note if you use the <code>PAGINATE_BY_PARAM</code> settings, you also have to set the <code>paginate_by_param</code> attribute in your view to <code>None</code> in order to turn off pagination for those requests that contain the <code>paginate_by_param</code> parameter.</p>
-<p>For more complex requirements such as serialization that differs depending on the requested media type you can override the <code>.get_paginate_by()</code> and <code>.get_pagination_serializer_class()</code> methods.</p>
-<hr />
-<h1 id="custom-pagination-serializers">Custom pagination serializers</h1>
-<p>To create a custom pagination serializer class you should override <code>pagination.BasePaginationSerializer</code> and set the fields that you want the serializer to return.</p>
-<p>You can also override the name used for the object list field, by setting the <code>results_field</code> attribute, which defaults to <code>'results'</code>.</p>
-<h2 id="example">Example</h2>
-<p>For example, to nest a pair of links labelled 'prev' and 'next', and set the name for the results field to 'objects', you might use something like this.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import pagination
-from rest_framework import serializers
-
-class LinksSerializer(serializers.Serializer):
- next = pagination.NextPageField(source='*')
- prev = pagination.PreviousPageField(source='*')
-
-class CustomPaginationSerializer(pagination.BasePaginationSerializer):
- links = LinksSerializer(source='*') # Takes the page object as the source
- total_results = serializers.Field(source='paginator.count')
-
- results_field = 'objects'
-</code></pre>
-<h2 id="using-your-custom-pagination-serializer">Using your custom pagination serializer</h2>
-<p>To have your custom pagination serializer be used by default, use the <code>DEFAULT_PAGINATION_SERIALIZER_CLASS</code> setting:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'DEFAULT_PAGINATION_SERIALIZER_CLASS':
- 'example_app.pagination.CustomPaginationSerializer',
-}
-</code></pre>
-<p>Alternatively, to set your custom pagination serializer on a per-view basis, use the <code>pagination_serializer_class</code> attribute on a generic class based view:</p>
-<pre class="prettyprint lang-py"><code>class PaginatedListView(generics.ListAPIView):
- model = ExampleModel
- pagination_serializer_class = CustomPaginationSerializer
- paginate_by = 10
-</code></pre>
-<h1 id="third-party-packages">Third party packages</h1>
-<p>The following third party packages are also available.</p>
-<h2 id="drf-extensions">DRF-extensions</h2>
-<p>The <a href="http://chibisov.github.io/drf-extensions/docs/"><code>DRF-extensions</code> package</a> includes a <a href="http://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin"><code>PaginateByMaxMixin</code> mixin class</a> that allows your API clients to specify <code>?page_size=max</code> to obtain the maximum allowed page size.</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/api-guide/pagination/index.html b/api-guide/pagination/index.html
new file mode 100644
index 00000000..95173edb
--- /dev/null
+++ b/api-guide/pagination/index.html
@@ -0,0 +1,581 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Pagination - 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/api-guide/pagination/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Pagination">
+ <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="../content-negotiation">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../filtering">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#pagination">Pagination</a>
+ </li>
+
+
+ <li>
+ <a href="#paginating-basic-data">Paginating basic data</a>
+ </li>
+
+ <li>
+ <a href="#paginating-querysets">Paginating QuerySets</a>
+ </li>
+
+ <li>
+ <a href="#pagination-in-the-generic-views">Pagination in the generic views</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-pagination-serializers">Custom pagination serializers</a>
+ </li>
+
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+ <li>
+ <a href="#using-your-custom-pagination-serializer">Using your custom pagination serializer</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#drf-extensions">DRF-extensions</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/pagination.py">
+ <span class="label label-info">pagination.py</span>
+ </a>
+
+
+
+ <h1 id="pagination">Pagination</h1>
+<blockquote>
+<p>Django provides a few classes that help you manage paginated data – that is, data that’s split across several pages, with “Previous/Next” links.</p>
+<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/topics/pagination/">Django documentation</a></p>
+</blockquote>
+<p>REST framework includes a <code>PaginationSerializer</code> class that makes it easy to return paginated data in a way that can then be rendered to arbitrary media types.</p>
+<h2 id="paginating-basic-data">Paginating basic data</h2>
+<p>Let's start by taking a look at an example from the Django documentation.</p>
+<pre><code>from django.core.paginator import Paginator
+
+objects = ['john', 'paul', 'george', 'ringo']
+paginator = Paginator(objects, 2)
+page = paginator.page(1)
+page.object_list
+# ['john', 'paul']
+</code></pre>
+<p>At this point we've got a page object. If we wanted to return this page object as a JSON response, we'd need to provide the client with context such as next and previous links, so that it would be able to page through the remaining results.</p>
+<pre><code>from rest_framework.pagination import PaginationSerializer
+
+serializer = PaginationSerializer(instance=page)
+serializer.data
+# {'count': 4, 'next': '?page=2', 'previous': None, 'results': [u'john', u'paul']}
+</code></pre>
+<p>The <code>context</code> argument of the <code>PaginationSerializer</code> class may optionally include the request. If the request is included in the context then the next and previous links returned by the serializer will use absolute URLs instead of relative URLs.</p>
+<pre><code>request = RequestFactory().get('/foobar')
+serializer = PaginationSerializer(instance=page, context={'request': request})
+serializer.data
+# {'count': 4, 'next': 'http://testserver/foobar?page=2', 'previous': None, 'results': [u'john', u'paul']}
+</code></pre>
+<p>We could now return that data in a <code>Response</code> object, and it would be rendered into the correct media type.</p>
+<h2 id="paginating-querysets">Paginating QuerySets</h2>
+<p>Our first example worked because we were using primitive objects. If we wanted to paginate a queryset or other complex data, we'd need to specify a serializer to use to serialize the result set itself.</p>
+<p>We can do this using the <code>object_serializer_class</code> attribute on the inner <code>Meta</code> class of the pagination serializer. For example.</p>
+<pre><code>class UserSerializer(serializers.ModelSerializer):
+ """
+ Serializes user querysets.
+ """
+ class Meta:
+ model = User
+ fields = ('username', 'email')
+
+class PaginatedUserSerializer(pagination.PaginationSerializer):
+ """
+ Serializes page objects of user querysets.
+ """
+ class Meta:
+ object_serializer_class = UserSerializer
+</code></pre>
+<p>We could now use our pagination serializer in a view like this.</p>
+<pre><code>@api_view('GET')
+def user_list(request):
+ queryset = User.objects.all()
+ paginator = Paginator(queryset, 20)
+
+ page = request.QUERY_PARAMS.get('page')
+ try:
+ users = paginator.page(page)
+ except PageNotAnInteger:
+ # If page is not an integer, deliver first page.
+ users = paginator.page(1)
+ except EmptyPage:
+ # If page is out of range (e.g. 9999),
+ # deliver last page of results.
+ users = paginator.page(paginator.num_pages)
+
+ serializer_context = {'request': request}
+ serializer = PaginatedUserSerializer(users,
+ context=serializer_context)
+ return Response(serializer.data)
+</code></pre>
+<h2 id="pagination-in-the-generic-views">Pagination in the generic views</h2>
+<p>The generic class based views <code>ListAPIView</code> and <code>ListCreateAPIView</code> provide pagination of the returned querysets by default. You can customise this behaviour by altering the pagination style, by modifying the default number of results, by allowing clients to override the page size using a query parameter, or by turning pagination off completely.</p>
+<p>The default pagination style may be set globally, using the <code>DEFAULT_PAGINATION_SERIALIZER_CLASS</code>, <code>PAGINATE_BY</code>, <code>PAGINATE_BY_PARAM</code>, and <code>MAX_PAGINATE_BY</code> settings. For example.</p>
+<pre><code>REST_FRAMEWORK = {
+ 'PAGINATE_BY': 10, # Default to 10
+ 'PAGINATE_BY_PARAM': 'page_size', # Allow client to override, using `?page_size=xxx`.
+ 'MAX_PAGINATE_BY': 100 # Maximum limit allowed when using `?page_size=xxx`.
+}
+</code></pre>
+<p>You can also set the pagination style on a per-view basis, using the <code>ListAPIView</code> generic class-based view.</p>
+<pre><code>class PaginatedListView(ListAPIView):
+ queryset = ExampleModel.objects.all()
+ serializer_class = ExampleModelSerializer
+ paginate_by = 10
+ paginate_by_param = 'page_size'
+ max_paginate_by = 100
+</code></pre>
+<p>Note that using a <code>paginate_by</code> value of <code>None</code> will turn off pagination for the view.
+Note if you use the <code>PAGINATE_BY_PARAM</code> settings, you also have to set the <code>paginate_by_param</code> attribute in your view to <code>None</code> in order to turn off pagination for those requests that contain the <code>paginate_by_param</code> parameter.</p>
+<p>For more complex requirements such as serialization that differs depending on the requested media type you can override the <code>.get_paginate_by()</code> and <code>.get_pagination_serializer_class()</code> methods.</p>
+<hr />
+<h1 id="custom-pagination-serializers">Custom pagination serializers</h1>
+<p>To create a custom pagination serializer class you should override <code>pagination.BasePaginationSerializer</code> and set the fields that you want the serializer to return.</p>
+<p>You can also override the name used for the object list field, by setting the <code>results_field</code> attribute, which defaults to <code>'results'</code>.</p>
+<h2 id="example">Example</h2>
+<p>For example, to nest a pair of links labelled 'prev' and 'next', and set the name for the results field to 'objects', you might use something like this.</p>
+<pre><code>from rest_framework import pagination
+from rest_framework import serializers
+
+class LinksSerializer(serializers.Serializer):
+ next = pagination.NextPageField(source='*')
+ prev = pagination.PreviousPageField(source='*')
+
+class CustomPaginationSerializer(pagination.BasePaginationSerializer):
+ links = LinksSerializer(source='*') # Takes the page object as the source
+ total_results = serializers.Field(source='paginator.count')
+
+ results_field = 'objects'
+</code></pre>
+<h2 id="using-your-custom-pagination-serializer">Using your custom pagination serializer</h2>
+<p>To have your custom pagination serializer be used by default, use the <code>DEFAULT_PAGINATION_SERIALIZER_CLASS</code> setting:</p>
+<pre><code>REST_FRAMEWORK = {
+ 'DEFAULT_PAGINATION_SERIALIZER_CLASS':
+ 'example_app.pagination.CustomPaginationSerializer',
+}
+</code></pre>
+<p>Alternatively, to set your custom pagination serializer on a per-view basis, use the <code>pagination_serializer_class</code> attribute on a generic class based view:</p>
+<pre><code>class PaginatedListView(generics.ListAPIView):
+ model = ExampleModel
+ pagination_serializer_class = CustomPaginationSerializer
+ paginate_by = 10
+</code></pre>
+<h1 id="third-party-packages">Third party packages</h1>
+<p>The following third party packages are also available.</p>
+<h2 id="drf-extensions">DRF-extensions</h2>
+<p>The <a href="http://chibisov.github.io/drf-extensions/docs/"><code>DRF-extensions</code> package</a> includes a <a href="http://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin"><code>PaginateByMaxMixin</code> mixin class</a> that allows your API clients to specify <code>?page_size=max</code> to obtain the maximum allowed page size.</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/api-guide/parsers.html b/api-guide/parsers.html
deleted file mode 100644
index 125c3b36..00000000
--- a/api-guide/parsers.html
+++ /dev/null
@@ -1,379 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Parsers - 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/api-guide/parsers"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Parsers, API Reference, Custom parsers, 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="parsers-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="../api-guide/renderers">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/routers"><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="#parsers">Parsers</a></li>
-<li><a href="#how-the-parser-is-determined">How the parser is determined</a></li>
-<li><a href="#setting-the-parsers">Setting the parsers</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#jsonparser">JSONParser</a></li>
-<li><a href="#yamlparser">YAMLParser</a></li>
-<li><a href="#xmlparser">XMLParser</a></li>
-<li><a href="#formparser">FormParser</a></li>
-<li><a href="#multipartparser">MultiPartParser</a></li>
-<li><a href="#fileuploadparser">FileUploadParser</a></li>
-<li class="main"><a href="#custom-parsers">Custom parsers</a></li>
-<li><a href="#example">Example</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#messagepack">MessagePack</a></li>
-<li><a href="#camelcase-json">CamelCase JSON</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/parsers.py"><span class="label label-info">parsers.py</span></a></p>
-<h1 id="parsers">Parsers</h1>
-<blockquote>
-<p>Machine interacting web services tend to use more
-structured formats for sending data than form-encoded, since they're
-sending more complex data than simple forms</p>
-<p>&mdash; Malcom Tredinnick, <a href="https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion">Django developers group</a></p>
-</blockquote>
-<p>REST framework includes a number of built in Parser classes, that allow you to accept requests with various media types. There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts.</p>
-<h2 id="how-the-parser-is-determined">How the parser is determined</h2>
-<p>The set of valid parsers for a view is always defined as a list of classes. When either <code>request.DATA</code> or <code>request.FILES</code> is accessed, REST framework will examine the <code>Content-Type</code> header on the incoming request, and determine which parser to use to parse the request content.</p>
-<hr />
-<p><strong>Note</strong>: When developing client applications always remember to make sure you're setting the <code>Content-Type</code> header when sending data in an HTTP request.</p>
-<p>If you don't set the content type, most clients will default to using <code>'application/x-www-form-urlencoded'</code>, which may not be what you wanted.</p>
-<p>As an example, if you are sending <code>json</code> encoded data using jQuery with the <a href="http://api.jquery.com/jQuery.ajax/">.ajax() method</a>, you should make sure to include the <code>contentType: 'application/json'</code> setting.</p>
-<hr />
-<h2 id="setting-the-parsers">Setting the parsers</h2>
-<p>The default set of parsers may be set globally, using the <code>DEFAULT_PARSER_CLASSES</code> setting. For example, the following settings would allow requests with <code>YAML</code> content.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'DEFAULT_PARSER_CLASSES': (
- 'rest_framework.parsers.YAMLParser',
- )
-}
-</code></pre>
-<p>You can also set the parsers used for an individual view, or viewset,
-using the <code>APIView</code> class based views.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.parsers import YAMLParser
-from rest_framework.response import Response
-from rest_framework.views import APIView
-
-class ExampleView(APIView):
- """
- A view that can accept POST requests with YAML content.
- """
- parser_classes = (YAMLParser,)
-
- def post(self, request, format=None):
- return Response({'received data': request.DATA})
-</code></pre>
-<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
-<pre class="prettyprint lang-py"><code>@api_view(['POST'])
-@parser_classes((YAMLParser,))
-def example_view(request, format=None):
- """
- A view that can accept POST requests with YAML content.
- """
- return Response({'received data': request.DATA})
-</code></pre>
-<hr />
-<h1 id="api-reference">API Reference</h1>
-<h2 id="jsonparser">JSONParser</h2>
-<p>Parses <code>JSON</code> request content.</p>
-<p><strong>.media_type</strong>: <code>application/json</code></p>
-<h2 id="yamlparser">YAMLParser</h2>
-<p>Parses <code>YAML</code> request content.</p>
-<p>Requires the <code>pyyaml</code> package to be installed.</p>
-<p><strong>.media_type</strong>: <code>application/yaml</code></p>
-<h2 id="xmlparser">XMLParser</h2>
-<p>Parses REST framework's default style of <code>XML</code> request content.</p>
-<p>Note that the <code>XML</code> markup language is typically used as the base language for more strictly defined domain-specific languages, such as <code>RSS</code>, <code>Atom</code>, and <code>XHTML</code>.</p>
-<p>If you are considering using <code>XML</code> for your API, you may want to consider implementing a custom renderer and parser for your specific requirements, and using an existing domain-specific media-type, or creating your own custom XML-based media-type.</p>
-<p>Requires the <code>defusedxml</code> package to be installed.</p>
-<p><strong>.media_type</strong>: <code>application/xml</code></p>
-<h2 id="formparser">FormParser</h2>
-<p>Parses HTML form content. <code>request.DATA</code> will be populated with a <code>QueryDict</code> of data, <code>request.FILES</code> will be populated with an empty <code>QueryDict</code> of data.</p>
-<p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p>
-<p><strong>.media_type</strong>: <code>application/x-www-form-urlencoded</code></p>
-<h2 id="multipartparser">MultiPartParser</h2>
-<p>Parses multipart HTML form content, which supports file uploads. Both <code>request.DATA</code> and <code>request.FILES</code> will be populated with a <code>QueryDict</code>.</p>
-<p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p>
-<p><strong>.media_type</strong>: <code>multipart/form-data</code></p>
-<h2 id="fileuploadparser">FileUploadParser</h2>
-<p>Parses raw file upload content. The <code>request.DATA</code> property will be an empty <code>QueryDict</code>, and <code>request.FILES</code> will be a dictionary with a single key <code>'file'</code> containing the uploaded file.</p>
-<p>If the view used with <code>FileUploadParser</code> is called with a <code>filename</code> URL keyword argument, then that argument will be used as the filename. If it is called without a <code>filename</code> URL keyword argument, then the client must set the filename in the <code>Content-Disposition</code> HTTP header. For example <code>Content-Disposition: attachment; filename=upload.jpg</code>.</p>
-<p><strong>.media_type</strong>: <code>*/*</code></p>
-<h5 id="notes">Notes:</h5>
-<ul>
-<li>The <code>FileUploadParser</code> is for usage with native clients that can upload the file as a raw data request. For web-based uploads, or for native clients with multipart upload support, you should use the <code>MultiPartParser</code> parser instead.</li>
-<li>Since this parser's <code>media_type</code> matches any content type, <code>FileUploadParser</code> should generally be the only parser set on an API view.</li>
-<li><code>FileUploadParser</code> respects Django's standard <code>FILE_UPLOAD_HANDLERS</code> setting, and the <code>request.upload_handlers</code> attribute. See the <a href="https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#upload-handlers">Django documentation</a> for more details.</li>
-</ul>
-<h5 id="basic-usage-example">Basic usage example:</h5>
-<pre class="prettyprint lang-py"><code>class FileUploadView(views.APIView):
- parser_classes = (FileUploadParser,)
-
- def put(self, request, filename, format=None):
- file_obj = request.FILES['file']
- # ...
- # do some staff with uploaded file
- # ...
- return Response(status=204)
-</code></pre>
-<hr />
-<h1 id="custom-parsers">Custom parsers</h1>
-<p>To implement a custom parser, you should override <code>BaseParser</code>, set the <code>.media_type</code> property, and implement the <code>.parse(self, stream, media_type, parser_context)</code> method.</p>
-<p>The method should return the data that will be used to populate the <code>request.DATA</code> property.</p>
-<p>The arguments passed to <code>.parse()</code> are:</p>
-<h3 id="stream">stream</h3>
-<p>A stream-like object representing the body of the request.</p>
-<h3 id="media_type">media_type</h3>
-<p>Optional. If provided, this is the media type of the incoming request content.</p>
-<p>Depending on the request's <code>Content-Type:</code> header, this may be more specific than the renderer's <code>media_type</code> attribute, and may include media type parameters. For example <code>"text/plain; charset=utf-8"</code>.</p>
-<h3 id="parser_context">parser_context</h3>
-<p>Optional. If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content.</p>
-<p>By default this will include the following keys: <code>view</code>, <code>request</code>, <code>args</code>, <code>kwargs</code>.</p>
-<h2 id="example">Example</h2>
-<p>The following is an example plaintext parser that will populate the <code>request.DATA</code> property with a string representing the body of the request. </p>
-<pre class="prettyprint lang-py"><code>class PlainTextParser(BaseParser):
-"""
-Plain text parser.
-"""
-
-media_type = 'text/plain'
-
-def parse(self, stream, media_type=None, parser_context=None):
- """
- Simply return a string representing the body of the request.
- """
- return stream.read()
-</code></pre>
-<hr />
-<h1 id="third-party-packages">Third party packages</h1>
-<p>The following third party packages are also available.</p>
-<h2 id="messagepack">MessagePack</h2>
-<p><a href="https://github.com/juanriaza/django-rest-framework-msgpack">MessagePack</a> is a fast, efficient binary serialization format. <a href="https://github.com/juanriaza">Juan Riaza</a> maintains the <a href="https://github.com/juanriaza/django-rest-framework-msgpack">djangorestframework-msgpack</a> package which provides MessagePack renderer and parser support for REST framework.</p>
-<h2 id="camelcase-json">CamelCase JSON</h2>
-<p><a href="https://github.com/vbabiy/djangorestframework-camel-case">djangorestframework-camel-case</a> provides camel case JSON renderers and parsers for REST framework. This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names. It is maintained by <a href="https://github.com/vbabiy">Vitaly Babiy</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="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/api-guide/parsers/index.html b/api-guide/parsers/index.html
new file mode 100644
index 00000000..b606f6fa
--- /dev/null
+++ b/api-guide/parsers/index.html
@@ -0,0 +1,621 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Parsers - 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/api-guide/parsers/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Parsers">
+ <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="../renderers">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../routers">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#parsers">Parsers</a>
+ </li>
+
+
+ <li>
+ <a href="#how-the-parser-is-determined">How the parser is determined</a>
+ </li>
+
+ <li>
+ <a href="#setting-the-parsers">Setting the parsers</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#jsonparser">JSONParser</a>
+ </li>
+
+ <li>
+ <a href="#yamlparser">YAMLParser</a>
+ </li>
+
+ <li>
+ <a href="#xmlparser">XMLParser</a>
+ </li>
+
+ <li>
+ <a href="#formparser">FormParser</a>
+ </li>
+
+ <li>
+ <a href="#multipartparser">MultiPartParser</a>
+ </li>
+
+ <li>
+ <a href="#fileuploadparser">FileUploadParser</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-parsers">Custom parsers</a>
+ </li>
+
+
+ <li>
+ <a href="#stream">stream</a>
+ </li>
+
+ <li>
+ <a href="#media_type">media_type</a>
+ </li>
+
+ <li>
+ <a href="#parser_context">parser_context</a>
+ </li>
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#messagepack">MessagePack</a>
+ </li>
+
+ <li>
+ <a href="#camelcase-json">CamelCase JSON</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/parsers.py">
+ <span class="label label-info">parsers.py</span>
+ </a>
+
+
+
+ <h1 id="parsers">Parsers</h1>
+<blockquote>
+<p>Machine interacting web services tend to use more
+structured formats for sending data than form-encoded, since they're
+sending more complex data than simple forms</p>
+<p>&mdash; Malcom Tredinnick, <a href="https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion">Django developers group</a></p>
+</blockquote>
+<p>REST framework includes a number of built in Parser classes, that allow you to accept requests with various media types. There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts.</p>
+<h2 id="how-the-parser-is-determined">How the parser is determined</h2>
+<p>The set of valid parsers for a view is always defined as a list of classes. When either <code>request.DATA</code> or <code>request.FILES</code> is accessed, REST framework will examine the <code>Content-Type</code> header on the incoming request, and determine which parser to use to parse the request content.</p>
+<hr />
+<p><strong>Note</strong>: When developing client applications always remember to make sure you're setting the <code>Content-Type</code> header when sending data in an HTTP request.</p>
+<p>If you don't set the content type, most clients will default to using <code>'application/x-www-form-urlencoded'</code>, which may not be what you wanted.</p>
+<p>As an example, if you are sending <code>json</code> encoded data using jQuery with the <a href="http://api.jquery.com/jQuery.ajax/">.ajax() method</a>, you should make sure to include the <code>contentType: 'application/json'</code> setting.</p>
+<hr />
+<h2 id="setting-the-parsers">Setting the parsers</h2>
+<p>The default set of parsers may be set globally, using the <code>DEFAULT_PARSER_CLASSES</code> setting. For example, the following settings would allow requests with <code>YAML</code> content.</p>
+<pre><code>REST_FRAMEWORK = {
+ 'DEFAULT_PARSER_CLASSES': (
+ 'rest_framework.parsers.YAMLParser',
+ )
+}
+</code></pre>
+<p>You can also set the parsers used for an individual view, or viewset,
+using the <code>APIView</code> class based views.</p>
+<pre><code>from rest_framework.parsers import YAMLParser
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+class ExampleView(APIView):
+ """
+ A view that can accept POST requests with YAML content.
+ """
+ parser_classes = (YAMLParser,)
+
+ def post(self, request, format=None):
+ return Response({'received data': request.DATA})
+</code></pre>
+<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
+<pre><code>@api_view(['POST'])
+@parser_classes((YAMLParser,))
+def example_view(request, format=None):
+ """
+ A view that can accept POST requests with YAML content.
+ """
+ return Response({'received data': request.DATA})
+</code></pre>
+<hr />
+<h1 id="api-reference">API Reference</h1>
+<h2 id="jsonparser">JSONParser</h2>
+<p>Parses <code>JSON</code> request content.</p>
+<p><strong>.media_type</strong>: <code>application/json</code></p>
+<h2 id="yamlparser">YAMLParser</h2>
+<p>Parses <code>YAML</code> request content.</p>
+<p>Requires the <code>pyyaml</code> package to be installed.</p>
+<p><strong>.media_type</strong>: <code>application/yaml</code></p>
+<h2 id="xmlparser">XMLParser</h2>
+<p>Parses REST framework's default style of <code>XML</code> request content.</p>
+<p>Note that the <code>XML</code> markup language is typically used as the base language for more strictly defined domain-specific languages, such as <code>RSS</code>, <code>Atom</code>, and <code>XHTML</code>.</p>
+<p>If you are considering using <code>XML</code> for your API, you may want to consider implementing a custom renderer and parser for your specific requirements, and using an existing domain-specific media-type, or creating your own custom XML-based media-type.</p>
+<p>Requires the <code>defusedxml</code> package to be installed.</p>
+<p><strong>.media_type</strong>: <code>application/xml</code></p>
+<h2 id="formparser">FormParser</h2>
+<p>Parses HTML form content. <code>request.DATA</code> will be populated with a <code>QueryDict</code> of data, <code>request.FILES</code> will be populated with an empty <code>QueryDict</code> of data.</p>
+<p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p>
+<p><strong>.media_type</strong>: <code>application/x-www-form-urlencoded</code></p>
+<h2 id="multipartparser">MultiPartParser</h2>
+<p>Parses multipart HTML form content, which supports file uploads. Both <code>request.DATA</code> and <code>request.FILES</code> will be populated with a <code>QueryDict</code>.</p>
+<p>You will typically want to use both <code>FormParser</code> and <code>MultiPartParser</code> together in order to fully support HTML form data.</p>
+<p><strong>.media_type</strong>: <code>multipart/form-data</code></p>
+<h2 id="fileuploadparser">FileUploadParser</h2>
+<p>Parses raw file upload content. The <code>request.DATA</code> property will be an empty <code>QueryDict</code>, and <code>request.FILES</code> will be a dictionary with a single key <code>'file'</code> containing the uploaded file.</p>
+<p>If the view used with <code>FileUploadParser</code> is called with a <code>filename</code> URL keyword argument, then that argument will be used as the filename. If it is called without a <code>filename</code> URL keyword argument, then the client must set the filename in the <code>Content-Disposition</code> HTTP header. For example <code>Content-Disposition: attachment; filename=upload.jpg</code>.</p>
+<p><strong>.media_type</strong>: <code>*/*</code></p>
+<h5 id="notes">Notes:</h5>
+<ul>
+<li>The <code>FileUploadParser</code> is for usage with native clients that can upload the file as a raw data request. For web-based uploads, or for native clients with multipart upload support, you should use the <code>MultiPartParser</code> parser instead.</li>
+<li>Since this parser's <code>media_type</code> matches any content type, <code>FileUploadParser</code> should generally be the only parser set on an API view.</li>
+<li><code>FileUploadParser</code> respects Django's standard <code>FILE_UPLOAD_HANDLERS</code> setting, and the <code>request.upload_handlers</code> attribute. See the <a href="https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#upload-handlers">Django documentation</a> for more details.</li>
+</ul>
+<h5 id="basic-usage-example">Basic usage example:</h5>
+<pre><code>class FileUploadView(views.APIView):
+ parser_classes = (FileUploadParser,)
+
+ def put(self, request, filename, format=None):
+ file_obj = request.FILES['file']
+ # ...
+ # do some staff with uploaded file
+ # ...
+ return Response(status=204)
+</code></pre>
+<hr />
+<h1 id="custom-parsers">Custom parsers</h1>
+<p>To implement a custom parser, you should override <code>BaseParser</code>, set the <code>.media_type</code> property, and implement the <code>.parse(self, stream, media_type, parser_context)</code> method.</p>
+<p>The method should return the data that will be used to populate the <code>request.DATA</code> property.</p>
+<p>The arguments passed to <code>.parse()</code> are:</p>
+<h3 id="stream">stream</h3>
+<p>A stream-like object representing the body of the request.</p>
+<h3 id="media_type">media_type</h3>
+<p>Optional. If provided, this is the media type of the incoming request content.</p>
+<p>Depending on the request's <code>Content-Type:</code> header, this may be more specific than the renderer's <code>media_type</code> attribute, and may include media type parameters. For example <code>"text/plain; charset=utf-8"</code>.</p>
+<h3 id="parser_context">parser_context</h3>
+<p>Optional. If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content.</p>
+<p>By default this will include the following keys: <code>view</code>, <code>request</code>, <code>args</code>, <code>kwargs</code>.</p>
+<h2 id="example">Example</h2>
+<p>The following is an example plaintext parser that will populate the <code>request.DATA</code> property with a string representing the body of the request.</p>
+<pre><code>class PlainTextParser(BaseParser):
+"""
+Plain text parser.
+"""
+
+media_type = 'text/plain'
+
+def parse(self, stream, media_type=None, parser_context=None):
+ """
+ Simply return a string representing the body of the request.
+ """
+ return stream.read()
+</code></pre>
+<hr />
+<h1 id="third-party-packages">Third party packages</h1>
+<p>The following third party packages are also available.</p>
+<h2 id="messagepack">MessagePack</h2>
+<p><a href="https://github.com/juanriaza/django-rest-framework-msgpack">MessagePack</a> is a fast, efficient binary serialization format. <a href="https://github.com/juanriaza">Juan Riaza</a> maintains the <a href="https://github.com/juanriaza/django-rest-framework-msgpack">djangorestframework-msgpack</a> package which provides MessagePack renderer and parser support for REST framework.</p>
+<h2 id="camelcase-json">CamelCase JSON</h2>
+<p><a href="https://github.com/vbabiy/djangorestframework-camel-case">djangorestframework-camel-case</a> provides camel case JSON renderers and parsers for REST framework. This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names. It is maintained by <a href="https://github.com/vbabiy">Vitaly Babiy</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="../../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/api-guide/permissions.html b/api-guide/permissions.html
deleted file mode 100644
index 70d70604..00000000
--- a/api-guide/permissions.html
+++ /dev/null
@@ -1,429 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Permissions - 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/api-guide/permissions"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Permissions, API Reference, Custom permissions, 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="permissions-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="../api-guide/throttling">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/authentication"><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="#permissions">Permissions</a></li>
-<li><a href="#how-permissions-are-determined">How permissions are determined</a></li>
-<li><a href="#object-level-permissions">Object level permissions</a></li>
-<li><a href="#setting-the-permission-policy">Setting the permission policy</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#allowany">AllowAny</a></li>
-<li><a href="#isauthenticated">IsAuthenticated</a></li>
-<li><a href="#isadminuser">IsAdminUser</a></li>
-<li><a href="#isauthenticatedorreadonly">IsAuthenticatedOrReadOnly</a></li>
-<li><a href="#djangomodelpermissions">DjangoModelPermissions</a></li>
-<li><a href="#djangomodelpermissionsoranonreadonly">DjangoModelPermissionsOrAnonReadOnly</a></li>
-<li><a href="#tokenhasreadwritescope">TokenHasReadWriteScope</a></li>
-<li class="main"><a href="#custom-permissions">Custom permissions</a></li>
-<li><a href="#examples">Examples</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#drf-any-permissions">DRF Any Permissions</a></li>
-<li><a href="#composed-permissions">Composed Permissions</a></li>
-<li><a href="#rest-condition">REST Condition</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/permissions.py"><span class="label label-info">permissions.py</span></a></p>
-<h1 id="permissions">Permissions</h1>
-<blockquote>
-<p>Authentication or identification by itself is not usually sufficient to gain access to information or code. For that, the entity requesting access must have authorization.</p>
-<p>&mdash; <a href="https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html">Apple Developer Documentation</a></p>
-</blockquote>
-<p>Together with <a href="authentication">authentication</a> and <a href="throttling">throttling</a>, permissions determine whether a request should be granted or denied access.</p>
-<p>Permission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the <code>request.user</code> and <code>request.auth</code> properties to determine if the incoming request should be permitted.</p>
-<h2 id="how-permissions-are-determined">How permissions are determined</h2>
-<p>Permissions in REST framework are always defined as a list of permission classes. </p>
-<p>Before running the main body of the view each permission in the list is checked.
-If any permission check fails an <code>exceptions.PermissionDenied</code> exception will be raised, and the main body of the view will not run.</p>
-<h2 id="object-level-permissions">Object level permissions</h2>
-<p>REST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.</p>
-<p>Object level permissions are run by REST framework's generic views when <code>.get_object()</code> is called.
-As with view level permissions, an <code>exceptions.PermissionDenied</code> exception will be raised if the user is not allowed to act on the given object.</p>
-<p>If you're writing your own views and want to enforce object level permissions,
-or if you override the <code>get_object</code> method on a generic view, then you'll need to explicitly call the <code>.check_object_permissions(request, obj)</code> method on the view at the point at which you've retrieved the object.</p>
-<p>This will either raise a <code>PermissionDenied</code> or <code>NotAuthenticated</code> exception, or simply return if the view has the appropriate permissions.</p>
-<p>For example:</p>
-<pre class="prettyprint lang-py"><code>def get_object(self):
- obj = get_object_or_404(self.get_queryset())
- self.check_object_permissions(self.request, obj)
- return obj
-</code></pre>
-<h4 id="limitations-of-object-level-permissions">Limitations of object level permissions</h4>
-<p>For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.</p>
-<p>Often when you're using object level permissions you'll also want to <a href="filtering">filter the queryset</a> appropriately, to ensure that users only have visibility onto instances that they are permitted to view.</p>
-<h2 id="setting-the-permission-policy">Setting the permission policy</h2>
-<p>The default permission policy may be set globally, using the <code>DEFAULT_PERMISSION_CLASSES</code> setting. For example.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'DEFAULT_PERMISSION_CLASSES': (
- 'rest_framework.permissions.IsAuthenticated',
- )
-}
-</code></pre>
-<p>If not specified, this setting defaults to allowing unrestricted access:</p>
-<pre class="prettyprint lang-py"><code>'DEFAULT_PERMISSION_CLASSES': (
- 'rest_framework.permissions.AllowAny',
-)
-</code></pre>
-<p>You can also set the authentication policy on a per-view, or per-viewset basis,
-using the <code>APIView</code> class based views.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.permissions import IsAuthenticated
-from rest_framework.response import Response
-from rest_framework.views import APIView
-
-class ExampleView(APIView):
- permission_classes = (IsAuthenticated,)
-
- def get(self, request, format=None):
- content = {
- 'status': 'request was permitted'
- }
- return Response(content)
-</code></pre>
-<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
-<pre class="prettyprint lang-py"><code>@api_view('GET')
-@permission_classes((IsAuthenticated, ))
-def example_view(request, format=None):
- content = {
- 'status': 'request was permitted'
- }
- return Response(content)
-</code></pre>
-<hr />
-<h1 id="api-reference">API Reference</h1>
-<h2 id="allowany">AllowAny</h2>
-<p>The <code>AllowAny</code> permission class will allow unrestricted access, <strong>regardless of if the request was authenticated or unauthenticated</strong>.</p>
-<p>This permission is not strictly required, since you can achieve the same result by using an empty list or tuple for the permissions setting, but you may find it useful to specify this class because it makes the intention explicit.</p>
-<h2 id="isauthenticated">IsAuthenticated</h2>
-<p>The <code>IsAuthenticated</code> permission class will deny permission to any unauthenticated user, and allow permission otherwise.</p>
-<p>This permission is suitable if you want your API to only be accessible to registered users.</p>
-<h2 id="isadminuser">IsAdminUser</h2>
-<p>The <code>IsAdminUser</code> permission class will deny permission to any user, unless <code>user.is_staff</code> is <code>True</code> in which case permission will be allowed.</p>
-<p>This permission is suitable is you want your API to only be accessible to a subset of trusted administrators.</p>
-<h2 id="isauthenticatedorreadonly">IsAuthenticatedOrReadOnly</h2>
-<p>The <code>IsAuthenticatedOrReadOnly</code> will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the "safe" methods; <code>GET</code>, <code>HEAD</code> or <code>OPTIONS</code>.</p>
-<p>This permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users.</p>
-<h2 id="djangomodelpermissions">DjangoModelPermissions</h2>
-<p>This permission class ties into Django's standard <code>django.contrib.auth</code> <a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#custom-permissions">model permissions</a>. This permission must only be applied to views that has a <code>.queryset</code> property set. Authorization will only be granted if the user <em>is authenticated</em> and has the <em>relevant model permissions</em> assigned.</p>
-<ul>
-<li><code>POST</code> requests require the user to have the <code>add</code> permission on the model.</li>
-<li><code>PUT</code> and <code>PATCH</code> requests require the user to have the <code>change</code> permission on the model.</li>
-<li><code>DELETE</code> requests require the user to have the <code>delete</code> permission on the model.</li>
-</ul>
-<p>The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a <code>view</code> model permission for <code>GET</code> requests.</p>
-<p>To use custom model permissions, override <code>DjangoModelPermissions</code> and set the <code>.perms_map</code> property. Refer to the source code for details.</p>
-<h4 id="using-with-views-that-do-not-include-a-queryset-attribute">Using with views that do not include a <code>queryset</code> attribute.</h4>
-<p>If you're using this permission with a view that uses an overridden <code>get_queryset()</code> method there may not be a <code>queryset</code> attribute on the view. In this case we suggest also marking the view with a sential queryset, so that this class can determine the required permissions. For example:</p>
-<pre class="prettyprint lang-py"><code>queryset = User.objects.none() # Required for DjangoModelPermissions
-</code></pre>
-<h2 id="djangomodelpermissionsoranonreadonly">DjangoModelPermissionsOrAnonReadOnly</h2>
-<p>Similar to <code>DjangoModelPermissions</code>, but also allows unauthenticated users to have read-only access to the API.</p>
-<h2 id="djangoobjectpermissions">DjangoObjectPermissions</h2>
-<p>This permission class ties into Django's standard <a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#handling-object-permissions">object permissions framework</a> that allows per-object permissions on models. In order to use this permission class, you'll also need to add a permission backend that supports object-level permissions, such as <a href="https://github.com/lukaszb/django-guardian">django-guardian</a>.</p>
-<p>As with <code>DjangoModelPermissions</code>, this permission must only be applied to views that have a <code>.queryset</code> property. Authorization will only be granted if the user <em>is authenticated</em> and has the <em>relevant per-object permissions</em> and <em>relevant model permissions</em> assigned.</p>
-<ul>
-<li><code>POST</code> requests require the user to have the <code>add</code> permission on the model instance.</li>
-<li><code>PUT</code> and <code>PATCH</code> requests require the user to have the <code>change</code> permission on the model instance.</li>
-<li><code>DELETE</code> requests require the user to have the <code>delete</code> permission on the model instance.</li>
-</ul>
-<p>Note that <code>DjangoObjectPermissions</code> <strong>does not</strong> require the <code>django-guardian</code> package, and should support other object-level backends equally well.</p>
-<p>As with <code>DjangoModelPermissions</code> you can use custom model permissions by overriding <code>DjangoModelPermissions</code> and setting the <code>.perms_map</code> property. Refer to the source code for details. Note that if you add a custom <code>view</code> permission for <code>GET</code>, <code>HEAD</code> and <code>OPTIONS</code> requests, you'll probably also want to consider adding the <code>DjangoObjectPermissionsFilter</code> class to ensure that list endpoints only return results including objects for which the user has appropriate view permissions.</p>
-<h2 id="tokenhasreadwritescope">TokenHasReadWriteScope</h2>
-<p>This permission class is intended for use with either of the <code>OAuthAuthentication</code> and <code>OAuth2Authentication</code> classes, and ties into the scoping that their backends provide.</p>
-<p>Requests with a safe methods of <code>GET</code>, <code>OPTIONS</code> or <code>HEAD</code> will be allowed if the authenticated token has read permission.</p>
-<p>Requests for <code>POST</code>, <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> will be allowed if the authenticated token has write permission.</p>
-<p>This permission class relies on the implementations of the <a href="http://code.larlet.fr/django-oauth-plus">django-oauth-plus</a> and <a href="https://github.com/caffeinehit/django-oauth2-provider">django-oauth2-provider</a> libraries, which both provide limited support for controlling the scope of access tokens:</p>
-<ul>
-<li><code>django-oauth-plus</code>: Tokens are associated with a <code>Resource</code> class which has a <code>name</code>, <code>url</code> and <code>is_readonly</code> properties.</li>
-<li><code>django-oauth2-provider</code>: Tokens are associated with a bitwise <code>scope</code> attribute, that defaults to providing bitwise values for <code>read</code> and/or <code>write</code>.</li>
-</ul>
-<p>If you require more advanced scoping for your API, such as restricting tokens to accessing a subset of functionality of your API then you will need to provide a custom permission class. See the source of the <code>django-oauth-plus</code> or <code>django-oauth2-provider</code> package for more details on scoping token access.</p>
-<hr />
-<h1 id="custom-permissions">Custom permissions</h1>
-<p>To implement a custom permission, override <code>BasePermission</code> and implement either, or both, of the following methods:</p>
-<ul>
-<li><code>.has_permission(self, request, view)</code></li>
-<li><code>.has_object_permission(self, request, view, obj)</code></li>
-</ul>
-<p>The methods should return <code>True</code> if the request should be granted access, and <code>False</code> otherwise.</p>
-<p>If you need to test if a request is a read operation or a write operation, you should check the request method against the constant <code>SAFE_METHODS</code>, which is a tuple containing <code>'GET'</code>, <code>'OPTIONS'</code> and <code>'HEAD'</code>. For example:</p>
-<pre class="prettyprint lang-py"><code>if request.method in permissions.SAFE_METHODS:
- # Check permissions for read-only request
-else:
- # Check permissions for write request
-</code></pre>
-<hr />
-<p><strong>Note</strong>: In versions 2.0 and 2.1, the signature for the permission checks always included an optional <code>obj</code> parameter, like so: <code>.has_permission(self, request, view, obj=None)</code>. The method would be called twice, first for the global permission checks, with no object supplied, and second for the object-level check when required.</p>
-<p>As of version 2.2 this signature has now been replaced with two separate method calls, which is more explicit and obvious. The old style signature continues to work, but its use will result in a <code>PendingDeprecationWarning</code>, which is silent by default. In 2.3 this will be escalated to a <code>DeprecationWarning</code>, and in 2.4 the old-style signature will be removed.</p>
-<p>For more details see the <a href="../topics/2.2-announcement">2.2 release announcement</a>.</p>
-<hr />
-<h2 id="examples">Examples</h2>
-<p>The following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import permissions
-
-class BlacklistPermission(permissions.BasePermission):
- """
- Global permission check for blacklisted IPs.
- """
-
- def has_permission(self, request, view):
- ip_addr = request.META['REMOTE_ADDR']
- blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()
- return not blacklisted
-</code></pre>
-<p>As well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example:</p>
-<pre class="prettyprint lang-py"><code>class IsOwnerOrReadOnly(permissions.BasePermission):
- """
- Object-level permission to only allow owners of an object to edit it.
- Assumes the model instance has an `owner` attribute.
- """
-
- def has_object_permission(self, request, view, obj):
- # Read permissions are allowed to any request,
- # so we'll always allow GET, HEAD or OPTIONS requests.
- if request.method in permissions.SAFE_METHODS:
- return True
-
- # Instance must have an attribute named `owner`.
- return obj.owner == request.user
-</code></pre>
-<p>Note that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself. You can do so by calling <code>self.check_object_permissions(request, obj)</code> from the view once you have the object instance. This call will raise an appropriate <code>APIException</code> if any object-level permission checks fail, and will otherwise simply return.</p>
-<p>Also note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you'll need to filter the queryset separately. See the <a href="filtering">filtering documentation</a> for more details.</p>
-<hr />
-<h1 id="third-party-packages">Third party packages</h1>
-<p>The following third party packages are also available.</p>
-<h2 id="drf-any-permissions">DRF Any Permissions</h2>
-<p>The <a href="https://github.com/kevin-brown/drf-any-permissions">DRF Any Permissions</a> packages provides a different permission behavior in contrast to REST framework. Instead of all specified permissions being required, only one of the given permissions has to be true in order to get access to the view.</p>
-<h2 id="composed-permissions">Composed Permissions</h2>
-<p>The <a href="https://github.com/niwibe/djangorestframework-composed-permissions">Composed Permissions</a> package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components.</p>
-<h2 id="rest-condition">REST Condition</h2>
-<p>The <a href="https://github.com/caxap/rest_condition">REST Condition</a> package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.</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/api-guide/permissions/index.html b/api-guide/permissions/index.html
new file mode 100644
index 00000000..85b5985c
--- /dev/null
+++ b/api-guide/permissions/index.html
@@ -0,0 +1,673 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Permissions - 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/api-guide/permissions/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Permissions">
+ <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="../throttling">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../authentication">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#permissions">Permissions</a>
+ </li>
+
+
+ <li>
+ <a href="#how-permissions-are-determined">How permissions are determined</a>
+ </li>
+
+ <li>
+ <a href="#object-level-permissions">Object level permissions</a>
+ </li>
+
+ <li>
+ <a href="#setting-the-permission-policy">Setting the permission policy</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#allowany">AllowAny</a>
+ </li>
+
+ <li>
+ <a href="#isauthenticated">IsAuthenticated</a>
+ </li>
+
+ <li>
+ <a href="#isadminuser">IsAdminUser</a>
+ </li>
+
+ <li>
+ <a href="#isauthenticatedorreadonly">IsAuthenticatedOrReadOnly</a>
+ </li>
+
+ <li>
+ <a href="#djangomodelpermissions">DjangoModelPermissions</a>
+ </li>
+
+ <li>
+ <a href="#djangomodelpermissionsoranonreadonly">DjangoModelPermissionsOrAnonReadOnly</a>
+ </li>
+
+ <li>
+ <a href="#djangoobjectpermissions">DjangoObjectPermissions</a>
+ </li>
+
+ <li>
+ <a href="#tokenhasreadwritescope">TokenHasReadWriteScope</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-permissions">Custom permissions</a>
+ </li>
+
+
+ <li>
+ <a href="#examples">Examples</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#drf-any-permissions">DRF Any Permissions</a>
+ </li>
+
+ <li>
+ <a href="#composed-permissions">Composed Permissions</a>
+ </li>
+
+ <li>
+ <a href="#rest-condition">REST Condition</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/permissions.py">
+ <span class="label label-info">permissions.py</span>
+ </a>
+
+
+
+ <h1 id="permissions">Permissions</h1>
+<blockquote>
+<p>Authentication or identification by itself is not usually sufficient to gain access to information or code. For that, the entity requesting access must have authorization.</p>
+<p>&mdash; <a href="https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html">Apple Developer Documentation</a></p>
+</blockquote>
+<p>Together with <a href="../authentication">authentication</a> and <a href="../throttling">throttling</a>, permissions determine whether a request should be granted or denied access.</p>
+<p>Permission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the <code>request.user</code> and <code>request.auth</code> properties to determine if the incoming request should be permitted.</p>
+<h2 id="how-permissions-are-determined">How permissions are determined</h2>
+<p>Permissions in REST framework are always defined as a list of permission classes.</p>
+<p>Before running the main body of the view each permission in the list is checked.
+If any permission check fails an <code>exceptions.PermissionDenied</code> exception will be raised, and the main body of the view will not run.</p>
+<h2 id="object-level-permissions">Object level permissions</h2>
+<p>REST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.</p>
+<p>Object level permissions are run by REST framework's generic views when <code>.get_object()</code> is called.
+As with view level permissions, an <code>exceptions.PermissionDenied</code> exception will be raised if the user is not allowed to act on the given object.</p>
+<p>If you're writing your own views and want to enforce object level permissions,
+or if you override the <code>get_object</code> method on a generic view, then you'll need to explicitly call the <code>.check_object_permissions(request, obj)</code> method on the view at the point at which you've retrieved the object.</p>
+<p>This will either raise a <code>PermissionDenied</code> or <code>NotAuthenticated</code> exception, or simply return if the view has the appropriate permissions.</p>
+<p>For example:</p>
+<pre><code>def get_object(self):
+ obj = get_object_or_404(self.get_queryset())
+ self.check_object_permissions(self.request, obj)
+ return obj
+</code></pre>
+<h4 id="limitations-of-object-level-permissions">Limitations of object level permissions</h4>
+<p>For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.</p>
+<p>Often when you're using object level permissions you'll also want to <a href="../filtering">filter the queryset</a> appropriately, to ensure that users only have visibility onto instances that they are permitted to view.</p>
+<h2 id="setting-the-permission-policy">Setting the permission policy</h2>
+<p>The default permission policy may be set globally, using the <code>DEFAULT_PERMISSION_CLASSES</code> setting. For example.</p>
+<pre><code>REST_FRAMEWORK = {
+ 'DEFAULT_PERMISSION_CLASSES': (
+ 'rest_framework.permissions.IsAuthenticated',
+ )
+}
+</code></pre>
+<p>If not specified, this setting defaults to allowing unrestricted access:</p>
+<pre><code>'DEFAULT_PERMISSION_CLASSES': (
+ 'rest_framework.permissions.AllowAny',
+)
+</code></pre>
+<p>You can also set the authentication policy on a per-view, or per-viewset basis,
+using the <code>APIView</code> class based views.</p>
+<pre><code>from rest_framework.permissions import IsAuthenticated
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+class ExampleView(APIView):
+ permission_classes = (IsAuthenticated,)
+
+ def get(self, request, format=None):
+ content = {
+ 'status': 'request was permitted'
+ }
+ return Response(content)
+</code></pre>
+<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
+<pre><code>@api_view('GET')
+@permission_classes((IsAuthenticated, ))
+def example_view(request, format=None):
+ content = {
+ 'status': 'request was permitted'
+ }
+ return Response(content)
+</code></pre>
+<hr />
+<h1 id="api-reference">API Reference</h1>
+<h2 id="allowany">AllowAny</h2>
+<p>The <code>AllowAny</code> permission class will allow unrestricted access, <strong>regardless of if the request was authenticated or unauthenticated</strong>.</p>
+<p>This permission is not strictly required, since you can achieve the same result by using an empty list or tuple for the permissions setting, but you may find it useful to specify this class because it makes the intention explicit.</p>
+<h2 id="isauthenticated">IsAuthenticated</h2>
+<p>The <code>IsAuthenticated</code> permission class will deny permission to any unauthenticated user, and allow permission otherwise.</p>
+<p>This permission is suitable if you want your API to only be accessible to registered users.</p>
+<h2 id="isadminuser">IsAdminUser</h2>
+<p>The <code>IsAdminUser</code> permission class will deny permission to any user, unless <code>user.is_staff</code> is <code>True</code> in which case permission will be allowed.</p>
+<p>This permission is suitable is you want your API to only be accessible to a subset of trusted administrators.</p>
+<h2 id="isauthenticatedorreadonly">IsAuthenticatedOrReadOnly</h2>
+<p>The <code>IsAuthenticatedOrReadOnly</code> will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the "safe" methods; <code>GET</code>, <code>HEAD</code> or <code>OPTIONS</code>.</p>
+<p>This permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users.</p>
+<h2 id="djangomodelpermissions">DjangoModelPermissions</h2>
+<p>This permission class ties into Django's standard <code>django.contrib.auth</code> <a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#custom-permissions">model permissions</a>. This permission must only be applied to views that has a <code>.queryset</code> property set. Authorization will only be granted if the user <em>is authenticated</em> and has the <em>relevant model permissions</em> assigned.</p>
+<ul>
+<li><code>POST</code> requests require the user to have the <code>add</code> permission on the model.</li>
+<li><code>PUT</code> and <code>PATCH</code> requests require the user to have the <code>change</code> permission on the model.</li>
+<li><code>DELETE</code> requests require the user to have the <code>delete</code> permission on the model.</li>
+</ul>
+<p>The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a <code>view</code> model permission for <code>GET</code> requests.</p>
+<p>To use custom model permissions, override <code>DjangoModelPermissions</code> and set the <code>.perms_map</code> property. Refer to the source code for details.</p>
+<h4 id="using-with-views-that-do-not-include-a-queryset-attribute">Using with views that do not include a <code>queryset</code> attribute.</h4>
+<p>If you're using this permission with a view that uses an overridden <code>get_queryset()</code> method there may not be a <code>queryset</code> attribute on the view. In this case we suggest also marking the view with a sential queryset, so that this class can determine the required permissions. For example:</p>
+<pre><code>queryset = User.objects.none() # Required for DjangoModelPermissions
+</code></pre>
+<h2 id="djangomodelpermissionsoranonreadonly">DjangoModelPermissionsOrAnonReadOnly</h2>
+<p>Similar to <code>DjangoModelPermissions</code>, but also allows unauthenticated users to have read-only access to the API.</p>
+<h2 id="djangoobjectpermissions">DjangoObjectPermissions</h2>
+<p>This permission class ties into Django's standard <a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#handling-object-permissions">object permissions framework</a> that allows per-object permissions on models. In order to use this permission class, you'll also need to add a permission backend that supports object-level permissions, such as <a href="https://github.com/lukaszb/django-guardian">django-guardian</a>.</p>
+<p>As with <code>DjangoModelPermissions</code>, this permission must only be applied to views that have a <code>.queryset</code> property. Authorization will only be granted if the user <em>is authenticated</em> and has the <em>relevant per-object permissions</em> and <em>relevant model permissions</em> assigned.</p>
+<ul>
+<li><code>POST</code> requests require the user to have the <code>add</code> permission on the model instance.</li>
+<li><code>PUT</code> and <code>PATCH</code> requests require the user to have the <code>change</code> permission on the model instance.</li>
+<li><code>DELETE</code> requests require the user to have the <code>delete</code> permission on the model instance.</li>
+</ul>
+<p>Note that <code>DjangoObjectPermissions</code> <strong>does not</strong> require the <code>django-guardian</code> package, and should support other object-level backends equally well.</p>
+<p>As with <code>DjangoModelPermissions</code> you can use custom model permissions by overriding <code>DjangoModelPermissions</code> and setting the <code>.perms_map</code> property. Refer to the source code for details.</p>
+<hr />
+<p><strong>Note</strong>: If you need object level <code>view</code> permissions for <code>GET</code>, <code>HEAD</code> and <code>OPTIONS</code> requests, you'll want to consider also adding the <code>DjangoObjectPermissionsFilter</code> class to ensure that list endpoints only return results including objects for which the user has appropriate view permissions.</p>
+<hr />
+<h2 id="tokenhasreadwritescope">TokenHasReadWriteScope</h2>
+<p>This permission class is intended for use with either of the <code>OAuthAuthentication</code> and <code>OAuth2Authentication</code> classes, and ties into the scoping that their backends provide.</p>
+<p>Requests with a safe methods of <code>GET</code>, <code>OPTIONS</code> or <code>HEAD</code> will be allowed if the authenticated token has read permission.</p>
+<p>Requests for <code>POST</code>, <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> will be allowed if the authenticated token has write permission.</p>
+<p>This permission class relies on the implementations of the <a href="http://code.larlet.fr/django-oauth-plus">django-oauth-plus</a> and <a href="https://github.com/caffeinehit/django-oauth2-provider">django-oauth2-provider</a> libraries, which both provide limited support for controlling the scope of access tokens:</p>
+<ul>
+<li><code>django-oauth-plus</code>: Tokens are associated with a <code>Resource</code> class which has a <code>name</code>, <code>url</code> and <code>is_readonly</code> properties.</li>
+<li><code>django-oauth2-provider</code>: Tokens are associated with a bitwise <code>scope</code> attribute, that defaults to providing bitwise values for <code>read</code> and/or <code>write</code>.</li>
+</ul>
+<p>If you require more advanced scoping for your API, such as restricting tokens to accessing a subset of functionality of your API then you will need to provide a custom permission class. See the source of the <code>django-oauth-plus</code> or <code>django-oauth2-provider</code> package for more details on scoping token access.</p>
+<hr />
+<h1 id="custom-permissions">Custom permissions</h1>
+<p>To implement a custom permission, override <code>BasePermission</code> and implement either, or both, of the following methods:</p>
+<ul>
+<li><code>.has_permission(self, request, view)</code></li>
+<li><code>.has_object_permission(self, request, view, obj)</code></li>
+</ul>
+<p>The methods should return <code>True</code> if the request should be granted access, and <code>False</code> otherwise.</p>
+<p>If you need to test if a request is a read operation or a write operation, you should check the request method against the constant <code>SAFE_METHODS</code>, which is a tuple containing <code>'GET'</code>, <code>'OPTIONS'</code> and <code>'HEAD'</code>. For example:</p>
+<pre><code>if request.method in permissions.SAFE_METHODS:
+ # Check permissions for read-only request
+else:
+ # Check permissions for write request
+</code></pre>
+<hr />
+<p><strong>Note</strong>: The instance-level <code>has_object_permission</code> method will only be called if the view-level <code>has_permission</code> checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call <code>.check_object_permissions(request, obj)</code>. If you are using the generic views then this will be handled for you by default.</p>
+<hr />
+<h2 id="examples">Examples</h2>
+<p>The following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted.</p>
+<pre><code>from rest_framework import permissions
+
+class BlacklistPermission(permissions.BasePermission):
+ """
+ Global permission check for blacklisted IPs.
+ """
+
+ def has_permission(self, request, view):
+ ip_addr = request.META['REMOTE_ADDR']
+ blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()
+ return not blacklisted
+</code></pre>
+<p>As well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example:</p>
+<pre><code>class IsOwnerOrReadOnly(permissions.BasePermission):
+ """
+ Object-level permission to only allow owners of an object to edit it.
+ Assumes the model instance has an `owner` attribute.
+ """
+
+ def has_object_permission(self, request, view, obj):
+ # Read permissions are allowed to any request,
+ # so we'll always allow GET, HEAD or OPTIONS requests.
+ if request.method in permissions.SAFE_METHODS:
+ return True
+
+ # Instance must have an attribute named `owner`.
+ return obj.owner == request.user
+</code></pre>
+<p>Note that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself. You can do so by calling <code>self.check_object_permissions(request, obj)</code> from the view once you have the object instance. This call will raise an appropriate <code>APIException</code> if any object-level permission checks fail, and will otherwise simply return.</p>
+<p>Also note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you'll need to filter the queryset separately. See the <a href="../filtering">filtering documentation</a> for more details.</p>
+<hr />
+<h1 id="third-party-packages">Third party packages</h1>
+<p>The following third party packages are also available.</p>
+<h2 id="drf-any-permissions">DRF Any Permissions</h2>
+<p>The <a href="https://github.com/kevin-brown/drf-any-permissions">DRF Any Permissions</a> packages provides a different permission behavior in contrast to REST framework. Instead of all specified permissions being required, only one of the given permissions has to be true in order to get access to the view.</p>
+<h2 id="composed-permissions">Composed Permissions</h2>
+<p>The <a href="https://github.com/niwibe/djangorestframework-composed-permissions">Composed Permissions</a> package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components.</p>
+<h2 id="rest-condition">REST Condition</h2>
+<p>The <a href="https://github.com/caxap/rest_condition">REST Condition</a> package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.</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/api-guide/relations.html b/api-guide/relations/index.html
index 64e5d989..ea662ba8 100644
--- a/api-guide/relations.html
+++ b/api-guide/relations/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>Serializer relations - 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/api-guide/relations"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Serializer relations, API Reference, Nested relationships, Custom relational fields, Further notes, 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="relations-page">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Serializer relations - 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/api-guide/relations/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Serializer relations">
+ <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="../api-guide/authentication">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/fields"><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="../validators">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../fields">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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>
+ <!--/.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,37 +335,128 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#serializer-relations">Serializer relations</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#relatedfield">RelatedField</a></li>
-<li><a href="#primarykeyrelatedfield">PrimaryKeyRelatedField</a></li>
-<li><a href="#hyperlinkedrelatedfield">HyperlinkedRelatedField</a></li>
-<li><a href="#slugrelatedfield">SlugRelatedField</a></li>
-<li><a href="#hyperlinkedidentityfield">HyperlinkedIdentityField</a></li>
-<li class="main"><a href="#nested-relationships">Nested relationships</a></li>
-<li><a href="#example">Example</a></li>
-<li class="main"><a href="#custom-relational-fields">Custom relational fields</a></li>
-<li><a href="#example">Example</a></li>
-<li class="main"><a href="#further-notes">Further notes</a></li>
-<li><a href="#reverse-relations">Reverse relations</a></li>
-<li><a href="#generic-relationships">Generic relationships</a></li>
-<li><a href="#manytomanyfields-with-a-through-model">ManyToManyFields with a Through Model</a></li>
-<li><a href="#advanced-hyperlinked-fields">Advanced Hyperlinked fields</a></li>
-<li><a href="#deprecated-apis">Deprecated APIs</a></li>
-<li class="main"><a href="#third-party-packages">Third Party Packages</a></li>
-<li><a href="#drf-nested-routers">DRF Nested Routers</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#serializer-relations">Serializer relations</a>
+ </li>
+
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#relatedfield">RelatedField</a>
+ </li>
+
+ <li>
+ <a href="#primarykeyrelatedfield">PrimaryKeyRelatedField</a>
+ </li>
+
+ <li>
+ <a href="#hyperlinkedrelatedfield">HyperlinkedRelatedField</a>
+ </li>
+
+ <li>
+ <a href="#slugrelatedfield">SlugRelatedField</a>
+ </li>
+
+ <li>
+ <a href="#hyperlinkedidentityfield">HyperlinkedIdentityField</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#nested-relationships">Nested relationships</a>
+ </li>
+
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-relational-fields">Custom relational fields</a>
+ </li>
+
+
+ <li>
+ <a href="#example_1">Example</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#further-notes">Further notes</a>
+ </li>
+
+
+ <li>
+ <a href="#reverse-relations">Reverse relations</a>
+ </li>
+
+ <li>
+ <a href="#generic-relationships">Generic relationships</a>
+ </li>
+
+ <li>
+ <a href="#manytomanyfields-with-a-through-model">ManyToManyFields with a Through Model</a>
+ </li>
+
+ <li>
+ <a href="#advanced-hyperlinked-fields">Advanced Hyperlinked fields</a>
+ </li>
+
+ <li>
+ <a href="#deprecated-apis">Deprecated APIs</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third Party Packages</a>
+ </li>
+
+
+ <li>
+ <a href="#drf-nested-routers">DRF Nested Routers</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/relations.py"><span class="label label-info">relations.py</span></a></p>
-<h1 id="serializer-relations">Serializer relations</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/relations.py">
+ <span class="label label-info">relations.py</span>
+ </a>
+
+
+
+ <h1 id="serializer-relations">Serializer relations</h1>
<blockquote>
<p>Bad programmers worry about the code.
Good programmers worry about data structures and their relationships.</p>
@@ -228,7 +468,7 @@ Good programmers worry about data structures and their relationships.</p>
<hr />
<h1 id="api-reference">API Reference</h1>
<p>In order to explain the various types of relational fields, we'll use a couple of simple models for our examples. Our models will be for music albums, and the tracks listed on each album.</p>
-<pre class="prettyprint lang-py"><code>class Album(models.Model):
+<pre><code>class Album(models.Model):
album_name = models.CharField(max_length=100)
artist = models.CharField(max_length=100)
@@ -248,7 +488,7 @@ class Track(models.Model):
<h2 id="relatedfield">RelatedField</h2>
<p><code>RelatedField</code> may be used to represent the target of the relationship using its <code>__unicode__</code> method.</p>
<p>For example, the following serializer.</p>
-<pre class="prettyprint lang-py"><code>class AlbumSerializer(serializers.ModelSerializer):
+<pre><code>class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.RelatedField(many=True)
class Meta:
@@ -256,7 +496,7 @@ class Track(models.Model):
fields = ('album_name', 'artist', 'tracks')
</code></pre>
<p>Would serialize to the following representation.</p>
-<pre class="prettyprint lang-py"><code>{
+<pre><code>{
'album_name': 'Things We Lost In The Fire',
'artist': 'Low',
'tracks': [
@@ -275,7 +515,7 @@ class Track(models.Model):
<h2 id="primarykeyrelatedfield">PrimaryKeyRelatedField</h2>
<p><code>PrimaryKeyRelatedField</code> may be used to represent the target of the relationship using its primary key.</p>
<p>For example, the following serializer:</p>
-<pre class="prettyprint lang-py"><code>class AlbumSerializer(serializers.ModelSerializer):
+<pre><code>class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
@@ -283,7 +523,7 @@ class Track(models.Model):
fields = ('album_name', 'artist', 'tracks')
</code></pre>
<p>Would serialize to a representation like this:</p>
-<pre class="prettyprint lang-py"><code>{
+<pre><code>{
'album_name': 'The Roots',
'artist': 'Undun',
'tracks': [
@@ -304,7 +544,7 @@ class Track(models.Model):
<h2 id="hyperlinkedrelatedfield">HyperlinkedRelatedField</h2>
<p><code>HyperlinkedRelatedField</code> may be used to represent the target of the relationship using a hyperlink.</p>
<p>For example, the following serializer:</p>
-<pre class="prettyprint lang-py"><code>class AlbumSerializer(serializers.ModelSerializer):
+<pre><code>class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.HyperlinkedRelatedField(many=True, read_only=True,
view_name='track-detail')
@@ -313,7 +553,7 @@ class Track(models.Model):
fields = ('album_name', 'artist', 'tracks')
</code></pre>
<p>Would serialize to a representation like this:</p>
-<pre class="prettyprint lang-py"><code>{
+<pre><code>{
'album_name': 'Graceland',
'artist': 'Paul Simon',
'tracks': [
@@ -337,7 +577,7 @@ class Track(models.Model):
<h2 id="slugrelatedfield">SlugRelatedField</h2>
<p><code>SlugRelatedField</code> may be used to represent the target of the relationship using a field on the target.</p>
<p>For example, the following serializer:</p>
-<pre class="prettyprint lang-py"><code>class AlbumSerializer(serializers.ModelSerializer):
+<pre><code>class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.SlugRelatedField(many=True, read_only=True,
slug_field='title')
@@ -346,7 +586,7 @@ class Track(models.Model):
fields = ('album_name', 'artist', 'tracks')
</code></pre>
<p>Would serialize to a representation like this:</p>
-<pre class="prettyprint lang-py"><code>{
+<pre><code>{
'album_name': 'Dear John',
'artist': 'Loney Dear',
'tracks': [
@@ -368,7 +608,7 @@ class Track(models.Model):
</ul>
<h2 id="hyperlinkedidentityfield">HyperlinkedIdentityField</h2>
<p>This field can be applied as an identity relationship, such as the <code>'url'</code> field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer:</p>
-<pre class="prettyprint lang-py"><code>class AlbumSerializer(serializers.HyperlinkedModelSerializer):
+<pre><code>class AlbumSerializer(serializers.HyperlinkedModelSerializer):
track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')
class Meta:
@@ -376,7 +616,7 @@ class Track(models.Model):
fields = ('album_name', 'artist', 'track_listing')
</code></pre>
<p>Would serialize to a representation like this:</p>
-<pre class="prettyprint lang-py"><code>{
+<pre><code>{
'album_name': 'The Eraser',
'artist': 'Thom Yorke',
'track_listing': 'http://www.example.com/api/track_list/12/',
@@ -385,7 +625,7 @@ class Track(models.Model):
<p>This field is always read-only.</p>
<p><strong>Arguments</strong>:</p>
<ul>
-<li><code>view_name</code> - The view name that should be used as the target of the relationship. If you're using <a href="http://www.django-rest-framework.org/api-guide/routers#defaultrouter">the standard router classes</a> this wil be a string with the format <code>&lt;model_name&gt;-detail</code>. <strong>required</strong>.</li>
+<li><code>view_name</code> - The view name that should be used as the target of the relationship. If you're using <a href="http://www.django-rest-framework.org/api-guide/routers#defaultrouter">the standard router classes</a> this will be a string with the format <code>&lt;model_name&gt;-detail</code>. <strong>required</strong>.</li>
<li><code>lookup_field</code> - The field on the target that should be used for the lookup. Should correspond to a URL keyword argument on the referenced view. Default is <code>'pk'</code>.</li>
<li><code>format</code> - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the <code>format</code> argument.</li>
</ul>
@@ -395,7 +635,7 @@ class Track(models.Model):
<p>If the field is used to represent a to-many relationship, you should add the <code>many=True</code> flag to the serializer field.</p>
<h2 id="example">Example</h2>
<p>For example, the following serializer:</p>
-<pre class="prettyprint lang-py"><code>class TrackSerializer(serializers.ModelSerializer):
+<pre><code>class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('order', 'title')
@@ -408,7 +648,7 @@ class AlbumSerializer(serializers.ModelSerializer):
fields = ('album_name', 'artist', 'tracks')
</code></pre>
<p>Would serialize to a nested representation like this:</p>
-<pre class="prettyprint lang-py"><code>{
+<pre><code>{
'album_name': 'The Grey Album',
'artist': 'Danger Mouse',
'tracks': [
@@ -424,7 +664,7 @@ class AlbumSerializer(serializers.ModelSerializer):
<p>If you want to implement a read-write relational field, you must also implement the <code>.from_native(self, data)</code> method, and add <code>read_only = False</code> to the class definition.</p>
<h2 id="example_1">Example</h2>
<p>For, example, we could define a relational field, to serialize a track to a custom string representation, using its ordering, title, and duration.</p>
-<pre class="prettyprint lang-py"><code>import time
+<pre><code>import time
class TrackListingField(serializers.RelatedField):
def to_native(self, value):
@@ -439,7 +679,7 @@ class AlbumSerializer(serializers.ModelSerializer):
fields = ('album_name', 'artist', 'tracks')
</code></pre>
<p>This custom field would then serialize to the following representation.</p>
-<pre class="prettyprint lang-py"><code>{
+<pre><code>{
'album_name': 'Sometimes I Wish We Were an Eagle',
'artist': 'Bill Callahan',
'tracks': [
@@ -454,17 +694,17 @@ class AlbumSerializer(serializers.ModelSerializer):
<h1 id="further-notes">Further notes</h1>
<h2 id="reverse-relations">Reverse relations</h2>
<p>Note that reverse relationships are not automatically included by the <code>ModelSerializer</code> and <code>HyperlinkedModelSerializer</code> classes. To include a reverse relationship, you must explicitly add it to the fields list. For example:</p>
-<pre class="prettyprint lang-py"><code>class AlbumSerializer(serializers.ModelSerializer):
+<pre><code>class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ('tracks', ...)
</code></pre>
<p>You'll normally want to ensure that you've set an appropriate <code>related_name</code> argument on the relationship, that you can use as the field name. For example:</p>
-<pre class="prettyprint lang-py"><code>class Track(models.Model):
+<pre><code>class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks')
...
</code></pre>
<p>If you have not set a related name for the reverse relationship, you'll need to use the automatically generated related name in the <code>fields</code> argument. For example:</p>
-<pre class="prettyprint lang-py"><code>class AlbumSerializer(serializers.ModelSerializer):
+<pre><code>class AlbumSerializer(serializers.ModelSerializer):
class Meta:
fields = ('track_set', ...)
</code></pre>
@@ -472,7 +712,7 @@ class AlbumSerializer(serializers.ModelSerializer):
<h2 id="generic-relationships">Generic relationships</h2>
<p>If you want to serialize a generic foreign key, you need to define a custom field, to determine explicitly how you want serialize the targets of the relationship.</p>
<p>For example, given the following model for a tag, which has a generic relationship with other arbitrary models:</p>
-<pre class="prettyprint lang-py"><code>class TaggedItem(models.Model):
+<pre><code>class TaggedItem(models.Model):
"""
Tags arbitrary model instances using a generic relation.
@@ -487,7 +727,7 @@ class AlbumSerializer(serializers.ModelSerializer):
return self.tag
</code></pre>
<p>And the following two models, which may be have associated tags:</p>
-<pre class="prettyprint lang-py"><code>class Bookmark(models.Model):
+<pre><code>class Bookmark(models.Model):
"""
A bookmark consists of a URL, and 0 or more descriptive tags.
"""
@@ -503,7 +743,7 @@ class Note(models.Model):
tags = GenericRelation(TaggedItem)
</code></pre>
<p>We could define a custom field that could be used to serialize tagged instances, using the type of each instance to determine how it should be serialized.</p>
-<pre class="prettyprint lang-py"><code>class TaggedObjectRelatedField(serializers.RelatedField):
+<pre><code>class TaggedObjectRelatedField(serializers.RelatedField):
"""
A custom field to use for the `tagged_object` generic relationship.
"""
@@ -511,7 +751,7 @@ class Note(models.Model):
def to_native(self, value):
"""
Serialize tagged objects to a simple textual representation.
- """
+ """
if isinstance(value, Bookmark):
return 'Bookmark: ' + value.url
elif isinstance(value, Note):
@@ -519,11 +759,11 @@ class Note(models.Model):
raise Exception('Unexpected type of tagged object')
</code></pre>
<p>If you need the target of the relationship to have a nested representation, you can use the required serializers inside the <code>.to_native()</code> method:</p>
-<pre class="prettyprint lang-py"><code> def to_native(self, value):
+<pre><code> def to_native(self, value):
"""
Serialize bookmark instances using a bookmark serializer,
and note instances using a note serializer.
- """
+ """
if isinstance(value, Bookmark):
serializer = BookmarkSerializer(value)
elif isinstance(value, Note):
@@ -542,7 +782,7 @@ class Note(models.Model):
<code>ManyToManyField</code> with a through model, be sure to set <code>read_only</code>
to <code>True</code>.</p>
<h2 id="advanced-hyperlinked-fields">Advanced Hyperlinked fields</h2>
-<p>If you have very specific requirements for the style of your hyperlinked relationships you can override <code>HyperlinkedRelatedField</code>. </p>
+<p>If you have very specific requirements for the style of your hyperlinked relationships you can override <code>HyperlinkedRelatedField</code>.</p>
<p>There are two methods you'll need to override.</p>
<h4 id="get_urlself-obj-view_name-request-format">get_url(self, obj, view_name, request, format)</h4>
<p>This method should return the URL that corresponds to the given object.</p>
@@ -552,8 +792,8 @@ attributes are not configured to correctly match the URL conf.</p>
<p>This method should the object that corresponds to the matched URL conf arguments.</p>
<p>May raise an <code>ObjectDoesNotExist</code> exception.</p>
<h3 id="example_2">Example</h3>
-<p>For example, if all your object URLs used both a account and a slug in the the URL to reference the object, you might create a custom field like this: </p>
-<pre class="prettyprint lang-py"><code>class CustomHyperlinkedField(serializers.HyperlinkedRelatedField):
+<p>For example, if all your object URLs used both a account and a slug in the the URL to reference the object, you might create a custom field like this:</p>
+<pre><code>class CustomHyperlinkedField(serializers.HyperlinkedRelatedField):
def get_url(self, obj, view_name, request, format):
kwargs = {'account': obj.account, 'slug': obj.slug}
return reverse(view_name, kwargs=kwargs, request=request, format=format)
@@ -576,48 +816,58 @@ They continue to function, but their usage will raise a <code>PendingDeprecation
<p>The <code>null=&lt;bool&gt;</code> flag has been deprecated in favor of the <code>required=&lt;bool&gt;</code> flag. It will continue to function, but will raise a <code>PendingDeprecationWarning</code>.</p>
<p>In the 2.3 release, these warnings will be escalated to a <code>DeprecationWarning</code>, which is loud by default.
In the 2.4 release, these parts of the API will be removed entirely.</p>
-<p>For more details see the <a href="../topics/2.2-announcement">2.2 release announcement</a>.</p>
+<p>For more details see the <a href="../../topics/2.2-announcement">2.2 release announcement</a>.</p>
<hr />
<h1 id="third-party-packages">Third Party Packages</h1>
<p>The following third party packages are also available.</p>
<h2 id="drf-nested-routers">DRF Nested Routers</h2>
<p>The <a href="https://github.com/alanjds/drf-nested-routers">drf-nested-routers package</a> provides routers and relationship fields for working with nested resources.</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/api-guide/renderers.html b/api-guide/renderers/index.html
index 3ce83b72..b29a88bf 100644
--- a/api-guide/renderers.html
+++ b/api-guide/renderers/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>Renderers - 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/api-guide/renderers"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Renderers, API Reference, Custom renderers, Advanced renderer usage, 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="renderers-page">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Renderers - 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/api-guide/renderers/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Renderers">
+ <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="../api-guide/serializers">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/parsers"><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="../serializers">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../parsers">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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>
+ <!--/.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,48 +335,176 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#renderers">Renderers</a></li>
-<li><a href="#how-the-renderer-is-determined">How the renderer is determined</a></li>
-<li><a href="#setting-the-renderers">Setting the renderers</a></li>
-<li><a href="#ordering-of-renderer-classes">Ordering of renderer classes</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#jsonrenderer">JSONRenderer</a></li>
-<li><a href="#unicodejsonrenderer">UnicodeJSONRenderer</a></li>
-<li><a href="#jsonprenderer">JSONPRenderer</a></li>
-<li><a href="#yamlrenderer">YAMLRenderer</a></li>
-<li><a href="#unicodeyamlrenderer">UnicodeYAMLRenderer</a></li>
-<li><a href="#xmlrenderer">XMLRenderer</a></li>
-<li><a href="#templatehtmlrenderer">TemplateHTMLRenderer</a></li>
-<li><a href="#statichtmlrenderer">StaticHTMLRenderer</a></li>
-<li><a href="#htmlformrenderer">HTMLFormRenderer</a></li>
-<li><a href="#browsableapirenderer">BrowsableAPIRenderer</a></li>
-<li><a href="#multipartrenderer">MultiPartRenderer</a></li>
-<li class="main"><a href="#custom-renderers">Custom renderers</a></li>
-<li><a href="#example">Example</a></li>
-<li><a href="#setting-the-character-set">Setting the character set</a></li>
-<li class="main"><a href="#advanced-renderer-usage">Advanced renderer usage</a></li>
-<li><a href="#varying-behaviour-by-media-type">Varying behaviour by media type</a></li>
-<li><a href="#underspecifying-the-media-type">Underspecifying the media type</a></li>
-<li><a href="#designing-your-media-types">Designing your media types</a></li>
-<li><a href="#html-error-views">HTML error views</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#messagepack">MessagePack</a></li>
-<li><a href="#csv">CSV</a></li>
-<li><a href="#ultrajson">UltraJSON</a></li>
-<li><a href="#camelcase-json">CamelCase JSON</a></li>
-<li><a href="#pandas-(csv,-excel,-png)">Pandas (CSV, Excel, PNG)</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#renderers">Renderers</a>
+ </li>
+
+
+ <li>
+ <a href="#how-the-renderer-is-determined">How the renderer is determined</a>
+ </li>
+
+ <li>
+ <a href="#setting-the-renderers">Setting the renderers</a>
+ </li>
+
+ <li>
+ <a href="#ordering-of-renderer-classes">Ordering of renderer classes</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#jsonrenderer">JSONRenderer</a>
+ </li>
+
+ <li>
+ <a href="#jsonprenderer">JSONPRenderer</a>
+ </li>
+
+ <li>
+ <a href="#yamlrenderer">YAMLRenderer</a>
+ </li>
+
+ <li>
+ <a href="#unicodeyamlrenderer">UnicodeYAMLRenderer</a>
+ </li>
+
+ <li>
+ <a href="#xmlrenderer">XMLRenderer</a>
+ </li>
+
+ <li>
+ <a href="#templatehtmlrenderer">TemplateHTMLRenderer</a>
+ </li>
+
+ <li>
+ <a href="#statichtmlrenderer">StaticHTMLRenderer</a>
+ </li>
+
+ <li>
+ <a href="#htmlformrenderer">HTMLFormRenderer</a>
+ </li>
+
+ <li>
+ <a href="#browsableapirenderer">BrowsableAPIRenderer</a>
+ </li>
+
+ <li>
+ <a href="#multipartrenderer">MultiPartRenderer</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-renderers">Custom renderers</a>
+ </li>
+
+
+ <li>
+ <a href="#data">data</a>
+ </li>
+
+ <li>
+ <a href="#media_typenone">media_type=None</a>
+ </li>
+
+ <li>
+ <a href="#renderer_contextnone">renderer_context=None</a>
+ </li>
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+ <li>
+ <a href="#setting-the-character-set">Setting the character set</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#advanced-renderer-usage">Advanced renderer usage</a>
+ </li>
+
+
+ <li>
+ <a href="#varying-behaviour-by-media-type">Varying behaviour by media type</a>
+ </li>
+
+ <li>
+ <a href="#underspecifying-the-media-type">Underspecifying the media type</a>
+ </li>
+
+ <li>
+ <a href="#designing-your-media-types">Designing your media types</a>
+ </li>
+
+ <li>
+ <a href="#html-error-views">HTML error views</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#messagepack">MessagePack</a>
+ </li>
+
+ <li>
+ <a href="#csv">CSV</a>
+ </li>
+
+ <li>
+ <a href="#ultrajson">UltraJSON</a>
+ </li>
+
+ <li>
+ <a href="#camelcase-json">CamelCase JSON</a>
+ </li>
+
+ <li>
+ <a href="#pandas-csv-excel-png">Pandas (CSV, Excel, PNG)</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/renderers.py"><span class="label label-info">renderers.py</span></a></p>
-<h1 id="renderers">Renderers</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/renderers.py">
+ <span class="label label-info">renderers.py</span>
+ </a>
+
+
+
+ <h1 id="renderers">Renderers</h1>
<blockquote>
<p>Before a TemplateResponse instance can be returned to the client, it must be rendered. The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client.</p>
<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/template-response/#the-rendering-process">Django documentation</a></p>
@@ -236,10 +513,10 @@ a.fusion-poweredby {
<h2 id="how-the-renderer-is-determined">How the renderer is determined</h2>
<p>The set of valid renderers for a view is always defined as a list of classes. When a view is entered REST framework will perform content negotiation on the incoming request, and determine the most appropriate renderer to satisfy the request.</p>
<p>The basic process of content negotiation involves examining the request's <code>Accept</code> header, to determine which media types it expects in the response. Optionally, format suffixes on the URL may be used to explicitly request a particular representation. For example the URL <code>http://example.com/api/users_count.json</code> might be an endpoint that always returns JSON data.</p>
-<p>For more information see the documentation on <a href="content-negotiation">content negotiation</a>.</p>
+<p>For more information see the documentation on <a href="../content-negotiation">content negotiation</a>.</p>
<h2 id="setting-the-renderers">Setting the renderers</h2>
<p>The default set of renderers may be set globally, using the <code>DEFAULT_RENDERER_CLASSES</code> setting. For example, the following settings would use <code>YAML</code> as the main media type and also include the self describing API.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
+<pre><code>REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.YAMLRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
@@ -248,7 +525,7 @@ a.fusion-poweredby {
</code></pre>
<p>You can also set the renderers used for an individual view, or viewset,
using the <code>APIView</code> class based views.</p>
-<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
+<pre><code>from django.contrib.auth.models import User
from rest_framework.renderers import JSONRenderer, YAMLRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
@@ -265,7 +542,7 @@ class UserCountView(APIView):
return Response(content)
</code></pre>
<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
-<pre class="prettyprint lang-py"><code>@api_view(['GET'])
+<pre><code>@api_view(['GET'])
@renderer_classes((JSONRenderer, JSONPRenderer))
def user_count_view(request, format=None):
"""
@@ -283,28 +560,16 @@ def user_count_view(request, format=None):
<h1 id="api-reference">API Reference</h1>
<h2 id="jsonrenderer">JSONRenderer</h2>
<p>Renders the request data into <code>JSON</code>, using utf-8 encoding.</p>
-<p>Note that non-ascii characters will be rendered using JSON's <code>\uXXXX</code> character escape. For example:</p>
-<pre class="prettyprint lang-py"><code>{"unicode black star": "\u2605"}
-</code></pre>
-<p>The client may additionally include an <code>'indent'</code> media type parameter, in which case the returned <code>JSON</code> will be indented. For example <code>Accept: application/json; indent=4</code>.</p>
-<pre class="prettyprint lang-py"><code>{
- "unicode black star": "\u2605"
-}
-</code></pre>
-<p><strong>.media_type</strong>: <code>application/json</code></p>
-<p><strong>.format</strong>: <code>'.json'</code></p>
-<p><strong>.charset</strong>: <code>None</code></p>
-<h2 id="unicodejsonrenderer">UnicodeJSONRenderer</h2>
-<p>Renders the request data into <code>JSON</code>, using utf-8 encoding.</p>
-<p>Note that non-ascii characters will not be character escaped. For example:</p>
-<pre class="prettyprint lang-py"><code>{"unicode black star": "★"}
+<p>Note that the default style is to include unicode characters, and render the response using a compact style with no unnecessary whitespace:</p>
+<pre><code>{"unicode black star":"★","value":999}
</code></pre>
<p>The client may additionally include an <code>'indent'</code> media type parameter, in which case the returned <code>JSON</code> will be indented. For example <code>Accept: application/json; indent=4</code>.</p>
-<pre class="prettyprint lang-py"><code>{
- "unicode black star": "★"
+<pre><code>{
+ "unicode black star": "★",
+ "value": 999
}
</code></pre>
-<p>Both the <code>JSONRenderer</code> and <code>UnicodeJSONRenderer</code> styles conform to <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>, and are syntactically valid JSON.</p>
+<p>The default JSON encoding style can be altered using the <code>UNICODE_JSON</code> and <code>COMPACT_JSON</code> settings keys.</p>
<p><strong>.media_type</strong>: <code>application/json</code></p>
<p><strong>.format</strong>: <code>'.json'</code></p>
<p><strong>.charset</strong>: <code>None</code></p>
@@ -312,26 +577,26 @@ def user_count_view(request, format=None):
<p>Renders the request data into <code>JSONP</code>. The <code>JSONP</code> media type provides a mechanism of allowing cross-domain AJAX requests, by wrapping a <code>JSON</code> response in a javascript callback.</p>
<p>The javascript callback function must be set by the client including a <code>callback</code> URL query parameter. For example <code>http://example.com/api/users?callback=jsonpCallback</code>. If the callback function is not explicitly set by the client it will default to <code>'callback'</code>.</p>
<hr />
-<p><strong>Warning</strong>: If you require cross-domain AJAX requests, you should almost certainly be using the more modern approach of <a href="http://www.w3.org/TR/cors/">CORS</a> as an alternative to <code>JSONP</code>. See the <a href="../topics/ajax-csrf-cors">CORS documentation</a> for more details.</p>
+<p><strong>Warning</strong>: If you require cross-domain AJAX requests, you should almost certainly be using the more modern approach of <a href="http://www.w3.org/TR/cors/">CORS</a> as an alternative to <code>JSONP</code>. See the <a href="../../topics/ajax-csrf-cors">CORS documentation</a> for more details.</p>
<p>The <code>jsonp</code> approach is essentially a browser hack, and is <a href="http://stackoverflow.com/questions/613962/is-jsonp-safe-to-use">only appropriate for globally readable API endpoints</a>, where <code>GET</code> requests are unauthenticated and do not require any user permissions.</p>
<hr />
<p><strong>.media_type</strong>: <code>application/javascript</code></p>
<p><strong>.format</strong>: <code>'.jsonp'</code></p>
<p><strong>.charset</strong>: <code>utf-8</code></p>
<h2 id="yamlrenderer">YAMLRenderer</h2>
-<p>Renders the request data into <code>YAML</code>. </p>
+<p>Renders the request data into <code>YAML</code>.</p>
<p>Requires the <code>pyyaml</code> package to be installed.</p>
<p>Note that non-ascii characters will be rendered using <code>\uXXXX</code> character escape. For example:</p>
-<pre class="prettyprint lang-py"><code>unicode black star: "\u2605"
+<pre><code>unicode black star: "\u2605"
</code></pre>
<p><strong>.media_type</strong>: <code>application/yaml</code></p>
<p><strong>.format</strong>: <code>'.yaml'</code></p>
<p><strong>.charset</strong>: <code>utf-8</code></p>
<h2 id="unicodeyamlrenderer">UnicodeYAMLRenderer</h2>
-<p>Renders the request data into <code>YAML</code>. </p>
+<p>Renders the request data into <code>YAML</code>.</p>
<p>Requires the <code>pyyaml</code> package to be installed.</p>
<p>Note that non-ascii characters will not be character escaped. For example:</p>
-<pre class="prettyprint lang-py"><code>unicode black star: ★
+<pre><code>unicode black star: ★
</code></pre>
<p><strong>.media_type</strong>: <code>application/yaml</code></p>
<p><strong>.format</strong>: <code>'.yaml'</code></p>
@@ -354,7 +619,7 @@ Unlike other renderers, the data passed to the <code>Response</code> does not ne
<li>The return result of calling <code>view.get_template_names()</code>.</li>
</ol>
<p>An example of a view that uses <code>TemplateHTMLRenderer</code>:</p>
-<pre class="prettyprint lang-py"><code>class UserDetail(generics.RetrieveAPIView):
+<pre><code>class UserDetail(generics.RetrieveAPIView):
"""
A view that returns a templated HTML representations of a given user.
"""
@@ -374,9 +639,9 @@ Unlike other renderers, the data passed to the <code>Response</code> does not ne
<h2 id="statichtmlrenderer">StaticHTMLRenderer</h2>
<p>A simple renderer that simply returns pre-rendered HTML. Unlike other renderers, the data passed to the response object should be a string representing the content to be returned.</p>
<p>An example of a view that uses <code>TemplateHTMLRenderer</code>:</p>
-<pre class="prettyprint lang-py"><code>@api_view(('GET',))
+<pre><code>@api_view(('GET',))
@renderer_classes((StaticHTMLRenderer,))
-def simple_html_view(request):
+def simple_html_view(request):
data = '&lt;html&gt;&lt;body&gt;&lt;h1&gt;Hello, world&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;'
return Response(data)
</code></pre>
@@ -400,12 +665,12 @@ def simple_html_view(request):
<p><strong>.template</strong>: <code>'rest_framework/api.html'</code></p>
<h4 id="customizing-browsableapirenderer">Customizing BrowsableAPIRenderer</h4>
<p>By default the response content will be rendered with the highest priority renderer apart from <code>BrowseableAPIRenderer</code>. If you need to customize this behavior, for example to use HTML as the default return format, but use JSON in the browsable API, you can do so by overriding the <code>get_default_renderer()</code> method. For example:</p>
-<pre class="prettyprint lang-py"><code>class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
+<pre><code>class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
def get_default_renderer(self, view):
return JSONRenderer()
</code></pre>
<h2 id="multipartrenderer">MultiPartRenderer</h2>
-<p>This renderer is used for rendering HTML multipart form data. <strong>It is not suitable as a response renderer</strong>, but is instead used for creating test requests, using REST framework's <a href="testing">test client and test request factory</a>.</p>
+<p>This renderer is used for rendering HTML multipart form data. <strong>It is not suitable as a response renderer</strong>, but is instead used for creating test requests, using REST framework's <a href="../testing">test client and test request factory</a>.</p>
<p><strong>.media_type</strong>: <code>multipart/form-data; boundary=BoUnDaRyStRiNg</code></p>
<p><strong>.format</strong>: <code>'.multipart'</code></p>
<p><strong>.charset</strong>: <code>utf-8</code></p>
@@ -424,7 +689,7 @@ def simple_html_view(request):
<p>By default this will include the following keys: <code>view</code>, <code>request</code>, <code>response</code>, <code>args</code>, <code>kwargs</code>.</p>
<h2 id="example">Example</h2>
<p>The following is an example plaintext renderer that will return a response with the <code>data</code> parameter as the content of the response.</p>
-<pre class="prettyprint lang-py"><code>from django.utils.encoding import smart_unicode
+<pre><code>from django.utils.encoding import smart_unicode
from rest_framework import renderers
@@ -437,7 +702,7 @@ class PlainTextRenderer(renderers.BaseRenderer):
</code></pre>
<h2 id="setting-the-character-set">Setting the character set</h2>
<p>By default renderer classes are assumed to be using the <code>UTF-8</code> encoding. To use a different encoding, set the <code>charset</code> attribute on the renderer.</p>
-<pre class="prettyprint lang-py"><code>class PlainTextRenderer(renderers.BaseRenderer):
+<pre><code>class PlainTextRenderer(renderers.BaseRenderer):
media_type = 'text/plain'
format = 'txt'
charset = 'iso-8859-1'
@@ -448,7 +713,7 @@ class PlainTextRenderer(renderers.BaseRenderer):
<p>Note that if a renderer class returns a unicode string, then the response content will be coerced into a bytestring by the <code>Response</code> class, with the <code>charset</code> attribute set on the renderer used to determine the encoding.</p>
<p>If the renderer returns a bytestring representing raw binary content, you should set a charset value of <code>None</code>, which will ensure the <code>Content-Type</code> header of the response will not have a <code>charset</code> value set.</p>
<p>In some cases you may also want to set the <code>render_style</code> attribute to <code>'binary'</code>. Doing so will also ensure that the browsable API will not attempt to display the binary content as a string.</p>
-<pre class="prettyprint lang-py"><code>class JPEGRenderer(renderers.BaseRenderer):
+<pre><code>class JPEGRenderer(renderers.BaseRenderer):
media_type = 'image/jpeg'
format = 'jpg'
charset = None
@@ -464,12 +729,12 @@ class PlainTextRenderer(renderers.BaseRenderer):
<li>Provide either flat or nested representations from the same endpoint, depending on the requested media type.</li>
<li>Serve both regular HTML webpages, and JSON based API responses from the same endpoints.</li>
<li>Specify multiple types of HTML representation for API clients to use.</li>
-<li>Underspecify a renderer's media type, such as using <code>media_type = 'image/*'</code>, and use the <code>Accept</code> header to vary the encoding of the response. </li>
+<li>Underspecify a renderer's media type, such as using <code>media_type = 'image/*'</code>, and use the <code>Accept</code> header to vary the encoding of the response.</li>
</ul>
<h2 id="varying-behaviour-by-media-type">Varying behaviour by media type</h2>
<p>In some cases you might want your view to use different serialization styles depending on the accepted media type. If you need to do this you can access <code>request.accepted_renderer</code> to determine the negotiated renderer that will be used for the response.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>@api_view(('GET',))
+<pre><code>@api_view(('GET',))
@renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def list_users(request):
"""
@@ -494,7 +759,7 @@ def list_users(request):
<p>In some cases you might want a renderer to serve a range of media types.
In this case you can underspecify the media types it should respond to, by using a <code>media_type</code> value such as <code>image/*</code>, or <code>*/*</code>.</p>
<p>If you underspecify the renderer's media type, you should make sure to specify the media type explicitly when you return the response, using the <code>content_type</code> attribute. For example:</p>
-<pre class="prettyprint lang-py"><code>return Response(data, content_type='image/png')
+<pre><code>return Response(data, content_type='image/png')
</code></pre>
<h2 id="designing-your-media-types">Designing your media types</h2>
<p>For the purposes of many Web APIs, simple <code>JSON</code> responses with hyperlinked relations may be sufficient. If you want to fully embrace RESTful design and <a href="http://timelessrepo.com/haters-gonna-hateoas">HATEOAS</a> you'll need to consider the design and usage of your media types in more detail.</p>
@@ -524,42 +789,52 @@ In this case you can underspecify the media types it should respond to, by using
<p><a href="https://github.com/vbabiy/djangorestframework-camel-case">djangorestframework-camel-case</a> provides camel case JSON renderers and parsers for REST framework. This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names. It is maintained by <a href="https://github.com/vbabiy">Vitaly Babiy</a>.</p>
<h2 id="pandas-csv-excel-png">Pandas (CSV, Excel, PNG)</h2>
<p><a href="https://github.com/wq/django-rest-pandas">Django REST Pandas</a> provides a serializer and renderers that support additional data processing and output via the <a href="http://pandas.pydata.org/">Pandas</a> DataFrame API. Django REST Pandas includes renderers for Pandas-style CSV files, Excel workbooks (both <code>.xls</code> and <code>.xlsx</code>), and a number of <a href="https://github.com/wq/django-rest-pandas#supported-formats">other formats</a>. It is maintained by <a href="https://github.com/sheppard">S. Andrew Sheppard</a> as part of the <a href="https://github.com/wq">wq Project</a>.</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/api-guide/requests.html b/api-guide/requests.html
deleted file mode 100644
index 50f40a53..00000000
--- a/api-guide/requests.html
+++ /dev/null
@@ -1,321 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Requests - 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/api-guide/requests"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Requests, Request parsing, Authentication, Browser enhancements, Standard HttpRequest attributes">
- <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="requests-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="../api-guide/responses">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../tutorial/6-viewsets-and-routers"><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="#requests">Requests</a></li>
-<li class="main"><a href="#request-parsing">Request parsing</a></li>
-<li><a href="#data">.DATA</a></li>
-<li><a href="#files">.FILES</a></li>
-<li><a href="#query_params">.QUERY_PARAMS</a></li>
-<li><a href="#parsers">.parsers</a></li>
-<li class="main"><a href="#authentication">Authentication</a></li>
-<li><a href="#user">.user</a></li>
-<li><a href="#auth">.auth</a></li>
-<li><a href="#authenticators">.authenticators</a></li>
-<li class="main"><a href="#browser-enhancements">Browser enhancements</a></li>
-<li><a href="#method">.method</a></li>
-<li><a href="#content_type">.content_type</a></li>
-<li><a href="#stream">.stream</a></li>
-<li class="main"><a href="#standard-httprequest-attributes">Standard HttpRequest attributes</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/request.py"><span class="label label-info">request.py</span></a></p>
-<h1 id="requests">Requests</h1>
-<blockquote>
-<p>If you're doing REST-based web service stuff ... you should ignore request.POST.</p>
-<p>&mdash; Malcom Tredinnick, <a href="https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion">Django developers group</a></p>
-</blockquote>
-<p>REST framework's <code>Request</code> class extends the standard <code>HttpRequest</code>, adding support for REST framework's flexible request parsing and request authentication.</p>
-<hr />
-<h1 id="request-parsing">Request parsing</h1>
-<p>REST framework's Request objects provide flexible request parsing that allows you to treat requests with JSON data or other media types in the same way that you would normally deal with form data.</p>
-<h2 id="data">.DATA</h2>
-<p><code>request.DATA</code> returns the parsed content of the request body. This is similar to the standard <code>request.POST</code> attribute except that:</p>
-<ul>
-<li>It supports parsing the content of HTTP methods other than <code>POST</code>, meaning that you can access the content of <code>PUT</code> and <code>PATCH</code> requests.</li>
-<li>It supports REST framework's flexible request parsing, rather than just supporting form data. For example you can handle incoming JSON data in the same way that you handle incoming form data.</li>
-</ul>
-<p>For more details see the <a href="parsers">parsers documentation</a>.</p>
-<h2 id="files">.FILES</h2>
-<p><code>request.FILES</code> returns any uploaded files that may be present in the content of the request body. This is the same as the standard <code>HttpRequest</code> behavior, except that the same flexible request parsing is used for <code>request.DATA</code>.</p>
-<p>For more details see the <a href="parsers">parsers documentation</a>.</p>
-<h2 id="query_params">.QUERY_PARAMS</h2>
-<p><code>request.QUERY_PARAMS</code> is a more correctly named synonym for <code>request.GET</code>.</p>
-<p>For clarity inside your code, we recommend using <code>request.QUERY_PARAMS</code> instead of the usual <code>request.GET</code>, as <em>any</em> HTTP method type may include query parameters.</p>
-<h2 id="parsers">.parsers</h2>
-<p>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically set to a list of <code>Parser</code> instances, based on the <code>parser_classes</code> set on the view or based on the <code>DEFAULT_PARSER_CLASSES</code> setting.</p>
-<p>You won't typically need to access this property.</p>
-<hr />
-<p><strong>Note:</strong> If a client sends malformed content, then accessing <code>request.DATA</code> or <code>request.FILES</code> may raise a <code>ParseError</code>. By default REST framework's <code>APIView</code> class or <code>@api_view</code> decorator will catch the error and return a <code>400 Bad Request</code> response.</p>
-<p>If a client sends a request with a content-type that cannot be parsed then a <code>UnsupportedMediaType</code> exception will be raised, which by default will be caught and return a <code>415 Unsupported Media Type</code> response.</p>
-<hr />
-<h1 id="authentication">Authentication</h1>
-<p>REST framework provides flexible, per-request authentication, that gives you the ability to:</p>
-<ul>
-<li>Use different authentication policies for different parts of your API.</li>
-<li>Support the use of multiple authentication policies.</li>
-<li>Provide both user and token information associated with the incoming request.</li>
-</ul>
-<h2 id="user">.user</h2>
-<p><code>request.user</code> typically returns an instance of <code>django.contrib.auth.models.User</code>, although the behavior depends on the authentication policy being used.</p>
-<p>If the request is unauthenticated the default value of <code>request.user</code> is an instance of <code>django.contrib.auth.models.AnonymousUser</code>.</p>
-<p>For more details see the <a href="authentication">authentication documentation</a>.</p>
-<h2 id="auth">.auth</h2>
-<p><code>request.auth</code> returns any additional authentication context. The exact behavior of <code>request.auth</code> depends on the authentication policy being used, but it may typically be an instance of the token that the request was authenticated against.</p>
-<p>If the request is unauthenticated, or if no additional context is present, the default value of <code>request.auth</code> is <code>None</code>.</p>
-<p>For more details see the <a href="authentication">authentication documentation</a>.</p>
-<h2 id="authenticators">.authenticators</h2>
-<p>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically set to a list of <code>Authentication</code> instances, based on the <code>authentication_classes</code> set on the view or based on the <code>DEFAULT_AUTHENTICATORS</code> setting.</p>
-<p>You won't typically need to access this property.</p>
-<hr />
-<h1 id="browser-enhancements">Browser enhancements</h1>
-<p>REST framework supports a few browser enhancements such as browser-based <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> forms.</p>
-<h2 id="method">.method</h2>
-<p><code>request.method</code> returns the <strong>uppercased</strong> string representation of the request's HTTP method.</p>
-<p>Browser-based <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> forms are transparently supported.</p>
-<p>For more information see the <a href="../topics/browser-enhancements">browser enhancements documentation</a>. </p>
-<h2 id="content_type">.content_type</h2>
-<p><code>request.content_type</code>, returns a string object representing the media type of the HTTP request's body, or an empty string if no media type was provided.</p>
-<p>You won't typically need to directly access the request's content type, as you'll normally rely on REST framework's default request parsing behavior.</p>
-<p>If you do need to access the content type of the request you should use the <code>.content_type</code> property in preference to using <code>request.META.get('HTTP_CONTENT_TYPE')</code>, as it provides transparent support for browser-based non-form content.</p>
-<p>For more information see the <a href="../topics/browser-enhancements">browser enhancements documentation</a>. </p>
-<h2 id="stream">.stream</h2>
-<p><code>request.stream</code> returns a stream representing the content of the request body.</p>
-<p>You won't typically need to directly access the request's content, as you'll normally rely on REST framework's default request parsing behavior.</p>
-<p>If you do need to access the raw content directly, you should use the <code>.stream</code> property in preference to using <code>request.content</code>, as it provides transparent support for browser-based non-form content.</p>
-<p>For more information see the <a href="../topics/browser-enhancements">browser enhancements documentation</a>. </p>
-<hr />
-<h1 id="standard-httprequest-attributes">Standard HttpRequest attributes</h1>
-<p>As REST framework's <code>Request</code> extends Django's <code>HttpRequest</code>, all the other standard attributes and methods are also available. For example the <code>request.META</code> and <code>request.session</code> dictionaries are available as normal.</p>
-<p>Note that due to implementation reasons the <code>Request</code> class does not inherit from <code>HttpRequest</code> class, but instead extends the class using composition.</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/api-guide/requests/index.html b/api-guide/requests/index.html
new file mode 100644
index 00000000..1649b0ba
--- /dev/null
+++ b/api-guide/requests/index.html
@@ -0,0 +1,578 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Requests - 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/api-guide/requests/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Requests">
+ <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="../responses">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../../tutorial/6-viewsets-and-routers">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li class="active" >
+ <a href=".">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#requests">Requests</a>
+ </li>
+
+
+
+
+
+ <li class="main">
+ <a href="#request-parsing">Request parsing</a>
+ </li>
+
+
+ <li>
+ <a href="#data">.DATA</a>
+ </li>
+
+ <li>
+ <a href="#files">.FILES</a>
+ </li>
+
+ <li>
+ <a href="#query_params">.QUERY_PARAMS</a>
+ </li>
+
+ <li>
+ <a href="#parsers">.parsers</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#content-negotiation">Content negotiation</a>
+ </li>
+
+
+ <li>
+ <a href="#accepted_renderer">.accepted_renderer</a>
+ </li>
+
+ <li>
+ <a href="#accepted_media_type">.accepted_media_type</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#authentication">Authentication</a>
+ </li>
+
+
+ <li>
+ <a href="#user">.user</a>
+ </li>
+
+ <li>
+ <a href="#auth">.auth</a>
+ </li>
+
+ <li>
+ <a href="#authenticators">.authenticators</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#browser-enhancements">Browser enhancements</a>
+ </li>
+
+
+ <li>
+ <a href="#method">.method</a>
+ </li>
+
+ <li>
+ <a href="#content_type">.content_type</a>
+ </li>
+
+ <li>
+ <a href="#stream">.stream</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#standard-httprequest-attributes">Standard HttpRequest attributes</a>
+ </li>
+
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/request.py">
+ <span class="label label-info">request.py</span>
+ </a>
+
+
+
+ <h1 id="requests">Requests</h1>
+<blockquote>
+<p>If you're doing REST-based web service stuff ... you should ignore request.POST.</p>
+<p>&mdash; Malcom Tredinnick, <a href="https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion">Django developers group</a></p>
+</blockquote>
+<p>REST framework's <code>Request</code> class extends the standard <code>HttpRequest</code>, adding support for REST framework's flexible request parsing and request authentication.</p>
+<hr />
+<h1 id="request-parsing">Request parsing</h1>
+<p>REST framework's Request objects provide flexible request parsing that allows you to treat requests with JSON data or other media types in the same way that you would normally deal with form data.</p>
+<h2 id="data">.DATA</h2>
+<p><code>request.DATA</code> returns the parsed content of the request body. This is similar to the standard <code>request.POST</code> attribute except that:</p>
+<ul>
+<li>It supports parsing the content of HTTP methods other than <code>POST</code>, meaning that you can access the content of <code>PUT</code> and <code>PATCH</code> requests.</li>
+<li>It supports REST framework's flexible request parsing, rather than just supporting form data. For example you can handle incoming JSON data in the same way that you handle incoming form data.</li>
+</ul>
+<p>For more details see the <a href="../parsers">parsers documentation</a>.</p>
+<h2 id="files">.FILES</h2>
+<p><code>request.FILES</code> returns any uploaded files that may be present in the content of the request body. This is the same as the standard <code>HttpRequest</code> behavior, except that the same flexible request parsing is used for <code>request.DATA</code>.</p>
+<p>For more details see the <a href="../parsers">parsers documentation</a>.</p>
+<h2 id="query_params">.QUERY_PARAMS</h2>
+<p><code>request.QUERY_PARAMS</code> is a more correctly named synonym for <code>request.GET</code>.</p>
+<p>For clarity inside your code, we recommend using <code>request.QUERY_PARAMS</code> instead of the usual <code>request.GET</code>, as <em>any</em> HTTP method type may include query parameters.</p>
+<h2 id="parsers">.parsers</h2>
+<p>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically set to a list of <code>Parser</code> instances, based on the <code>parser_classes</code> set on the view or based on the <code>DEFAULT_PARSER_CLASSES</code> setting.</p>
+<p>You won't typically need to access this property.</p>
+<hr />
+<p><strong>Note:</strong> If a client sends malformed content, then accessing <code>request.DATA</code> or <code>request.FILES</code> may raise a <code>ParseError</code>. By default REST framework's <code>APIView</code> class or <code>@api_view</code> decorator will catch the error and return a <code>400 Bad Request</code> response.</p>
+<p>If a client sends a request with a content-type that cannot be parsed then a <code>UnsupportedMediaType</code> exception will be raised, which by default will be caught and return a <code>415 Unsupported Media Type</code> response.</p>
+<hr />
+<h1 id="content-negotiation">Content negotiation</h1>
+<p>The request exposes some properties that allow you to determine the result of the content negotiation stage. This allows you to implement behaviour such as selecting a different serialisation schemes for different media types.</p>
+<h2 id="accepted_renderer">.accepted_renderer</h2>
+<p>The renderer instance what was selected by the content negotiation stage.</p>
+<h2 id="accepted_media_type">.accepted_media_type</h2>
+<p>A string representing the media type that was accepted by the content negotiation stage.</p>
+<hr />
+<h1 id="authentication">Authentication</h1>
+<p>REST framework provides flexible, per-request authentication, that gives you the ability to:</p>
+<ul>
+<li>Use different authentication policies for different parts of your API.</li>
+<li>Support the use of multiple authentication policies.</li>
+<li>Provide both user and token information associated with the incoming request.</li>
+</ul>
+<h2 id="user">.user</h2>
+<p><code>request.user</code> typically returns an instance of <code>django.contrib.auth.models.User</code>, although the behavior depends on the authentication policy being used.</p>
+<p>If the request is unauthenticated the default value of <code>request.user</code> is an instance of <code>django.contrib.auth.models.AnonymousUser</code>.</p>
+<p>For more details see the <a href="../authentication">authentication documentation</a>.</p>
+<h2 id="auth">.auth</h2>
+<p><code>request.auth</code> returns any additional authentication context. The exact behavior of <code>request.auth</code> depends on the authentication policy being used, but it may typically be an instance of the token that the request was authenticated against.</p>
+<p>If the request is unauthenticated, or if no additional context is present, the default value of <code>request.auth</code> is <code>None</code>.</p>
+<p>For more details see the <a href="../authentication">authentication documentation</a>.</p>
+<h2 id="authenticators">.authenticators</h2>
+<p>The <code>APIView</code> class or <code>@api_view</code> decorator will ensure that this property is automatically set to a list of <code>Authentication</code> instances, based on the <code>authentication_classes</code> set on the view or based on the <code>DEFAULT_AUTHENTICATORS</code> setting.</p>
+<p>You won't typically need to access this property.</p>
+<hr />
+<h1 id="browser-enhancements">Browser enhancements</h1>
+<p>REST framework supports a few browser enhancements such as browser-based <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> forms.</p>
+<h2 id="method">.method</h2>
+<p><code>request.method</code> returns the <strong>uppercased</strong> string representation of the request's HTTP method.</p>
+<p>Browser-based <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> forms are transparently supported.</p>
+<p>For more information see the <a href="../../topics/browser-enhancements">browser enhancements documentation</a>.</p>
+<h2 id="content_type">.content_type</h2>
+<p><code>request.content_type</code>, returns a string object representing the media type of the HTTP request's body, or an empty string if no media type was provided.</p>
+<p>You won't typically need to directly access the request's content type, as you'll normally rely on REST framework's default request parsing behavior.</p>
+<p>If you do need to access the content type of the request you should use the <code>.content_type</code> property in preference to using <code>request.META.get('HTTP_CONTENT_TYPE')</code>, as it provides transparent support for browser-based non-form content.</p>
+<p>For more information see the <a href="../../topics/browser-enhancements">browser enhancements documentation</a>.</p>
+<h2 id="stream">.stream</h2>
+<p><code>request.stream</code> returns a stream representing the content of the request body.</p>
+<p>You won't typically need to directly access the request's content, as you'll normally rely on REST framework's default request parsing behavior.</p>
+<p>If you do need to access the raw content directly, you should use the <code>.stream</code> property in preference to using <code>request.content</code>, as it provides transparent support for browser-based non-form content.</p>
+<p>For more information see the <a href="../../topics/browser-enhancements">browser enhancements documentation</a>.</p>
+<hr />
+<h1 id="standard-httprequest-attributes">Standard HttpRequest attributes</h1>
+<p>As REST framework's <code>Request</code> extends Django's <code>HttpRequest</code>, all the other standard attributes and methods are also available. For example the <code>request.META</code> and <code>request.session</code> dictionaries are available as normal.</p>
+<p>Note that due to implementation reasons the <code>Request</code> class does not inherit from <code>HttpRequest</code> class, but instead extends the class using composition.</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/api-guide/responses.html b/api-guide/responses.html
deleted file mode 100644
index 5bc21986..00000000
--- a/api-guide/responses.html
+++ /dev/null
@@ -1,304 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Responses - 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/api-guide/responses"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Responses, Creating responses, Attributes, Standard HttpResponse attributes">
- <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="responses-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="../api-guide/views">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/requests"><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="#responses">Responses</a></li>
-<li class="main"><a href="#creating-responses">Creating responses</a></li>
-<li><a href="#response()">Response()</a></li>
-<li class="main"><a href="#attributes">Attributes</a></li>
-<li><a href="#data">.data</a></li>
-<li><a href="#status_code">.status_code</a></li>
-<li><a href="#content">.content</a></li>
-<li><a href="#template_name">.template_name</a></li>
-<li><a href="#accepted_renderer">.accepted_renderer</a></li>
-<li><a href="#accepted_media_type">.accepted_media_type</a></li>
-<li><a href="#renderer_context">.renderer_context</a></li>
-<li class="main"><a href="#standard-httpresponse-attributes">Standard HttpResponse attributes</a></li>
-<li><a href="#render()">.render()</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/response.py"><span class="label label-info">response.py</span></a></p>
-<h1 id="responses">Responses</h1>
-<blockquote>
-<p>Unlike basic HttpResponse objects, TemplateResponse objects retain the details of the context that was provided by the view to compute the response. The final output of the response is not computed until it is needed, later in the response process.</p>
-<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/template-response/">Django documentation</a></p>
-</blockquote>
-<p>REST framework supports HTTP content negotiation by providing a <code>Response</code> class which allows you to return content that can be rendered into multiple content types, depending on the client request.</p>
-<p>The <code>Response</code> class subclasses Django's <code>SimpleTemplateResponse</code>. <code>Response</code> objects are initialised with data, which should consist of native Python primitives. REST framework then uses standard HTTP content negotiation to determine how it should render the final response content.</p>
-<p>There's no requirement for you to use the <code>Response</code> class, you can also return regular <code>HttpResponse</code> or <code>StreamingHttpResponse</code> objects from your views if required. Using the <code>Response</code> class simply provides a nicer interface for returning content-negotiated Web API responses, that can be rendered to multiple formats.</p>
-<p>Unless you want to heavily customize REST framework for some reason, you should always use an <code>APIView</code> class or <code>@api_view</code> function for views that return <code>Response</code> objects. Doing so ensures that the view can perform content negotiation and select the appropriate renderer for the response, before it is returned from the view.</p>
-<hr />
-<h1 id="creating-responses">Creating responses</h1>
-<h2 id="response">Response()</h2>
-<p><strong>Signature:</strong> <code>Response(data, status=None, template_name=None, headers=None, content_type=None)</code></p>
-<p>Unlike regular <code>HttpResponse</code> objects, you do not instantiate <code>Response</code> objects with rendered content. Instead you pass in unrendered data, which may consist of any Python primitives.</p>
-<p>The renderers used by the <code>Response</code> class cannot natively handle complex datatypes such as Django model instances, so you need to serialize the data into primitive datatypes before creating the <code>Response</code> object.</p>
-<p>You can use REST framework's <code>Serializer</code> classes to perform this data serialization, or use your own custom serialization.</p>
-<p>Arguments:</p>
-<ul>
-<li><code>data</code>: The serialized data for the response.</li>
-<li><code>status</code>: A status code for the response. Defaults to 200. See also <a href="status-codes">status codes</a>.</li>
-<li><code>template_name</code>: A template name to use if <code>HTMLRenderer</code> is selected.</li>
-<li><code>headers</code>: A dictionary of HTTP headers to use in the response.</li>
-<li><code>content_type</code>: The content type of the response. Typically, this will be set automatically by the renderer as determined by content negotiation, but there may be some cases where you need to specify the content type explicitly.</li>
-</ul>
-<hr />
-<h1 id="attributes">Attributes</h1>
-<h2 id="data">.data</h2>
-<p>The unrendered content of a <code>Request</code> object.</p>
-<h2 id="status_code">.status_code</h2>
-<p>The numeric status code of the HTTP response.</p>
-<h2 id="content">.content</h2>
-<p>The rendered content of the response. The <code>.render()</code> method must have been called before <code>.content</code> can be accessed.</p>
-<h2 id="template_name">.template_name</h2>
-<p>The <code>template_name</code>, if supplied. Only required if <code>HTMLRenderer</code> or some other custom template renderer is the accepted renderer for the response.</p>
-<h2 id="accepted_renderer">.accepted_renderer</h2>
-<p>The renderer instance that will be used to render the response.</p>
-<p>Set automatically by the <code>APIView</code> or <code>@api_view</code> immediately before the response is returned from the view.</p>
-<h2 id="accepted_media_type">.accepted_media_type</h2>
-<p>The media type that was selected by the content negotiation stage.</p>
-<p>Set automatically by the <code>APIView</code> or <code>@api_view</code> immediately before the response is returned from the view.</p>
-<h2 id="renderer_context">.renderer_context</h2>
-<p>A dictionary of additional context information that will be passed to the renderer's <code>.render()</code> method.</p>
-<p>Set automatically by the <code>APIView</code> or <code>@api_view</code> immediately before the response is returned from the view.</p>
-<hr />
-<h1 id="standard-httpresponse-attributes">Standard HttpResponse attributes</h1>
-<p>The <code>Response</code> class extends <code>SimpleTemplateResponse</code>, and all the usual attributes and methods are also available on the response. For example you can set headers on the response in the standard way:</p>
-<pre class="prettyprint lang-py"><code>response = Response()
-response['Cache-Control'] = 'no-cache'
-</code></pre>
-<h2 id="render">.render()</h2>
-<p><strong>Signature:</strong> <code>.render()</code></p>
-<p>As with any other <code>TemplateResponse</code>, this method is called to render the serialized data of the response into the final response content. When <code>.render()</code> is called, the response content will be set to the result of calling the <code>.render(data, accepted_media_type, renderer_context)</code> method on the <code>accepted_renderer</code> instance.</p>
-<p>You won't typically need to call <code>.render()</code> yourself, as it's handled by Django's standard response cycle.</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/api-guide/responses/index.html b/api-guide/responses/index.html
new file mode 100644
index 00000000..a6f94666
--- /dev/null
+++ b/api-guide/responses/index.html
@@ -0,0 +1,528 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Responses - 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/api-guide/responses/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Responses">
+ <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="../views">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../requests">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#responses">Responses</a>
+ </li>
+
+
+
+
+
+ <li class="main">
+ <a href="#creating-responses">Creating responses</a>
+ </li>
+
+
+ <li>
+ <a href="#response">Response()</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#attributes">Attributes</a>
+ </li>
+
+
+ <li>
+ <a href="#data">.data</a>
+ </li>
+
+ <li>
+ <a href="#status_code">.status_code</a>
+ </li>
+
+ <li>
+ <a href="#content">.content</a>
+ </li>
+
+ <li>
+ <a href="#template_name">.template_name</a>
+ </li>
+
+ <li>
+ <a href="#accepted_renderer">.accepted_renderer</a>
+ </li>
+
+ <li>
+ <a href="#accepted_media_type">.accepted_media_type</a>
+ </li>
+
+ <li>
+ <a href="#renderer_context">.renderer_context</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#standard-httpresponse-attributes">Standard HttpResponse attributes</a>
+ </li>
+
+
+ <li>
+ <a href="#render">.render()</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/response.py">
+ <span class="label label-info">response.py</span>
+ </a>
+
+
+
+ <h1 id="responses">Responses</h1>
+<blockquote>
+<p>Unlike basic HttpResponse objects, TemplateResponse objects retain the details of the context that was provided by the view to compute the response. The final output of the response is not computed until it is needed, later in the response process.</p>
+<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/template-response/">Django documentation</a></p>
+</blockquote>
+<p>REST framework supports HTTP content negotiation by providing a <code>Response</code> class which allows you to return content that can be rendered into multiple content types, depending on the client request.</p>
+<p>The <code>Response</code> class subclasses Django's <code>SimpleTemplateResponse</code>. <code>Response</code> objects are initialised with data, which should consist of native Python primitives. REST framework then uses standard HTTP content negotiation to determine how it should render the final response content.</p>
+<p>There's no requirement for you to use the <code>Response</code> class, you can also return regular <code>HttpResponse</code> or <code>StreamingHttpResponse</code> objects from your views if required. Using the <code>Response</code> class simply provides a nicer interface for returning content-negotiated Web API responses, that can be rendered to multiple formats.</p>
+<p>Unless you want to heavily customize REST framework for some reason, you should always use an <code>APIView</code> class or <code>@api_view</code> function for views that return <code>Response</code> objects. Doing so ensures that the view can perform content negotiation and select the appropriate renderer for the response, before it is returned from the view.</p>
+<hr />
+<h1 id="creating-responses">Creating responses</h1>
+<h2 id="response">Response()</h2>
+<p><strong>Signature:</strong> <code>Response(data, status=None, template_name=None, headers=None, content_type=None)</code></p>
+<p>Unlike regular <code>HttpResponse</code> objects, you do not instantiate <code>Response</code> objects with rendered content. Instead you pass in unrendered data, which may consist of any Python primitives.</p>
+<p>The renderers used by the <code>Response</code> class cannot natively handle complex datatypes such as Django model instances, so you need to serialize the data into primitive datatypes before creating the <code>Response</code> object.</p>
+<p>You can use REST framework's <code>Serializer</code> classes to perform this data serialization, or use your own custom serialization.</p>
+<p>Arguments:</p>
+<ul>
+<li><code>data</code>: The serialized data for the response.</li>
+<li><code>status</code>: A status code for the response. Defaults to 200. See also <a href="../status-codes">status codes</a>.</li>
+<li><code>template_name</code>: A template name to use if <code>HTMLRenderer</code> is selected.</li>
+<li><code>headers</code>: A dictionary of HTTP headers to use in the response.</li>
+<li><code>content_type</code>: The content type of the response. Typically, this will be set automatically by the renderer as determined by content negotiation, but there may be some cases where you need to specify the content type explicitly.</li>
+</ul>
+<hr />
+<h1 id="attributes">Attributes</h1>
+<h2 id="data">.data</h2>
+<p>The unrendered content of a <code>Request</code> object.</p>
+<h2 id="status_code">.status_code</h2>
+<p>The numeric status code of the HTTP response.</p>
+<h2 id="content">.content</h2>
+<p>The rendered content of the response. The <code>.render()</code> method must have been called before <code>.content</code> can be accessed.</p>
+<h2 id="template_name">.template_name</h2>
+<p>The <code>template_name</code>, if supplied. Only required if <code>HTMLRenderer</code> or some other custom template renderer is the accepted renderer for the response.</p>
+<h2 id="accepted_renderer">.accepted_renderer</h2>
+<p>The renderer instance that will be used to render the response.</p>
+<p>Set automatically by the <code>APIView</code> or <code>@api_view</code> immediately before the response is returned from the view.</p>
+<h2 id="accepted_media_type">.accepted_media_type</h2>
+<p>The media type that was selected by the content negotiation stage.</p>
+<p>Set automatically by the <code>APIView</code> or <code>@api_view</code> immediately before the response is returned from the view.</p>
+<h2 id="renderer_context">.renderer_context</h2>
+<p>A dictionary of additional context information that will be passed to the renderer's <code>.render()</code> method.</p>
+<p>Set automatically by the <code>APIView</code> or <code>@api_view</code> immediately before the response is returned from the view.</p>
+<hr />
+<h1 id="standard-httpresponse-attributes">Standard HttpResponse attributes</h1>
+<p>The <code>Response</code> class extends <code>SimpleTemplateResponse</code>, and all the usual attributes and methods are also available on the response. For example you can set headers on the response in the standard way:</p>
+<pre><code>response = Response()
+response['Cache-Control'] = 'no-cache'
+</code></pre>
+<h2 id="render">.render()</h2>
+<p><strong>Signature:</strong> <code>.render()</code></p>
+<p>As with any other <code>TemplateResponse</code>, this method is called to render the serialized data of the response into the final response content. When <code>.render()</code> is called, the response content will be set to the result of calling the <code>.render(data, accepted_media_type, renderer_context)</code> method on the <code>accepted_renderer</code> instance.</p>
+<p>You won't typically need to call <code>.render()</code> yourself, as it's handled by Django's standard response cycle.</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/api-guide/reverse.html b/api-guide/reverse.html
deleted file mode 100644
index 48c8b3c5..00000000
--- a/api-guide/reverse.html
+++ /dev/null
@@ -1,279 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Returning URLs - 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/api-guide/reverse"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Returning URLs">
- <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="reverse-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="../api-guide/exceptions">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/format-suffixes"><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="#returning-urls">Returning URLs</a></li>
-<li><a href="#reverse">reverse</a></li>
-<li><a href="#reverse_lazy">reverse_lazy</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/reverse.py"><span class="label label-info">reverse.py</span></a></p>
-<h1 id="returning-urls">Returning URLs</h1>
-<blockquote>
-<p>The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components.</p>
-<p>&mdash; Roy Fielding, <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5">Architectural Styles and the Design of Network-based Software Architectures</a></p>
-</blockquote>
-<p>As a rule, it's probably better practice to return absolute URIs from your Web APIs, such as <code>http://example.com/foobar</code>, rather than returning relative URIs, such as <code>/foobar</code>.</p>
-<p>The advantages of doing so are:</p>
-<ul>
-<li>It's more explicit.</li>
-<li>It leaves less work for your API clients.</li>
-<li>There's no ambiguity about the meaning of the string when it's found in representations such as JSON that do not have a native URI type.</li>
-<li>It makes it easy to do things like markup HTML representations with hyperlinks.</li>
-</ul>
-<p>REST framework provides two utility functions to make it more simple to return absolute URIs from your Web API.</p>
-<p>There's no requirement for you to use them, but if you do then the self-describing API will be able to automatically hyperlink its output for you, which makes browsing the API much easier.</p>
-<h2 id="reverse">reverse</h2>
-<p><strong>Signature:</strong> <code>reverse(viewname, *args, **kwargs)</code></p>
-<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse"><code>django.core.urlresolvers.reverse</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
-<p>You should <strong>include the request as a keyword argument</strong> to the function, for example:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.reverse import reverse
-from rest_framework.views import APIView
-from django.utils.timezone import now
-
-class APIRootView(APIView):
- def get(self, request):
- year = now().year
- data = {
- ...
- 'year-summary-url': reverse('year-summary', args=[year], request=request)
- }
- return Response(data)
-</code></pre>
-<h2 id="reverse_lazy">reverse_lazy</h2>
-<p><strong>Signature:</strong> <code>reverse_lazy(viewname, *args, **kwargs)</code></p>
-<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy"><code>django.core.urlresolvers.reverse_lazy</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
-<p>As with the <code>reverse</code> function, you should <strong>include the request as a keyword argument</strong> to the function, for example:</p>
-<pre class="prettyprint lang-py"><code>api_root = reverse_lazy('api-root', request=request)
-</code></pre>
- </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/api-guide/reverse/index.html b/api-guide/reverse/index.html
new file mode 100644
index 00000000..2d50b9d8
--- /dev/null
+++ b/api-guide/reverse/index.html
@@ -0,0 +1,461 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Returning URLs - 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/api-guide/reverse/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Returning URLs">
+ <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="../exceptions">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../format-suffixes">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#returning-urls">Returning URLs</a>
+ </li>
+
+
+ <li>
+ <a href="#reverse">reverse</a>
+ </li>
+
+ <li>
+ <a href="#reverse_lazy">reverse_lazy</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/reverse.py">
+ <span class="label label-info">reverse.py</span>
+ </a>
+
+
+
+ <h1 id="returning-urls">Returning URLs</h1>
+<blockquote>
+<p>The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components.</p>
+<p>&mdash; Roy Fielding, <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5">Architectural Styles and the Design of Network-based Software Architectures</a></p>
+</blockquote>
+<p>As a rule, it's probably better practice to return absolute URIs from your Web APIs, such as <code>http://example.com/foobar</code>, rather than returning relative URIs, such as <code>/foobar</code>.</p>
+<p>The advantages of doing so are:</p>
+<ul>
+<li>It's more explicit.</li>
+<li>It leaves less work for your API clients.</li>
+<li>There's no ambiguity about the meaning of the string when it's found in representations such as JSON that do not have a native URI type.</li>
+<li>It makes it easy to do things like markup HTML representations with hyperlinks.</li>
+</ul>
+<p>REST framework provides two utility functions to make it more simple to return absolute URIs from your Web API.</p>
+<p>There's no requirement for you to use them, but if you do then the self-describing API will be able to automatically hyperlink its output for you, which makes browsing the API much easier.</p>
+<h2 id="reverse">reverse</h2>
+<p><strong>Signature:</strong> <code>reverse(viewname, *args, **kwargs)</code></p>
+<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse"><code>django.core.urlresolvers.reverse</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
+<p>You should <strong>include the request as a keyword argument</strong> to the function, for example:</p>
+<pre><code>from rest_framework.reverse import reverse
+from rest_framework.views import APIView
+from django.utils.timezone import now
+
+class APIRootView(APIView):
+ def get(self, request):
+ year = now().year
+ data = {
+ ...
+ 'year-summary-url': reverse('year-summary', args=[year], request=request)
+ }
+ return Response(data)
+</code></pre>
+<h2 id="reverse_lazy">reverse_lazy</h2>
+<p><strong>Signature:</strong> <code>reverse_lazy(viewname, *args, **kwargs)</code></p>
+<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy"><code>django.core.urlresolvers.reverse_lazy</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
+<p>As with the <code>reverse</code> function, you should <strong>include the request as a keyword argument</strong> to the function, for example:</p>
+<pre><code>api_root = reverse_lazy('api-root', request=request)
+</code></pre>
+
+ </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/api-guide/routers.html b/api-guide/routers/index.html
index a578fcfc..18ad04d5 100644
--- a/api-guide/routers.html
+++ b/api-guide/routers/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>Routers - 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/api-guide/routers"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Routers, API Guide, Custom Routers, 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="routers-page">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Routers - 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/api-guide/routers/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Routers">
+ <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="../api-guide/parsers">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/viewsets"><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="../parsers">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../viewsets">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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,31 +335,96 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#routers">Routers</a></li>
-<li><a href="#usage">Usage</a></li>
-<li class="main"><a href="#api-guide">API Guide</a></li>
-<li><a href="#simplerouter">SimpleRouter</a></li>
-<li><a href="#defaultrouter">DefaultRouter</a></li>
-<li class="main"><a href="#custom-routers">Custom Routers</a></li>
-<li><a href="#customizing-dynamic-routes">Customizing dynamic routes</a></li>
-<li><a href="#example">Example</a></li>
-<li><a href="#advanced-custom-routers">Advanced custom routers</a></li>
-<li class="main"><a href="#third-party-packages">Third Party Packages</a></li>
-<li><a href="#drf-nested-routers">DRF Nested Routers</a></li>
-<li><a href="#wqdb">wq.db</a></li>
-<li><a href="#drf-extensions">DRF-extensions</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#routers">Routers</a>
+ </li>
+
+
+ <li>
+ <a href="#usage">Usage</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-guide">API Guide</a>
+ </li>
+
+
+ <li>
+ <a href="#simplerouter">SimpleRouter</a>
+ </li>
+
+ <li>
+ <a href="#defaultrouter">DefaultRouter</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-routers">Custom Routers</a>
+ </li>
+
+
+ <li>
+ <a href="#customizing-dynamic-routes">Customizing dynamic routes</a>
+ </li>
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+ <li>
+ <a href="#advanced-custom-routers">Advanced custom routers</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third Party Packages</a>
+ </li>
+
+
+ <li>
+ <a href="#drf-nested-routers">DRF Nested Routers</a>
+ </li>
+
+ <li>
+ <a href="#wqdb">wq.db</a>
+ </li>
+
+ <li>
+ <a href="#drf-extensions">DRF-extensions</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/routers.py"><span class="label label-info">routers.py</span></a></p>
-<h1 id="routers">Routers</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/routers.py">
+ <span class="label label-info">routers.py</span>
+ </a>
+
+
+
+ <h1 id="routers">Routers</h1>
<blockquote>
<p>Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index... a resourceful route declares them in a single line of code.</p>
<p>&mdash; <a href="http://guides.rubyonrails.org/routing.html">Ruby on Rails Documentation</a></p>
@@ -219,7 +433,7 @@ a.fusion-poweredby {
<p>REST framework adds support for automatic URL routing to Django, and provides you with a simple, quick and consistent way of wiring your view logic to a set of URLs.</p>
<h2 id="usage">Usage</h2>
<p>Here's an example of a simple URL conf, that uses <code>SimpleRouter</code>.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import routers
+<pre><code>from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
@@ -245,14 +459,14 @@ urlpatterns = router.urls
<hr />
<p><strong>Note</strong>: The <code>base_name</code> argument is used to specify the initial part of the view name pattern. In the example above, that's the <code>user</code> or <code>account</code> part.</p>
<p>Typically you won't <em>need</em> to specify the <code>base-name</code> argument, but if you have a viewset where you've defined a custom <code>get_queryset</code> method, then the viewset may not have a <code>.queryset</code> attribute set. If you try to register that viewset you'll see an error like this:</p>
-<pre class="prettyprint lang-py"><code>'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
+<pre><code>'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
</code></pre>
<p>This means you'll need to explicitly set the <code>base_name</code> argument when registering the viewset, as it could not be automatically determined from the model name.</p>
<hr />
<h3 id="extra-link-and-actions">Extra link and actions</h3>
<p>Any methods on the viewset decorated with <code>@detail_route</code> or <code>@list_route</code> will also be routed.
For example, given a method like this on the <code>UserViewSet</code> class:</p>
-<pre class="prettyprint lang-py"><code>from myapp.permissions import IsAdminOrIsSelf
+<pre><code>from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route
class UserViewSet(ModelViewSet):
@@ -266,7 +480,7 @@ class UserViewSet(ModelViewSet):
<ul>
<li>URL pattern: <code>^users/{pk}/set_password/$</code> Name: <code>'user-set-password'</code></li>
</ul>
-<p>For more information see the viewset documentation on <a href="viewsets.html#marking-extra-actions-for-routing">marking extra actions for routing</a>.</p>
+<p>For more information see the viewset documentation on <a href="../../viewsets.html#marking-extra-actions-for-routing">marking extra actions for routing</a>.</p>
<h1 id="api-guide">API Guide</h1>
<h2 id="simplerouter">SimpleRouter</h2>
<p>This router includes routes for the standard set of <code>list</code>, <code>create</code>, <code>retrieve</code>, <code>update</code>, <code>partial_update</code> and <code>destroy</code> actions. The viewset can also mark additional methods to be routed, using the <code>@detail_route</code> or <code>@list_route</code> decorators.</p>
@@ -284,11 +498,11 @@ class UserViewSet(ModelViewSet):
<p>By default the URLs created by <code>SimpleRouter</code> are appended with a trailing slash.
This behavior can be modified by setting the <code>trailing_slash</code> argument to <code>False</code> when instantiating the router. For example:</p>
-<pre class="prettyprint lang-py"><code>router = SimpleRouter(trailing_slash=False)
+<pre><code>router = SimpleRouter(trailing_slash=False)
</code></pre>
<p>Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.</p>
<p>The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the <code>lookup_value_regex</code> attribute on the viewset. For example, you can limit the lookup to valid UUIDs:</p>
-<pre class="prettyprint lang-py"><code>class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
+<pre><code>class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_id'
lookup_value_regex = '[0-9a-f]{32}'
</code></pre>
@@ -308,7 +522,7 @@ This behavior can be modified by setting the <code>trailing_slash</code> argumen
</table>
<p>As with <code>SimpleRouter</code> the trailing slashes on the URL routes can be removed by setting the <code>trailing_slash</code> argument to <code>False</code> when instantiating the router.</p>
-<pre class="prettyprint lang-py"><code>router = DefaultRouter(trailing_slash=False)
+<pre><code>router = DefaultRouter(trailing_slash=False)
</code></pre>
<h1 id="custom-routers">Custom Routers</h1>
<p>Implementing a custom router isn't something you'd need to do very often, but it can be useful if you have specific requirements about how the your URLs for your API are structured. Doing so allows you to encapsulate the URL structure in a reusable way that ensures you don't have to write your URL patterns explicitly for each new view.</p>
@@ -335,7 +549,7 @@ To route either or both of these decorators, include a <code>DynamicListRoute</c
<p><strong>initkwargs</strong>: A dictionary of any additional arguments that should be passed when instantiating the view.</p>
<h2 id="example">Example</h2>
<p>The following example will only route to the <code>list</code> and <code>retrieve</code> actions, and does not use the trailing slash convention.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter
+<pre><code>from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter
class CustomReadOnlyRouter(SimpleRouter):
"""
@@ -363,7 +577,7 @@ class CustomReadOnlyRouter(SimpleRouter):
</code></pre>
<p>Let's take a look at the routes our <code>CustomReadOnlyRouter</code> would generate for a simple viewset.</p>
<p><code>views.py</code>:</p>
-<pre class="prettyprint lang-py"><code>class UserViewSet(viewsets.ReadOnlyModelViewSet):
+<pre><code>class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
A viewset that provides the standard actions
"""
@@ -382,7 +596,7 @@ class CustomReadOnlyRouter(SimpleRouter):
return Response([group.name for group in groups])
</code></pre>
<p><code>urls.py</code>:</p>
-<pre class="prettyprint lang-py"><code>router = CustomReadOnlyRouter()
+<pre><code>router = CustomReadOnlyRouter()
router.register('users', UserViewSet)
urlpatterns = router.urls
</code></pre>
@@ -396,7 +610,7 @@ urlpatterns = router.urls
<p>For another example of setting the <code>.routes</code> attribute, see the source code for the <code>SimpleRouter</code> class.</p>
<h2 id="advanced-custom-routers">Advanced custom routers</h2>
-<p>If you want to provide totally custom behavior, you can override <code>BaseRouter</code> and override the <code>get_urls(self)</code> method. The method should inspect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the <code>self.registry</code> attribute. </p>
+<p>If you want to provide totally custom behavior, you can override <code>BaseRouter</code> and override the <code>get_urls(self)</code> method. The method should inspect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the <code>self.registry</code> attribute.</p>
<p>You may also want to override the <code>get_default_base_name(self, viewset)</code> method, or else always explicitly set the <code>base_name</code> argument when registering your viewsets with the router.</p>
<h1 id="third-party-packages">Third Party Packages</h1>
<p>The following third party packages are also available.</p>
@@ -404,49 +618,59 @@ urlpatterns = router.urls
<p>The <a href="https://github.com/alanjds/drf-nested-routers">drf-nested-routers package</a> provides routers and relationship fields for working with nested resources.</p>
<h2 id="wqdb">wq.db</h2>
<p>The <a href="http://wq.io/wq.db">wq.db package</a> provides an advanced <a href="http://wq.io/docs/app.py">Router</a> class (and singleton instance) that extends <code>DefaultRouter</code> with a <code>register_model()</code> API. Much like Django's <code>admin.site.register</code>, the only required argument to <code>app.router.register_model</code> is a model class. Reasonable defaults for a url prefix and viewset will be inferred from the model and global configuration.</p>
-<pre class="prettyprint lang-py"><code>from wq.db.rest import app
+<pre><code>from wq.db.rest import app
from myapp.models import MyModel
app.router.register_model(MyModel)
</code></pre>
<h2 id="drf-extensions">DRF-extensions</h2>
<p>The <a href="http://chibisov.github.io/drf-extensions/docs/"><code>DRF-extensions</code> package</a> provides <a href="http://chibisov.github.io/drf-extensions/docs/#routers">routers</a> for creating <a href="http://chibisov.github.io/drf-extensions/docs/#nested-routes">nested viewsets</a>, <a href="http://chibisov.github.io/drf-extensions/docs/#collection-level-controllers">collection level controllers</a> with <a href="http://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name">customizable endpoint names</a>.</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/api-guide/serializers.html b/api-guide/serializers/index.html
index b6ac381a..23724095 100644
--- a/api-guide/serializers.html
+++ b/api-guide/serializers/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>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/api-guide/serializers"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Serializers, ModelSerializer, HyperlinkedModelSerializer, Advanced serializer usage, 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="serializers-page">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Serializers - 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/api-guide/serializers/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Serializers">
+ <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="../api-guide/fields">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/renderers"><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="../fields">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../renderers">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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,44 +335,156 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#serializers">Serializers</a></li>
-<li><a href="#declaring-serializers">Declaring Serializers</a></li>
-<li><a href="#serializing-objects">Serializing objects</a></li>
-<li><a href="#deserializing-objects">Deserializing objects</a></li>
-<li><a href="#validation">Validation</a></li>
-<li><a href="#saving-object-state">Saving object state</a></li>
-<li><a href="#dealing-with-nested-objects">Dealing with nested objects</a></li>
-<li><a href="#dealing-with-multiple-objects">Dealing with multiple objects</a></li>
-<li><a href="#including-extra-context">Including extra context</a></li>
-<li class="main"><a href="#modelserializer">ModelSerializer</a></li>
-<li><a href="#specifying-which-fields-should-be-included">Specifying which fields should be included</a></li>
-<li><a href="#specifying-nested-serialization">Specifying nested serialization</a></li>
-<li><a href="#specifying-which-fields-should-be-read-only">Specifying which fields should be read-only</a></li>
-<li><a href="#specifying-which-fields-should-be-write-only">Specifying which fields should be write-only</a></li>
-<li><a href="#specifying-fields-explicitly">Specifying fields explicitly</a></li>
-<li><a href="#relational-fields">Relational fields</a></li>
-<li class="main"><a href="#hyperlinkedmodelserializer">HyperlinkedModelSerializer</a></li>
-<li><a href="#how-hyperlinked-views-are-determined">How hyperlinked views are determined</a></li>
-<li><a href="#overriding-the-url-field-behavior">Overriding the URL field behavior</a></li>
-<li class="main"><a href="#advanced-serializer-usage">Advanced serializer usage</a></li>
-<li><a href="#dynamically-modifying-fields">Dynamically modifying fields</a></li>
-<li><a href="#customising-the-default-fields">Customising the default fields</a></li>
-<li class="main"><a href="#third-party-packages">Third party packages</a></li>
-<li><a href="#mongoenginemodelserializer">MongoengineModelSerializer</a></li>
-<li><a href="#geofeaturemodelserializer">GeoFeatureModelSerializer</a></li>
-<li><a href="#hstoreserializer">HStoreSerializer</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#serializers">Serializers</a>
+ </li>
+
+
+ <li>
+ <a href="#declaring-serializers">Declaring Serializers</a>
+ </li>
+
+ <li>
+ <a href="#serializing-objects">Serializing objects</a>
+ </li>
+
+ <li>
+ <a href="#deserializing-objects">Deserializing objects</a>
+ </li>
+
+ <li>
+ <a href="#validation">Validation</a>
+ </li>
+
+ <li>
+ <a href="#saving-object-state">Saving object state</a>
+ </li>
+
+ <li>
+ <a href="#dealing-with-nested-objects">Dealing with nested objects</a>
+ </li>
+
+ <li>
+ <a href="#dealing-with-multiple-objects">Dealing with multiple objects</a>
+ </li>
+
+ <li>
+ <a href="#including-extra-context">Including extra context</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#modelserializer">ModelSerializer</a>
+ </li>
+
+
+ <li>
+ <a href="#specifying-which-fields-should-be-included">Specifying which fields should be included</a>
+ </li>
+
+ <li>
+ <a href="#specifying-nested-serialization">Specifying nested serialization</a>
+ </li>
+
+ <li>
+ <a href="#specifying-which-fields-should-be-read-only">Specifying which fields should be read-only</a>
+ </li>
+
+ <li>
+ <a href="#specifying-which-fields-should-be-write-only">Specifying which fields should be write-only</a>
+ </li>
+
+ <li>
+ <a href="#specifying-fields-explicitly">Specifying fields explicitly</a>
+ </li>
+
+ <li>
+ <a href="#relational-fields">Relational fields</a>
+ </li>
+
+ <li>
+ <a href="#inheritance-of-the-meta-class">Inheritance of the 'Meta' class</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#hyperlinkedmodelserializer">HyperlinkedModelSerializer</a>
+ </li>
+
+
+ <li>
+ <a href="#how-hyperlinked-views-are-determined">How hyperlinked views are determined</a>
+ </li>
+
+ <li>
+ <a href="#overriding-the-url-field-behavior">Overriding the URL field behavior</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#advanced-serializer-usage">Advanced serializer usage</a>
+ </li>
+
+
+ <li>
+ <a href="#dynamically-modifying-fields">Dynamically modifying fields</a>
+ </li>
+
+ <li>
+ <a href="#customising-the-default-fields">Customising the default fields</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#third-party-packages">Third party packages</a>
+ </li>
+
+
+ <li>
+ <a href="#mongoenginemodelserializer">MongoengineModelSerializer</a>
+ </li>
+
+ <li>
+ <a href="#geofeaturemodelserializer">GeoFeatureModelSerializer</a>
+ </li>
+
+ <li>
+ <a href="#hstoreserializer">HStoreSerializer</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/serializers.py"><span class="label label-info">serializers.py</span></a></p>
-<h1 id="serializers">Serializers</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/serializers.py">
+ <span class="label label-info">serializers.py</span>
+ </a>
+
+
+
+ <h1 id="serializers">Serializers</h1>
<blockquote>
<p>Expanding the usefulness of the serializers is something that we would
like to address. However, it's not a trivial problem, and it
@@ -234,7 +495,7 @@ will take some serious design work.</p>
<p>REST framework's serializers work very similarly to Django's <code>Form</code> and <code>ModelForm</code> classes. It provides a <code>Serializer</code> class which gives you a powerful, generic way to control the output of your responses, as well as a <code>ModelSerializer</code> class which provides a useful shortcut for creating serializers that deal with model instances and querysets.</p>
<h2 id="declaring-serializers">Declaring Serializers</h2>
<p>Let's start by creating a simple object we can use for example purposes:</p>
-<pre class="prettyprint lang-py"><code>class Comment(object):
+<pre><code>class Comment(object):
def __init__(self, email, content, created=None):
self.email = email
self.content = content
@@ -244,7 +505,7 @@ comment = Comment(email='leila@example.com', content='foo bar')
</code></pre>
<p>We'll declare a serializer that we can use to serialize and deserialize <code>Comment</code> objects.</p>
<p>Declaring a serializer looks very similar to declaring a form:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import serializers
+<pre><code>from rest_framework import serializers
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField()
@@ -267,12 +528,12 @@ class CommentSerializer(serializers.Serializer):
<p>The <code>restore_object</code> method is optional, and is only required if we want our serializer to support deserialization into fully fledged object instances. If we don't define this method, then deserializing data will simply return a dictionary of items.</p>
<h2 id="serializing-objects">Serializing objects</h2>
<p>We can now use <code>CommentSerializer</code> to serialize a comment, or list of comments. Again, using the <code>Serializer</code> class looks a lot like using a <code>Form</code> class.</p>
-<pre class="prettyprint lang-py"><code>serializer = CommentSerializer(comment)
+<pre><code>serializer = CommentSerializer(comment)
serializer.data
# {'email': u'leila@example.com', 'content': u'foo bar', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774)}
</code></pre>
<p>At this point we've translated the model instance into Python native datatypes. To finalise the serialization process we render the data into <code>json</code>.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.renderers import JSONRenderer
+<pre><code>from rest_framework.renderers import JSONRenderer
json = JSONRenderer().render(serializer.data)
json
@@ -281,7 +542,7 @@ json
<h3 id="customizing-field-representation">Customizing field representation</h3>
<p>Sometimes when serializing objects, you may not want to represent everything exactly the way it is in your model.</p>
<p>If you need to customize the serialized value of a particular field, you can do this by creating a <code>transform_&lt;fieldname&gt;</code> method. For example if you needed to render some markdown from a text field:</p>
-<pre class="prettyprint lang-py"><code>description = serializers.CharField()
+<pre><code>description = serializers.CharField()
description_html = serializers.CharField(source='description', read_only=True)
def transform_description_html(self, obj, value):
@@ -290,30 +551,30 @@ def transform_description_html(self, obj, value):
</code></pre>
<p>These methods are essentially the reverse of <code>validate_&lt;fieldname&gt;</code> (see <em>Validation</em> below.)</p>
<h2 id="deserializing-objects">Deserializing objects</h2>
-<p>Deserialization is similar. First we parse a stream into Python native datatypes... </p>
-<pre class="prettyprint lang-py"><code>from StringIO import StringIO
+<p>Deserialization is similar. First we parse a stream into Python native datatypes...</p>
+<pre><code>from StringIO import StringIO
from rest_framework.parsers import JSONParser
stream = StringIO(json)
data = JSONParser().parse(stream)
</code></pre>
<p>...then we restore those native datatypes into a fully populated object instance.</p>
-<pre class="prettyprint lang-py"><code>serializer = CommentSerializer(data=data)
+<pre><code>serializer = CommentSerializer(data=data)
serializer.is_valid()
# True
serializer.object
# &lt;Comment object at 0x10633b2d0&gt;
</code></pre>
<p>When deserializing data, we can either create a new instance, or update an existing instance.</p>
-<pre class="prettyprint lang-py"><code>serializer = CommentSerializer(data=data) # Create new instance
+<pre><code>serializer = CommentSerializer(data=data) # Create new instance
serializer = CommentSerializer(comment, data=data) # Update `comment`
</code></pre>
<p>By default, serializers must be passed values for all required fields or they will throw validation errors. You can use the <code>partial</code> argument in order to allow partial updates.</p>
-<pre class="prettyprint lang-py"><code>serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True) # Update `comment` with partial data
+<pre><code>serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True) # Update `comment` with partial data
</code></pre>
<h2 id="validation">Validation</h2>
<p>When deserializing data, you always need to call <code>is_valid()</code> before attempting to access the deserialized object. If any validation errors occur, the <code>.errors</code> property will contain a dictionary representing the resulting error messages. For example:</p>
-<pre class="prettyprint lang-py"><code>serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
+<pre><code>serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
@@ -325,7 +586,7 @@ serializer.errors
<p>You can specify custom field-level validation by adding <code>.validate_&lt;fieldname&gt;</code> methods to your <code>Serializer</code> subclass. These are analogous to <code>.clean_&lt;fieldname&gt;</code> methods on Django forms, but accept slightly different arguments.</p>
<p>They take a dictionary of deserialized attributes as a first argument, and the field name in that dictionary as a second argument (which will be either the name of the field or the value of the <code>source</code> argument to the field, if one was provided).</p>
<p>Your <code>validate_&lt;fieldname&gt;</code> methods should either just return the <code>attrs</code> dictionary or raise a <code>ValidationError</code>. For example:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import serializers
+<pre><code>from rest_framework import serializers
class BlogPostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
@@ -342,7 +603,7 @@ class BlogPostSerializer(serializers.Serializer):
</code></pre>
<h4 id="object-level-validation">Object-level validation</h4>
<p>To do any other validation that requires access to multiple fields, add a method called <code>.validate()</code> to your <code>Serializer</code> subclass. This method takes a single argument, which is the <code>attrs</code> dictionary. It should raise a <code>ValidationError</code> if necessary, or just return <code>attrs</code>. For example:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import serializers
+<pre><code>from rest_framework import serializers
class EventSerializer(serializers.Serializer):
description = serializers.CharField(max_length=100)
@@ -359,15 +620,15 @@ class EventSerializer(serializers.Serializer):
</code></pre>
<h2 id="saving-object-state">Saving object state</h2>
<p>To save the deserialized objects created by a serializer, call the <code>.save()</code> method:</p>
-<pre class="prettyprint lang-py"><code>if serializer.is_valid():
+<pre><code>if serializer.is_valid():
serializer.save()
</code></pre>
<p>The default behavior of the method is to simply call <code>.save()</code> on the deserialized object instance. You can override the default save behaviour by overriding the <code>.save_object(obj)</code> method on the serializer class.</p>
-<p>The generic views provided by REST framework call the <code>.save()</code> method when updating or creating entities. </p>
+<p>The generic views provided by REST framework call the <code>.save()</code> method when updating or creating entities.</p>
<h2 id="dealing-with-nested-objects">Dealing with nested objects</h2>
<p>The previous examples are fine for dealing with objects that only have simple datatypes, but sometimes we also need to be able to represent more complex objects, where some of the attributes of an object might not be simple datatypes such as strings, dates or integers.</p>
<p>The <code>Serializer</code> class is itself a type of <code>Field</code>, and can be used to represent relationships where one object type is nested inside another.</p>
-<pre class="prettyprint lang-py"><code>class UserSerializer(serializers.Serializer):
+<pre><code>class UserSerializer(serializers.Serializer):
email = serializers.EmailField()
username = serializers.CharField(max_length=100)
@@ -377,20 +638,20 @@ class CommentSerializer(serializers.Serializer):
created = serializers.DateTimeField()
</code></pre>
<p>If a nested representation may optionally accept the <code>None</code> value you should pass the <code>required=False</code> flag to the nested serializer.</p>
-<pre class="prettyprint lang-py"><code>class CommentSerializer(serializers.Serializer):
+<pre><code>class CommentSerializer(serializers.Serializer):
user = UserSerializer(required=False) # May be an anonymous user.
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
</code></pre>
<p>Similarly if a nested representation should be a list of items, you should pass the <code>many=True</code> flag to the nested serialized.</p>
-<pre class="prettyprint lang-py"><code>class CommentSerializer(serializers.Serializer):
+<pre><code>class CommentSerializer(serializers.Serializer):
user = UserSerializer(required=False)
edits = EditItemSerializer(many=True) # A nested list of 'edit' items.
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
</code></pre>
<p>Validation of nested objects will work the same as before. Errors with nested objects will be nested under the field name of the nested object.</p>
-<pre class="prettyprint lang-py"><code>serializer = CommentSerializer(data={'user': {'email': 'foobar', 'username': 'doe'}, 'content': 'baz'})
+<pre><code>serializer = CommentSerializer(data={'user': {'email': 'foobar', 'username': 'doe'}, 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
@@ -400,7 +661,7 @@ serializer.errors
<p>The <code>Serializer</code> class can also handle serializing or deserializing lists of objects.</p>
<h4 id="serializing-multiple-objects">Serializing multiple objects</h4>
<p>To serialize a queryset or list of objects instead of a single object instance, you should pass the <code>many=True</code> flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.</p>
-<pre class="prettyprint lang-py"><code>queryset = Book.objects.all()
+<pre><code>queryset = Book.objects.all()
serializer = BookSerializer(queryset, many=True)
serializer.data
# [
@@ -413,7 +674,7 @@ serializer.data
<p>To deserialize a list of object data, and create multiple object instances in a single pass, you should also set the <code>many=True</code> flag, and pass a list of data to be deserialized.</p>
<p>This allows you to write views that create multiple items when a <code>POST</code> request is made.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>data = [
+<pre><code>data = [
{'title': 'The bell jar', 'author': 'Sylvia Plath'},
{'title': 'For whom the bell tolls', 'author': 'Ernest Hemingway'}
]
@@ -426,7 +687,7 @@ serializer.save() # `.save()` will be called on each deserialized instance
<p>You can also deserialize a list of objects as part of a bulk update of multiple existing items.
In this case you need to supply both an existing list or queryset of items, as well as a list of data to update those items with.</p>
<p>This allows you to write views that update or create multiple items when a <code>PUT</code> request is made.</p>
-<pre class="prettyprint lang-py"><code># Capitalizing the titles of the books
+<pre><code># Capitalizing the titles of the books
queryset = Book.objects.all()
data = [
{'id': 3, 'title': 'The Bell Jar', 'author': 'Sylvia Plath'},
@@ -439,7 +700,7 @@ serializer.save() # `.save()` will be called on each updated or newly created i
</code></pre>
<p>By default bulk updates will be limited to updating instances that already exist in the provided queryset.</p>
<p>When performing a bulk update you may want to allow new items to be created, and missing items to be deleted. To do so, pass <code>allow_add_remove=True</code> to the serializer.</p>
-<pre class="prettyprint lang-py"><code>serializer = BookSerializer(queryset, data=data, many=True, allow_add_remove=True)
+<pre><code>serializer = BookSerializer(queryset, data=data, many=True, allow_add_remove=True)
serializer.is_valid()
# True
serializer.save() # `.save()` will be called on updated or newly created instances.
@@ -449,7 +710,7 @@ serializer.save() # `.save()` will be called on updated or newly created instan
<h4 id="how-identity-is-determined-when-performing-bulk-updates">How identity is determined when performing bulk updates</h4>
<p>Performing a bulk update is slightly more complicated than performing a bulk creation, because the serializer needs a way to determine how the items in the incoming data should be matched against the existing object instances.</p>
<p>By default the serializer class will use the <code>id</code> key on the incoming data to determine the canonical identity of an object. If you need to change this behavior you should override the <code>get_identity</code> method on the <code>Serializer</code> class. For example:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.Serializer):
+<pre><code>class AccountSerializer(serializers.Serializer):
slug = serializers.CharField(max_length=100)
created = serializers.DateTimeField()
... # Various other fields
@@ -471,7 +732,7 @@ serializer.save() # `.save()` will be called on updated or newly created instan
<h2 id="including-extra-context">Including extra context</h2>
<p>There are some cases where you need to provide extra context to the serializer in addition to the object being serialized. One common case is if you're using a serializer that includes hyperlinked relations, which requires the serializer to have access to the current request so that it can properly generate fully qualified URLs.</p>
<p>You can provide arbitrary additional context by passing a <code>context</code> argument when instantiating the serializer. For example:</p>
-<pre class="prettyprint lang-py"><code>serializer = AccountSerializer(account, context={'request': request})
+<pre><code>serializer = AccountSerializer(account, context={'request': request})
serializer.data
# {'id': 6, 'owner': u'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'}
</code></pre>
@@ -480,7 +741,7 @@ serializer.data
<h1 id="modelserializer">ModelSerializer</h1>
<p>Often you'll want serializer classes that map closely to model definitions.
The <code>ModelSerializer</code> class lets you automatically create a Serializer class with fields that correspond to the Model fields.</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.ModelSerializer):
+<pre><code>class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
</code></pre>
@@ -492,14 +753,14 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<h2 id="specifying-which-fields-should-be-included">Specifying which fields should be included</h2>
<p>If you only want a subset of the default fields to be used in a model serializer, you can do so using <code>fields</code> or <code>exclude</code> options, just as you would with a <code>ModelForm</code>.</p>
<p>For example:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.ModelSerializer):
+<pre><code>class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'users', 'created')
</code></pre>
<h2 id="specifying-nested-serialization">Specifying nested serialization</h2>
<p>The default <code>ModelSerializer</code> uses primary keys for relationships, but you can also easily generate nested representations using the <code>depth</code> option:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.ModelSerializer):
+<pre><code>class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'users', 'created')
@@ -509,16 +770,16 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<p>If you want to customize the way the serialization is done (e.g. using <code>allow_add_remove</code>) you'll need to define the field yourself.</p>
<h2 id="specifying-which-fields-should-be-read-only">Specifying which fields should be read-only</h2>
<p>You may wish to specify multiple fields as read-only. Instead of adding each field explicitly with the <code>read_only=True</code> attribute, you may use the <code>read_only_fields</code> Meta option, like so:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.ModelSerializer):
+<pre><code>class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'users', 'created')
read_only_fields = ('account_name',)
</code></pre>
-<p>Model fields which have <code>editable=False</code> set, and <code>AutoField</code> fields will be set to read-only by default, and do not need to be added to the <code>read_only_fields</code> option. </p>
+<p>Model fields which have <code>editable=False</code> set, and <code>AutoField</code> fields will be set to read-only by default, and do not need to be added to the <code>read_only_fields</code> option.</p>
<h2 id="specifying-which-fields-should-be-write-only">Specifying which fields should be write-only</h2>
<p>You may wish to specify multiple fields as write-only. Instead of adding each field explicitly with the <code>write_only=True</code> attribute, you may use the <code>write_only_fields</code> Meta option, like so:</p>
-<pre class="prettyprint lang-py"><code>class CreateUserSerializer(serializers.ModelSerializer):
+<pre><code>class CreateUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'username', 'password')
@@ -528,14 +789,14 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
"""
Instantiate a new User instance.
"""
- assert instance is None, 'Cannot update users with CreateUserSerializer'
+ assert instance is None, 'Cannot update users with CreateUserSerializer'
user = User(email=attrs['email'], username=attrs['username'])
user.set_password(attrs['password'])
return user
</code></pre>
<h2 id="specifying-fields-explicitly">Specifying fields explicitly</h2>
<p>You can add extra fields to a <code>ModelSerializer</code> or override the default fields by declaring fields on the class, just as you would for a <code>Serializer</code> class.</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.ModelSerializer):
+<pre><code>class AccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
groups = serializers.PrimaryKeyRelatedField(many=True)
@@ -546,14 +807,21 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<h2 id="relational-fields">Relational fields</h2>
<p>When serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation for <code>ModelSerializer</code> is to use the primary keys of the related instances.</p>
<p>Alternative representations include serializing using hyperlinks, serializing complete nested representations, or serializing with a custom representation.</p>
-<p>For full details see the <a href="relations">serializer relations</a> documentation.</p>
+<p>For full details see the <a href="../relations">serializer relations</a> documentation.</p>
+<h2 id="inheritance-of-the-meta-class">Inheritance of the 'Meta' class</h2>
+<p>The inner <code>Meta</code> class on serializers is not inherited from parent classes by default. This is the same behaviour as with Django's <code>Model</code> and <code>ModelForm</code> classes. If you want the <code>Meta</code> class to inherit from a parent class you must do so explicitly. For example:</p>
+<pre><code>class AccountSerializer(MyBaseSerializer):
+ class Meta(MyBaseSerializer.Meta):
+ model = Account
+</code></pre>
+<p>Typically we would recommend <em>not</em> using inheritance on inner Meta classes, but instead declaring all options explicitly.</p>
<hr />
<h1 id="hyperlinkedmodelserializer">HyperlinkedModelSerializer</h1>
<p>The <code>HyperlinkedModelSerializer</code> class is similar to the <code>ModelSerializer</code> class except that it uses hyperlinks to represent relationships, rather than primary keys.</p>
<p>By default the serializer will include a <code>url</code> field instead of a primary key field.</p>
<p>The url field will be represented using a <code>HyperlinkedIdentityField</code> serializer field, and any relationships on the model will be represented using a <code>HyperlinkedRelatedField</code> serializer field.</p>
<p>You can explicitly include the primary key by adding it to the <code>fields</code> option, for example:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
+<pre><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Account
fields = ('url', 'id', 'account_name', 'users', 'created')
@@ -562,7 +830,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<p>There needs to be a way of determining which views should be used for hyperlinking to model instances.</p>
<p>By default hyperlinks are expected to correspond to a view name that matches the style <code>'{model_name}-detail'</code>, and looks up the instance by a <code>pk</code> keyword argument.</p>
<p>You can change the field that is used for object lookups by setting the <code>lookup_field</code> option. The value of this option should correspond both with a kwarg in the URL conf, and with a field on the model. For example:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
+<pre><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Account
fields = ('url', 'account_name', 'users', 'created')
@@ -570,7 +838,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
</code></pre>
<p>Note that the <code>lookup_field</code> will be used as the default on <em>all</em> hyperlinked fields, including both the URL identity, and any hyperlinked relationships.</p>
<p>For more specific requirements such as specifying a different lookup for each field, you'll want to set the fields on the serializer explicitly. For example:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
+<pre><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='account_detail',
lookup_field='account_name'
@@ -589,7 +857,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<h2 id="overriding-the-url-field-behavior">Overriding the URL field behavior</h2>
<p>The name of the URL field defaults to 'url'. You can override this globally, by using the <code>URL_FIELD_NAME</code> setting.</p>
<p>You can also override this on a per-serializer basis by using the <code>url_field_name</code> option on the serializer, like so:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
+<pre><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Account
fields = ('account_url', 'account_name', 'users', 'created')
@@ -597,7 +865,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
</code></pre>
<p><strong>Note</strong>: The generic view implementations normally generate a <code>Location</code> header in response to successful <code>POST</code> requests. Serializers using <code>url_field_name</code> option will not have this header automatically included by the view. If you need to do so you will ned to also override the view's <code>get_success_headers()</code> method.</p>
<p>You can also override the URL field's view name and lookup field without overriding the field explicitly, by using the <code>view_name</code> and <code>lookup_field</code> options, like so:</p>
-<pre class="prettyprint lang-py"><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
+<pre><code>class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Account
fields = ('account_url', 'account_name', 'users', 'created')
@@ -613,7 +881,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<p>Modifying the <code>fields</code> argument directly allows you to do interesting things such as changing the arguments on serializer fields at runtime, rather than at the point of declaring the serializer.</p>
<h3 id="example">Example</h3>
<p>For example, if you wanted to be able to set which fields should be used by a serializer at the point of initializing it, you could create a serializer class like so:</p>
-<pre class="prettyprint lang-py"><code>class DynamicFieldsModelSerializer(serializers.ModelSerializer):
+<pre><code>class DynamicFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed.
@@ -634,7 +902,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
self.fields.pop(field_name)
</code></pre>
<p>This would then allow you to do the following:</p>
-<pre class="prettyprint lang-py"><code>&gt;&gt;&gt; class UserSerializer(DynamicFieldsModelSerializer):
+<pre><code>&gt;&gt;&gt; class UserSerializer(DynamicFieldsModelSerializer):
&gt;&gt;&gt; class Meta:
&gt;&gt;&gt; model = User
&gt;&gt;&gt; fields = ('id', 'username', 'email')
@@ -646,7 +914,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
{'id': 2, 'email': 'jon@example.com'}
</code></pre>
<h2 id="customising-the-default-fields">Customising the default fields</h2>
-<p>The <code>field_mapping</code> attribute is a dictionary that maps model classes to serializer classes. Overriding the attribute will let you set a different set of default serializer classes. </p>
+<p>The <code>field_mapping</code> attribute is a dictionary that maps model classes to serializer classes. Overriding the attribute will let you set a different set of default serializer classes.</p>
<p>For more advanced customization than simply changing the default serializer class you can override various <code>get_&lt;field_type&gt;_field</code> methods. Doing so will allow you to customize the arguments that each serializer field is initialized with. Each of these methods may either return a field or serializer instance, or <code>None</code>.</p>
<h3 id="get_pk_field">get_pk_field</h3>
<p><strong>Signature</strong>: <code>.get_pk_field(self, model_field)</code></p>
@@ -664,7 +932,7 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<p>Returns the field instance that should be used for non-relational, non-pk fields.</p>
<h3 id="example_1">Example</h3>
<p>The following custom model serializer could be used as a base class for model serializers that should always exclude the pk by default.</p>
-<pre class="prettyprint lang-py"><code>class NoPKModelSerializer(serializers.ModelSerializer):
+<pre><code>class NoPKModelSerializer(serializers.ModelSerializer):
def get_pk_field(self, model_field):
return None
</code></pre>
@@ -677,42 +945,52 @@ The <code>ModelSerializer</code> class lets you automatically create a Serialize
<p>The <a href="https://github.com/djangonauts/django-rest-framework-gis">django-rest-framework-gis</a> package provides a <code>GeoFeatureModelSerializer</code> serializer class that supports GeoJSON both for read and write operations.</p>
<h2 id="hstoreserializer">HStoreSerializer</h2>
<p>The <a href="https://github.com/djangonauts/django-rest-framework-hstore">django-rest-framework-hstore</a> package provides an <code>HStoreSerializer</code> to support <a href="https://github.com/djangonauts/django-hstore">django-hstore</a> <code>DictionaryField</code> model field and its <code>schema-mode</code> feature.</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/api-guide/settings.html b/api-guide/settings/index.html
index c0866f02..2a86a14b 100644
--- a/api-guide/settings.html
+++ b/api-guide/settings/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>Settings - 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/api-guide/settings"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Settings, API Reference">
- <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="settings-page">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Settings - 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/api-guide/settings/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Settings">
+ <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/documenting-your-api">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/testing"><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="../../topics/documenting-your-api">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../testing">
+ <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">
+
+ <li class="dropdown active">
<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="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">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>
+
+ <li >
+ <a href="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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,36 +335,91 @@ a.fusion-poweredby {
-->
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
- <li class="main"><a href="#settings">Settings</a></li>
-<li><a href="#accessing-settings">Accessing settings</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#api-policy-settings">API policy settings</a></li>
-<li><a href="#generic-view-settings">Generic view settings</a></li>
-<li><a href="#authentication-settings">Authentication settings</a></li>
-<li><a href="#test-settings">Test settings</a></li>
-<li><a href="#browser-overrides">Browser overrides</a></li>
-<li><a href="#date-and-time-formatting">Date and time formatting</a></li>
-<li><a href="#view-names-and-descriptions">View names and descriptions</a></li>
-<li><a href="#miscellaneous-settings">Miscellaneous settings</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
+
+
+
+
+
+ <li class="main">
+ <a href="#settings">Settings</a>
+ </li>
+
+
+ <li>
+ <a href="#accessing-settings">Accessing settings</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#api-policy-settings">API policy settings</a>
+ </li>
+
+ <li>
+ <a href="#generic-view-settings">Generic view settings</a>
+ </li>
+
+ <li>
+ <a href="#authentication-settings">Authentication settings</a>
+ </li>
+
+ <li>
+ <a href="#test-settings">Test settings</a>
+ </li>
+
+ <li>
+ <a href="#browser-overrides">Browser overrides</a>
+ </li>
+
+ <li>
+ <a href="#date-and-time-formatting">Date and time formatting</a>
+ </li>
+
+ <li>
+ <a href="#encodings">Encodings</a>
+ </li>
+
+ <li>
+ <a href="#view-names-and-descriptions">View names and descriptions</a>
+ </li>
+
+ <li>
+ <a href="#miscellaneous-settings">Miscellaneous settings</a>
+ </li>
+
+
+
+
+
+
+ </ul>
</div>
</div>
<div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/settings.py"><span class="label label-info">settings.py</span></a></p>
-<h1 id="settings">Settings</h1>
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/settings.py">
+ <span class="label label-info">settings.py</span>
+ </a>
+
+
+
+ <h1 id="settings">Settings</h1>
<blockquote>
<p>Namespaces are one honking great idea - let's do more of those!</p>
<p>&mdash; <a href="http://www.python.org/dev/peps/pep-0020/">The Zen of Python</a></p>
</blockquote>
<p>Configuration for REST framework is all namespaced inside a single Django setting, named <code>REST_FRAMEWORK</code>.</p>
<p>For example your project's <code>settings.py</code> file might include something like this:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
+<pre><code>REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.YAMLRenderer',
),
@@ -227,7 +431,7 @@ a.fusion-poweredby {
<h2 id="accessing-settings">Accessing settings</h2>
<p>If you need to access the values of REST framework's API settings in your project,
you should use the <code>api_settings</code> object. For example.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.settings import api_settings
+<pre><code>from rest_framework.settings import api_settings
print api_settings.DEFAULT_AUTHENTICATION_CLASSES
</code></pre>
@@ -239,7 +443,7 @@ print api_settings.DEFAULT_AUTHENTICATION_CLASSES
<h4 id="default_renderer_classes">DEFAULT_RENDERER_CLASSES</h4>
<p>A list or tuple of renderer classes, that determines the default set of renderers that may be used when returning a <code>Response</code> object.</p>
<p>Default:</p>
-<pre class="prettyprint lang-py"><code>(
+<pre><code>(
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
)
@@ -247,7 +451,7 @@ print api_settings.DEFAULT_AUTHENTICATION_CLASSES
<h4 id="default_parser_classes">DEFAULT_PARSER_CLASSES</h4>
<p>A list or tuple of parser classes, that determines the default set of parsers used when accessing the <code>request.DATA</code> property.</p>
<p>Default:</p>
-<pre class="prettyprint lang-py"><code>(
+<pre><code>(
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
@@ -256,15 +460,15 @@ print api_settings.DEFAULT_AUTHENTICATION_CLASSES
<h4 id="default_authentication_classes">DEFAULT_AUTHENTICATION_CLASSES</h4>
<p>A list or tuple of authentication classes, that determines the default set of authenticators used when accessing the <code>request.user</code> or <code>request.auth</code> properties.</p>
<p>Default:</p>
-<pre class="prettyprint lang-py"><code>(
+<pre><code>(
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
</code></pre>
<h4 id="default_permission_classes">DEFAULT_PERMISSION_CLASSES</h4>
-<p>A list or tuple of permission classes, that determines the default set of permissions checked at the start of a view.</p>
+<p>A list or tuple of permission classes, that determines the default set of permissions checked at the start of a view. Permission must be granted by every class in the list.</p>
<p>Default:</p>
-<pre class="prettyprint lang-py"><code>(
+<pre><code>(
'rest_framework.permissions.AllowAny',
)
</code></pre>
@@ -289,33 +493,33 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<h4 id="paginate_by_param">PAGINATE_BY_PARAM</h4>
<p>The name of a query parameter, which can be used by the client to override the default page size to use for pagination. If set to <code>None</code>, clients may not override the default page size.</p>
<p>For example, given the following settings:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
+<pre><code>REST_FRAMEWORK = {
'PAGINATE_BY': 10,
'PAGINATE_BY_PARAM': 'page_size',
}
</code></pre>
<p>A client would be able to modify the pagination size by using the <code>page_size</code> query parameter. For example:</p>
-<pre class="prettyprint lang-py"><code>GET http://example.com/api/accounts?page_size=25
+<pre><code>GET http://example.com/api/accounts?page_size=25
</code></pre>
<p>Default: <code>None</code></p>
<h4 id="max_paginate_by">MAX_PAGINATE_BY</h4>
<p>The maximum page size to allow when the page size is specified by the client. If set to <code>None</code>, then no maximum limit is applied.</p>
<p>For example, given the following settings:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
+<pre><code>REST_FRAMEWORK = {
'PAGINATE_BY': 10,
'PAGINATE_BY_PARAM': 'page_size',
'MAX_PAGINATE_BY': 100
}
</code></pre>
<p>A client request like the following would return a paginated list of up to 100 items.</p>
-<pre class="prettyprint lang-py"><code>GET http://example.com/api/accounts?page_size=999
+<pre><code>GET http://example.com/api/accounts?page_size=999
</code></pre>
<p>Default: <code>None</code></p>
<h3 id="search_param">SEARCH_PARAM</h3>
-<p>The name of a query paramater, which can be used to specify the search term used by <code>SearchFilter</code>.</p>
+<p>The name of a query parameter, which can be used to specify the search term used by <code>SearchFilter</code>.</p>
<p>Default: <code>search</code></p>
<h4 id="ordering_param">ORDERING_PARAM</h4>
-<p>The name of a query paramater, which can be used to specify the ordering of results returned by <code>OrderingFilter</code>.</p>
+<p>The name of a query parameter, which can be used to specify the ordering of results returned by <code>OrderingFilter</code>.</p>
<p>Default: <code>ordering</code></p>
<hr />
<h2 id="authentication-settings">Authentication settings</h2>
@@ -337,7 +541,7 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<p>The renderer classes that are supported when building test requests.</p>
<p>The format of any of these renderer classes may be used when constructing a test request, for example: <code>client.post('/users', {'username': 'jamie'}, format='json')</code></p>
<p>Default:</p>
-<pre class="prettyprint lang-py"><code>(
+<pre><code>(
'rest_framework.renderers.MultiPartRenderer',
'rest_framework.renderers.JSONRenderer'
)
@@ -370,7 +574,7 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<h4 id="datetime_format">DATETIME_FORMAT</h4>
<p>A format string that should be used by default for rendering the output of <code>DateTimeField</code> serializer fields. If <code>None</code>, then <code>DateTimeField</code> serializer fields will return Python <code>datetime</code> objects, and the datetime encoding will be determined by the renderer.</p>
<p>May be any of <code>None</code>, <code>'iso-8601'</code> or a Python <a href="http://docs.python.org/2/library/time.html#time.strftime">strftime format</a> string.</p>
-<p>Default: <code>None</code></p>
+<p>Default: <code>'iso-8601'</code></p>
<h4 id="datetime_input_formats">DATETIME_INPUT_FORMATS</h4>
<p>A list of format strings that should be used by default for parsing inputs to <code>DateTimeField</code> serializer fields.</p>
<p>May be a list including the string <code>'iso-8601'</code> or Python <a href="http://docs.python.org/2/library/time.html#time.strftime">strftime format</a> strings.</p>
@@ -378,7 +582,7 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<h4 id="date_format">DATE_FORMAT</h4>
<p>A format string that should be used by default for rendering the output of <code>DateField</code> serializer fields. If <code>None</code>, then <code>DateField</code> serializer fields will return Python <code>date</code> objects, and the date encoding will be determined by the renderer.</p>
<p>May be any of <code>None</code>, <code>'iso-8601'</code> or a Python <a href="http://docs.python.org/2/library/time.html#time.strftime">strftime format</a> string.</p>
-<p>Default: <code>None</code></p>
+<p>Default: <code>'iso-8601'</code></p>
<h4 id="date_input_formats">DATE_INPUT_FORMATS</h4>
<p>A list of format strings that should be used by default for parsing inputs to <code>DateField</code> serializer fields.</p>
<p>May be a list including the string <code>'iso-8601'</code> or Python <a href="http://docs.python.org/2/library/time.html#time.strftime">strftime format</a> strings.</p>
@@ -386,18 +590,42 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<h4 id="time_format">TIME_FORMAT</h4>
<p>A format string that should be used by default for rendering the output of <code>TimeField</code> serializer fields. If <code>None</code>, then <code>TimeField</code> serializer fields will return Python <code>time</code> objects, and the time encoding will be determined by the renderer.</p>
<p>May be any of <code>None</code>, <code>'iso-8601'</code> or a Python <a href="http://docs.python.org/2/library/time.html#time.strftime">strftime format</a> string.</p>
-<p>Default: <code>None</code></p>
+<p>Default: <code>'iso-8601'</code></p>
<h4 id="time_input_formats">TIME_INPUT_FORMATS</h4>
<p>A list of format strings that should be used by default for parsing inputs to <code>TimeField</code> serializer fields.</p>
<p>May be a list including the string <code>'iso-8601'</code> or Python <a href="http://docs.python.org/2/library/time.html#time.strftime">strftime format</a> strings.</p>
<p>Default: <code>['iso-8601']</code></p>
<hr />
+<h2 id="encodings">Encodings</h2>
+<h4 id="unicode_json">UNICODE_JSON</h4>
+<p>When set to <code>True</code>, JSON responses will allow unicode characters in responses. For example:</p>
+<pre><code>{"unicode black star":"★"}
+</code></pre>
+<p>When set to <code>False</code>, JSON responses will escape non-ascii characters, like so:</p>
+<pre><code>{"unicode black star":"\u2605"}
+</code></pre>
+<p>Both styles conform to <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>, and are syntactically valid JSON. The unicode style is preferred as being more user-friendly when inspecting API responses.</p>
+<p>Default: <code>True</code></p>
+<h4 id="compact_json">COMPACT_JSON</h4>
+<p>When set to <code>True</code>, JSON responses will return compact representations, with no spacing after <code>':'</code> and <code>','</code> characters. For example:</p>
+<pre><code>{"is_admin":false,"email":"jane@example"}
+</code></pre>
+<p>When set to <code>False</code>, JSON responses will return slightly more verbose representations, like so:</p>
+<pre><code>{"is_admin": false, "email": "jane@example"}
+</code></pre>
+<p>The default style is to return minified responses, in line with <a href="https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses">Heroku's API design guidelines</a>.</p>
+<p>Default: <code>True</code></p>
+<h4 id="coerce_decimal_to_string">COERCE_DECIMAL_TO_STRING</h4>
+<p>When returning decimal objects in API representations that do not support a native decimal type, it is normally best to return the value as a string. This avoids the loss of precision that occurs with binary floating point implementations.</p>
+<p>When set to <code>True</code>, the serializer <code>DecimalField</code> class will return strings instead of <code>Decimal</code> objects. When set to <code>False</code>, serializers will return <code>Decimal</code> objects, which the default JSON encoder will return as floats.</p>
+<p>Default: <code>True</code></p>
+<hr />
<h2 id="view-names-and-descriptions">View names and descriptions</h2>
<p><strong>The following settings are used to generate the view names and descriptions, as used in responses to <code>OPTIONS</code> requests, and as used in the browsable API.</strong></p>
<h4 id="view_name_function">VIEW_NAME_FUNCTION</h4>
<p>A string representing the function that should be used when generating view names.</p>
<p>This should be a function with the following signature:</p>
-<pre class="prettyprint lang-py"><code>view_name(cls, suffix=None)
+<pre><code>view_name(cls, suffix=None)
</code></pre>
<ul>
<li><code>cls</code>: The view class. Typically the name function would inspect the name of the class when generating a descriptive name, by accessing <code>cls.__name__</code>.</li>
@@ -408,7 +636,7 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<p>A string representing the function that should be used when generating view descriptions.</p>
<p>This setting can be changed to support markup styles other than the default markdown. For example, you can use it to support <code>rst</code> markup in your view docstrings being output in the browsable API.</p>
<p>This should be a function with the following signature:</p>
-<pre class="prettyprint lang-py"><code>view_description(cls, html=False)
+<pre><code>view_description(cls, html=False)
</code></pre>
<ul>
<li><code>cls</code>: The view class. Typically the description function would inspect the docstring of the class when generating a description, by accessing <code>cls.__doc__</code></li>
@@ -421,12 +649,15 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<p>A string representing the function that should be used when returning a response for any given exception. If the function returns <code>None</code>, a 500 error will be raised.</p>
<p>This setting can be changed to support error responses other than the default <code>{"detail": "Failure..."}</code> responses. For example, you can use it to provide API responses like <code>{"errors": [{"message": "Failure...", "code": ""} ...]}</code>.</p>
<p>This should be a function with the following signature:</p>
-<pre class="prettyprint lang-py"><code>exception_handler(exc)
+<pre><code>exception_handler(exc)
</code></pre>
<ul>
<li><code>exc</code>: The exception.</li>
</ul>
<p>Default: <code>'rest_framework.views.exception_handler'</code></p>
+<h4 id="non_field_errors_key">NON_FIELD_ERRORS_KEY</h4>
+<p>A string representing the key that should be used for serializer errors that do not refer to a specific field, but are instead general errors.</p>
+<p>Default: <code>'non_field_errors'</code></p>
<h4 id="url_field_name">URL_FIELD_NAME</h4>
<p>A string representing the key that should be used for the URL fields generated by <code>HyperlinkedModelSerializer</code>.</p>
<p>Default: <code>'url'</code></p>
@@ -436,42 +667,52 @@ If set to <code>None</code> then generic filtering is disabled.</p>
<h4 id="num_proxies">NUM_PROXIES</h4>
<p>An integer of 0 or more, that may be used to specify the number of application proxies that the API runs behind. This allows throttling to more accurately identify client IP addresses. If set to <code>None</code> then less strict IP matching will be used by the throttle classes.</p>
<p>Default: <code>None</code></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>
- // Dynamically force sidenav to no higher than browser window
- $('.side-nav').css('max-height', window.innerHeight - 130);
+ <script>
+ //$('.side-nav').scrollspy()
+ var shiftWindow = function() {
+ scrollBy(0, -50)
+ };
+ if (location.hash) shiftWindow();
+ window.addEventListener("hashchange", shiftWindow);
- $(function(){
- $(window).resize(function(){
- $('.side-nav').css('max-height', window.innerHeight - 130);
- });
+ $('.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>
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/api-guide/status-codes.html b/api-guide/status-codes.html
deleted file mode 100644
index 2daa0edf..00000000
--- a/api-guide/status-codes.html
+++ /dev/null
@@ -1,339 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Status Codes - 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/api-guide/status-codes"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Status Codes">
- <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="status-codes-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="../api-guide/testing">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/exceptions"><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="#status-codes">Status Codes</a></li>
-<li><a href="#informational---1xx">Informational - 1xx</a></li>
-<li><a href="#successful---2xx">Successful - 2xx</a></li>
-<li><a href="#redirection---3xx">Redirection - 3xx</a></li>
-<li><a href="#client-error---4xx">Client Error - 4xx</a></li>
-<li><a href="#server-error---5xx">Server Error - 5xx</a></li>
-<li><a href="#helper-functions">Helper functions</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/status.py"><span class="label label-info">status.py</span></a></p>
-<h1 id="status-codes">Status Codes</h1>
-<blockquote>
-<p>418 I'm a teapot - Any attempt to brew coffee with a teapot should result in the error code "418 I'm a teapot". The resulting entity body MAY be short and stout.</p>
-<p>&mdash; <a href="http://www.ietf.org/rfc/rfc2324.txt">RFC 2324</a>, Hyper Text Coffee Pot Control Protocol</p>
-</blockquote>
-<p>Using bare status codes in your responses isn't recommended. REST framework includes a set of named constants that you can use to make more code more obvious and readable.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import status
-from rest_framework.response import Response
-
-def empty_view(self):
- content = {'please move along': 'nothing to see here'}
- return Response(content, status=status.HTTP_404_NOT_FOUND)
-</code></pre>
-<p>The full set of HTTP status codes included in the <code>status</code> module is listed below.</p>
-<p>The module also includes a set of helper functions for testing if a status code is in a given range.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework import status
-from rest_framework.test import APITestCase
-
-class ExampleTestCase(APITestCase):
- def test_url_root(self):
- url = reverse('index')
- response = self.client.get(url)
- self.assertTrue(status.is_success(response.status_code))
-</code></pre>
-<p>For more information on proper usage of HTTP status codes see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">RFC 2616</a>
-and <a href="http://tools.ietf.org/html/rfc6585">RFC 6585</a>.</p>
-<h2 id="informational-1xx">Informational - 1xx</h2>
-<p>This class of status code indicates a provisional response. There are no 1xx status codes used in REST framework by default.</p>
-<pre class="prettyprint lang-py"><code>HTTP_100_CONTINUE
-HTTP_101_SWITCHING_PROTOCOLS
-</code></pre>
-<h2 id="successful-2xx">Successful - 2xx</h2>
-<p>This class of status code indicates that the client's request was successfully received, understood, and accepted.</p>
-<pre class="prettyprint lang-py"><code>HTTP_200_OK
-HTTP_201_CREATED
-HTTP_202_ACCEPTED
-HTTP_203_NON_AUTHORITATIVE_INFORMATION
-HTTP_204_NO_CONTENT
-HTTP_205_RESET_CONTENT
-HTTP_206_PARTIAL_CONTENT
-</code></pre>
-<h2 id="redirection-3xx">Redirection - 3xx</h2>
-<p>This class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request.</p>
-<pre class="prettyprint lang-py"><code>HTTP_300_MULTIPLE_CHOICES
-HTTP_301_MOVED_PERMANENTLY
-HTTP_302_FOUND
-HTTP_303_SEE_OTHER
-HTTP_304_NOT_MODIFIED
-HTTP_305_USE_PROXY
-HTTP_306_RESERVED
-HTTP_307_TEMPORARY_REDIRECT
-</code></pre>
-<h2 id="client-error-4xx">Client Error - 4xx</h2>
-<p>The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition.</p>
-<pre class="prettyprint lang-py"><code>HTTP_400_BAD_REQUEST
-HTTP_401_UNAUTHORIZED
-HTTP_402_PAYMENT_REQUIRED
-HTTP_403_FORBIDDEN
-HTTP_404_NOT_FOUND
-HTTP_405_METHOD_NOT_ALLOWED
-HTTP_406_NOT_ACCEPTABLE
-HTTP_407_PROXY_AUTHENTICATION_REQUIRED
-HTTP_408_REQUEST_TIMEOUT
-HTTP_409_CONFLICT
-HTTP_410_GONE
-HTTP_411_LENGTH_REQUIRED
-HTTP_412_PRECONDITION_FAILED
-HTTP_413_REQUEST_ENTITY_TOO_LARGE
-HTTP_414_REQUEST_URI_TOO_LONG
-HTTP_415_UNSUPPORTED_MEDIA_TYPE
-HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
-HTTP_417_EXPECTATION_FAILED
-HTTP_428_PRECONDITION_REQUIRED
-HTTP_429_TOO_MANY_REQUESTS
-HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
-</code></pre>
-<h2 id="server-error-5xx">Server Error - 5xx</h2>
-<p>Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has erred or is incapable of performing the request. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition.</p>
-<pre class="prettyprint lang-py"><code>HTTP_500_INTERNAL_SERVER_ERROR
-HTTP_501_NOT_IMPLEMENTED
-HTTP_502_BAD_GATEWAY
-HTTP_503_SERVICE_UNAVAILABLE
-HTTP_504_GATEWAY_TIMEOUT
-HTTP_505_HTTP_VERSION_NOT_SUPPORTED
-HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
-</code></pre>
-<h2 id="helper-functions">Helper functions</h2>
-<p>The following helper functions are available for identifying the category of the response code.</p>
-<pre class="prettyprint lang-py"><code>is_informational() # 1xx
-is_success() # 2xx
-is_redirect() # 3xx
-is_client_error() # 4xx
-is_server_error() # 5xx
-</code></pre>
- </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/api-guide/status-codes/index.html b/api-guide/status-codes/index.html
new file mode 100644
index 00000000..b7d71887
--- /dev/null
+++ b/api-guide/status-codes/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>Status codes - 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/api-guide/status-codes/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Status codes">
+ <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="../testing">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../exceptions">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#status-codes">Status Codes</a>
+ </li>
+
+
+ <li>
+ <a href="#informational-1xx">Informational - 1xx</a>
+ </li>
+
+ <li>
+ <a href="#successful-2xx">Successful - 2xx</a>
+ </li>
+
+ <li>
+ <a href="#redirection-3xx">Redirection - 3xx</a>
+ </li>
+
+ <li>
+ <a href="#client-error-4xx">Client Error - 4xx</a>
+ </li>
+
+ <li>
+ <a href="#server-error-5xx">Server Error - 5xx</a>
+ </li>
+
+ <li>
+ <a href="#helper-functions">Helper functions</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/status.py">
+ <span class="label label-info">status.py</span>
+ </a>
+
+
+
+ <h1 id="status-codes">Status Codes</h1>
+<blockquote>
+<p>418 I'm a teapot - Any attempt to brew coffee with a teapot should result in the error code "418 I'm a teapot". The resulting entity body MAY be short and stout.</p>
+<p>&mdash; <a href="http://www.ietf.org/rfc/rfc2324.txt">RFC 2324</a>, Hyper Text Coffee Pot Control Protocol</p>
+</blockquote>
+<p>Using bare status codes in your responses isn't recommended. REST framework includes a set of named constants that you can use to make more code more obvious and readable.</p>
+<pre><code>from rest_framework import status
+from rest_framework.response import Response
+
+def empty_view(self):
+ content = {'please move along': 'nothing to see here'}
+ return Response(content, status=status.HTTP_404_NOT_FOUND)
+</code></pre>
+<p>The full set of HTTP status codes included in the <code>status</code> module is listed below.</p>
+<p>The module also includes a set of helper functions for testing if a status code is in a given range.</p>
+<pre><code>from rest_framework import status
+from rest_framework.test import APITestCase
+
+class ExampleTestCase(APITestCase):
+ def test_url_root(self):
+ url = reverse('index')
+ response = self.client.get(url)
+ self.assertTrue(status.is_success(response.status_code))
+</code></pre>
+<p>For more information on proper usage of HTTP status codes see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">RFC 2616</a>
+and <a href="http://tools.ietf.org/html/rfc6585">RFC 6585</a>.</p>
+<h2 id="informational-1xx">Informational - 1xx</h2>
+<p>This class of status code indicates a provisional response. There are no 1xx status codes used in REST framework by default.</p>
+<pre><code>HTTP_100_CONTINUE
+HTTP_101_SWITCHING_PROTOCOLS
+</code></pre>
+<h2 id="successful-2xx">Successful - 2xx</h2>
+<p>This class of status code indicates that the client's request was successfully received, understood, and accepted.</p>
+<pre><code>HTTP_200_OK
+HTTP_201_CREATED
+HTTP_202_ACCEPTED
+HTTP_203_NON_AUTHORITATIVE_INFORMATION
+HTTP_204_NO_CONTENT
+HTTP_205_RESET_CONTENT
+HTTP_206_PARTIAL_CONTENT
+</code></pre>
+<h2 id="redirection-3xx">Redirection - 3xx</h2>
+<p>This class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request.</p>
+<pre><code>HTTP_300_MULTIPLE_CHOICES
+HTTP_301_MOVED_PERMANENTLY
+HTTP_302_FOUND
+HTTP_303_SEE_OTHER
+HTTP_304_NOT_MODIFIED
+HTTP_305_USE_PROXY
+HTTP_306_RESERVED
+HTTP_307_TEMPORARY_REDIRECT
+</code></pre>
+<h2 id="client-error-4xx">Client Error - 4xx</h2>
+<p>The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition.</p>
+<pre><code>HTTP_400_BAD_REQUEST
+HTTP_401_UNAUTHORIZED
+HTTP_402_PAYMENT_REQUIRED
+HTTP_403_FORBIDDEN
+HTTP_404_NOT_FOUND
+HTTP_405_METHOD_NOT_ALLOWED
+HTTP_406_NOT_ACCEPTABLE
+HTTP_407_PROXY_AUTHENTICATION_REQUIRED
+HTTP_408_REQUEST_TIMEOUT
+HTTP_409_CONFLICT
+HTTP_410_GONE
+HTTP_411_LENGTH_REQUIRED
+HTTP_412_PRECONDITION_FAILED
+HTTP_413_REQUEST_ENTITY_TOO_LARGE
+HTTP_414_REQUEST_URI_TOO_LONG
+HTTP_415_UNSUPPORTED_MEDIA_TYPE
+HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
+HTTP_417_EXPECTATION_FAILED
+HTTP_428_PRECONDITION_REQUIRED
+HTTP_429_TOO_MANY_REQUESTS
+HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
+</code></pre>
+<h2 id="server-error-5xx">Server Error - 5xx</h2>
+<p>Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has erred or is incapable of performing the request. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition.</p>
+<pre><code>HTTP_500_INTERNAL_SERVER_ERROR
+HTTP_501_NOT_IMPLEMENTED
+HTTP_502_BAD_GATEWAY
+HTTP_503_SERVICE_UNAVAILABLE
+HTTP_504_GATEWAY_TIMEOUT
+HTTP_505_HTTP_VERSION_NOT_SUPPORTED
+HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
+</code></pre>
+<h2 id="helper-functions">Helper functions</h2>
+<p>The following helper functions are available for identifying the category of the response code.</p>
+<pre><code>is_informational() # 1xx
+is_success() # 2xx
+is_redirect() # 3xx
+is_client_error() # 4xx
+is_server_error() # 5xx
+</code></pre>
+
+ </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/api-guide/testing.html b/api-guide/testing.html
deleted file mode 100644
index b58f4637..00000000
--- a/api-guide/testing.html
+++ /dev/null
@@ -1,451 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Testing - 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/api-guide/testing"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Testing, APIRequestFactory, APIClient, Test cases, Testing responses, Configuration">
- <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="testing-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="../api-guide/settings">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/status-codes"><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="#testing">Testing</a></li>
-<li class="main"><a href="#apirequestfactory">APIRequestFactory</a></li>
-<li><a href="#creating-test-requests">Creating test requests</a></li>
-<li><a href="#forcing-authentication">Forcing authentication</a></li>
-<li><a href="#forcing-csrf-validation">Forcing CSRF validation</a></li>
-<li class="main"><a href="#apiclient">APIClient</a></li>
-<li><a href="#making-requests">Making requests</a></li>
-<li><a href="#authenticating">Authenticating</a></li>
-<li><a href="#csrf-validation">CSRF validation</a></li>
-<li class="main"><a href="#test-cases">Test cases</a></li>
-<li><a href="#example">Example</a></li>
-<li class="main"><a href="#testing-responses">Testing responses</a></li>
-<li><a href="#checking-the-response-data">Checking the response data</a></li>
-<li><a href="#rendering-responses">Rendering responses</a></li>
-<li class="main"><a href="#configuration">Configuration</a></li>
-<li><a href="#setting-the-default-format">Setting the default format</a></li>
-<li><a href="#setting-the-available-formats">Setting the available formats</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/test.py"><span class="label label-info">test.py</span></a></p>
-<h1 id="testing">Testing</h1>
-<blockquote>
-<p>Code without tests is broken as designed.</p>
-<p>&mdash; <a href="http://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper">Jacob Kaplan-Moss</a></p>
-</blockquote>
-<p>REST framework includes a few helper classes that extend Django's existing test framework, and improve support for making API requests.</p>
-<h1 id="apirequestfactory">APIRequestFactory</h1>
-<p>Extends <a href="https://docs.djangoproject.com/en/dev/topics/testing/advanced/#django.test.client.RequestFactory">Django's existing <code>RequestFactory</code> class</a>.</p>
-<h2 id="creating-test-requests">Creating test requests</h2>
-<p>The <code>APIRequestFactory</code> class supports an almost identical API to Django's standard <code>RequestFactory</code> class. This means the that standard <code>.get()</code>, <code>.post()</code>, <code>.put()</code>, <code>.patch()</code>, <code>.delete()</code>, <code>.head()</code> and <code>.options()</code> methods are all available.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.test import APIRequestFactory
-
-# Using the standard RequestFactory API to create a form POST request
-factory = APIRequestFactory()
-request = factory.post('/notes/', {'title': 'new idea'})
-</code></pre>
-<h4 id="using-the-format-argument">Using the <code>format</code> argument</h4>
-<p>Methods which create a request body, such as <code>post</code>, <code>put</code> and <code>patch</code>, include a <code>format</code> argument, which make it easy to generate requests using a content type other than multipart form data. For example:</p>
-<pre class="prettyprint lang-py"><code># Create a JSON POST request
-factory = APIRequestFactory()
-request = factory.post('/notes/', {'title': 'new idea'}, format='json')
-</code></pre>
-<p>By default the available formats are <code>'multipart'</code> and <code>'json'</code>. For compatibility with Django's existing <code>RequestFactory</code> the default format is <code>'multipart'</code>.</p>
-<p>To support a wider set of request formats, or change the default format, <a href="#configuration">see the configuration section</a>.</p>
-<h4 id="explicitly-encoding-the-request-body">Explicitly encoding the request body</h4>
-<p>If you need to explicitly encode the request body, you can do so by setting the <code>content_type</code> flag. For example:</p>
-<pre class="prettyprint lang-py"><code>request = factory.post('/notes/', json.dumps({'title': 'new idea'}), content_type='application/json')
-</code></pre>
-<h4 id="put-and-patch-with-form-data">PUT and PATCH with form data</h4>
-<p>One difference worth noting between Django's <code>RequestFactory</code> and REST framework's <code>APIRequestFactory</code> is that multipart form data will be encoded for methods other than just <code>.post()</code>.</p>
-<p>For example, using <code>APIRequestFactory</code>, you can make a form PUT request like so:</p>
-<pre class="prettyprint lang-py"><code>factory = APIRequestFactory()
-request = factory.put('/notes/547/', {'title': 'remember to email dave'})
-</code></pre>
-<p>Using Django's <code>RequestFactory</code>, you'd need to explicitly encode the data yourself:</p>
-<pre class="prettyprint lang-py"><code>from django.test.client import encode_multipart, RequestFactory
-
-factory = RequestFactory()
-data = {'title': 'remember to email dave'}
-content = encode_multipart('BoUnDaRyStRiNg', data)
-content_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg'
-request = factory.put('/notes/547/', content, content_type=content_type)
-</code></pre>
-<h2 id="forcing-authentication">Forcing authentication</h2>
-<p>When testing views directly using a request factory, it's often convenient to be able to directly authenticate the request, rather than having to construct the correct authentication credentials.</p>
-<p>To forcibly authenticate a request, use the <code>force_authenticate()</code> method.</p>
-<pre class="prettyprint lang-py"><code>factory = APIRequestFactory()
-user = User.objects.get(username='olivia')
-view = AccountDetail.as_view()
-
-# Make an authenticated request to the view...
-request = factory.get('/accounts/django-superstars/')
-force_authenticate(request, user=user)
-response = view(request)
-</code></pre>
-<p>The signature for the method is <code>force_authenticate(request, user=None, token=None)</code>. When making the call, either or both of the user and token may be set.</p>
-<p>For example, when forcibly authenticating using a token, you might do something like the following:</p>
-<pre class="prettyprint lang-py"><code>user = User.objects.get(username='olivia')
-request = factory.get('/accounts/django-superstars/')
-force_authenticate(request, user=user, token=user.token)
-</code></pre>
-<hr />
-<p><strong>Note</strong>: When using <code>APIRequestFactory</code>, the object that is returned is Django's standard <code>HttpRequest</code>, and not REST framework's <code>Request</code> object, which is only generated once the view is called.</p>
-<p>This means that setting attributes directly on the request object may not always have the effect you expect. For example, setting <code>.token</code> directly will have no effect, and setting <code>.user</code> directly will only work if session authentication is being used.</p>
-<pre class="prettyprint lang-py"><code># Request will only authenticate if `SessionAuthentication` is in use.
-request = factory.get('/accounts/django-superstars/')
-request.user = user
-response = view(request)
-</code></pre>
-<hr />
-<h2 id="forcing-csrf-validation">Forcing CSRF validation</h2>
-<p>By default, requests created with <code>APIRequestFactory</code> will not have CSRF validation applied when passed to a REST framework view. If you need to explicitly turn CSRF validation on, you can do so by setting the <code>enforce_csrf_checks</code> flag when instantiating the factory.</p>
-<pre class="prettyprint lang-py"><code>factory = APIRequestFactory(enforce_csrf_checks=True)
-</code></pre>
-<hr />
-<p><strong>Note</strong>: It's worth noting that Django's standard <code>RequestFactory</code> doesn't need to include this option, because when using regular Django the CSRF validation takes place in middleware, which is not run when testing views directly. When using REST framework, CSRF validation takes place inside the view, so the request factory needs to disable view-level CSRF checks.</p>
-<hr />
-<h1 id="apiclient">APIClient</h1>
-<p>Extends <a href="https://docs.djangoproject.com/en/dev/topics/testing/overview/#module-django.test.client">Django's existing <code>Client</code> class</a>.</p>
-<h2 id="making-requests">Making requests</h2>
-<p>The <code>APIClient</code> class supports the same request interface as <code>APIRequestFactory</code>. This means the that standard <code>.get()</code>, <code>.post()</code>, <code>.put()</code>, <code>.patch()</code>, <code>.delete()</code>, <code>.head()</code> and <code>.options()</code> methods are all available. For example:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.test import APIClient
-
-client = APIClient()
-client.post('/notes/', {'title': 'new idea'}, format='json')
-</code></pre>
-<p>To support a wider set of request formats, or change the default format, <a href="#configuration">see the configuration section</a>.</p>
-<h2 id="authenticating">Authenticating</h2>
-<h4 id="loginkwargs">.login(**kwargs)</h4>
-<p>The <code>login</code> method functions exactly as it does with Django's regular <code>Client</code> class. This allows you to authenticate requests against any views which include <code>SessionAuthentication</code>.</p>
-<pre class="prettyprint lang-py"><code># Make all requests in the context of a logged in session.
-client = APIClient()
-client.login(username='lauren', password='secret')
-</code></pre>
-<p>To logout, call the <code>logout</code> method as usual.</p>
-<pre class="prettyprint lang-py"><code># Log out
-client.logout()
-</code></pre>
-<p>The <code>login</code> method is appropriate for testing APIs that use session authentication, for example web sites which include AJAX interaction with the API.</p>
-<h4 id="credentialskwargs">.credentials(**kwargs)</h4>
-<p>The <code>credentials</code> method can be used to set headers that will then be included on all subsequent requests by the test client.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.authtoken.models import Token
-from rest_framework.test import APIClient
-
-# Include an appropriate `Authorization:` header on all requests.
-token = Token.objects.get(user__username='lauren')
-client = APIClient()
-client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
-</code></pre>
-<p>Note that calling <code>credentials</code> a second time overwrites any existing credentials. You can unset any existing credentials by calling the method with no arguments.</p>
-<pre class="prettyprint lang-py"><code># Stop including any credentials
-client.credentials()
-</code></pre>
-<p>The <code>credentials</code> method is appropriate for testing APIs that require authentication headers, such as basic authentication, OAuth1a and OAuth2 authentication, and simple token authentication schemes.</p>
-<h4 id="force_authenticateusernone-tokennone">.force_authenticate(user=None, token=None)</h4>
-<p>Sometimes you may want to bypass authentication, and simple force all requests by the test client to be automatically treated as authenticated.</p>
-<p>This can be a useful shortcut if you're testing the API but don't want to have to construct valid authentication credentials in order to make test requests.</p>
-<pre class="prettyprint lang-py"><code>user = User.objects.get(username='lauren')
-client = APIClient()
-client.force_authenticate(user=user)
-</code></pre>
-<p>To unauthenticate subsequent requests, call <code>force_authenticate</code> setting the user and/or token to <code>None</code>.</p>
-<pre class="prettyprint lang-py"><code>client.force_authenticate(user=None)
-</code></pre>
-<h2 id="csrf-validation">CSRF validation</h2>
-<p>By default CSRF validation is not applied when using <code>APIClient</code>. If you need to explicitly enable CSRF validation, you can do so by setting the <code>enforce_csrf_checks</code> flag when instantiating the client.</p>
-<pre class="prettyprint lang-py"><code>client = APIClient(enforce_csrf_checks=True)
-</code></pre>
-<p>As usual CSRF validation will only apply to any session authenticated views. This means CSRF validation will only occur if the client has been logged in by calling <code>login()</code>.</p>
-<hr />
-<h1 id="test-cases">Test cases</h1>
-<p>REST framework includes the following test case classes, that mirror the existing Django test case classes, but use <code>APIClient</code> instead of Django's default <code>Client</code>.</p>
-<ul>
-<li><code>APISimpleTestCase</code></li>
-<li><code>APITransactionTestCase</code></li>
-<li><code>APITestCase</code></li>
-<li><code>APILiveServerTestCase</code></li>
-</ul>
-<h2 id="example">Example</h2>
-<p>You can use any of REST framework's test case classes as you would for the regular Django test case classes. The <code>self.client</code> attribute will be an <code>APIClient</code> instance.</p>
-<pre class="prettyprint lang-py"><code>from django.core.urlresolvers import reverse
-from rest_framework import status
-from rest_framework.test import APITestCase
-
-class AccountTests(APITestCase):
- def test_create_account(self):
- """
- Ensure we can create a new account object.
- """
- url = reverse('account-list')
- data = {'name': 'DabApps'}
- response = self.client.post(url, data, format='json')
- self.assertEqual(response.status_code, status.HTTP_201_CREATED)
- self.assertEqual(response.data, data)
-</code></pre>
-<hr />
-<h1 id="testing-responses">Testing responses</h1>
-<h2 id="checking-the-response-data">Checking the response data</h2>
-<p>When checking the validity of test responses it's often more convenient to inspect the data that the response was created with, rather than inspecting the fully rendered response.</p>
-<p>For example, it's easier to inspect <code>response.data</code>:</p>
-<pre class="prettyprint lang-py"><code>response = self.client.get('/users/4/')
-self.assertEqual(response.data, {'id': 4, 'username': 'lauren'})
-</code></pre>
-<p>Instead of inspecting the result of parsing <code>response.content</code>:</p>
-<pre class="prettyprint lang-py"><code>response = self.client.get('/users/4/')
-self.assertEqual(json.loads(response.content), {'id': 4, 'username': 'lauren'})
-</code></pre>
-<h2 id="rendering-responses">Rendering responses</h2>
-<p>If you're testing views directly using <code>APIRequestFactory</code>, the responses that are returned will not yet be rendered, as rendering of template responses is performed by Django's internal request-response cycle. In order to access <code>response.content</code>, you'll first need to render the response.</p>
-<pre class="prettyprint lang-py"><code>view = UserDetail.as_view()
-request = factory.get('/users/4')
-response = view(request, pk='4')
-response.render() # Cannot access `response.content` without this.
-self.assertEqual(response.content, '{"username": "lauren", "id": 4}')
-</code></pre>
-<hr />
-<h1 id="configuration">Configuration</h1>
-<h2 id="setting-the-default-format">Setting the default format</h2>
-<p>The default format used to make test requests may be set using the <code>TEST_REQUEST_DEFAULT_FORMAT</code> setting key. For example, to always use JSON for test requests by default instead of standard multipart form requests, set the following in your <code>settings.py</code> file:</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- ...
- 'TEST_REQUEST_DEFAULT_FORMAT': 'json'
-}
-</code></pre>
-<h2 id="setting-the-available-formats">Setting the available formats</h2>
-<p>If you need to test requests using something other than multipart or json requests, you can do so by setting the <code>TEST_REQUEST_RENDERER_CLASSES</code> setting.</p>
-<p>For example, to add support for using <code>format='yaml'</code> in test requests, you might have something like this in your <code>settings.py</code> file.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- ...
- 'TEST_REQUEST_RENDERER_CLASSES': (
- 'rest_framework.renderers.MultiPartRenderer',
- 'rest_framework.renderers.JSONRenderer',
- 'rest_framework.renderers.YAMLRenderer'
- )
-}
-</code></pre>
- </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/api-guide/testing/index.html b/api-guide/testing/index.html
new file mode 100644
index 00000000..3d9b61b1
--- /dev/null
+++ b/api-guide/testing/index.html
@@ -0,0 +1,695 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Testing - 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/api-guide/testing/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Testing">
+ <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="../settings">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../status-codes">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#testing">Testing</a>
+ </li>
+
+
+
+
+
+ <li class="main">
+ <a href="#apirequestfactory">APIRequestFactory</a>
+ </li>
+
+
+ <li>
+ <a href="#creating-test-requests">Creating test requests</a>
+ </li>
+
+ <li>
+ <a href="#forcing-authentication">Forcing authentication</a>
+ </li>
+
+ <li>
+ <a href="#forcing-csrf-validation">Forcing CSRF validation</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#apiclient">APIClient</a>
+ </li>
+
+
+ <li>
+ <a href="#making-requests">Making requests</a>
+ </li>
+
+ <li>
+ <a href="#authenticating">Authenticating</a>
+ </li>
+
+ <li>
+ <a href="#csrf-validation">CSRF validation</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#test-cases">Test cases</a>
+ </li>
+
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#testing-responses">Testing responses</a>
+ </li>
+
+
+ <li>
+ <a href="#checking-the-response-data">Checking the response data</a>
+ </li>
+
+ <li>
+ <a href="#rendering-responses">Rendering responses</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#configuration">Configuration</a>
+ </li>
+
+
+ <li>
+ <a href="#setting-the-default-format">Setting the default format</a>
+ </li>
+
+ <li>
+ <a href="#setting-the-available-formats">Setting the available formats</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/test.py">
+ <span class="label label-info">test.py</span>
+ </a>
+
+
+
+ <h1 id="testing">Testing</h1>
+<blockquote>
+<p>Code without tests is broken as designed.</p>
+<p>&mdash; <a href="http://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper">Jacob Kaplan-Moss</a></p>
+</blockquote>
+<p>REST framework includes a few helper classes that extend Django's existing test framework, and improve support for making API requests.</p>
+<h1 id="apirequestfactory">APIRequestFactory</h1>
+<p>Extends <a href="https://docs.djangoproject.com/en/dev/topics/testing/advanced/#django.test.client.RequestFactory">Django's existing <code>RequestFactory</code> class</a>.</p>
+<h2 id="creating-test-requests">Creating test requests</h2>
+<p>The <code>APIRequestFactory</code> class supports an almost identical API to Django's standard <code>RequestFactory</code> class. This means the that standard <code>.get()</code>, <code>.post()</code>, <code>.put()</code>, <code>.patch()</code>, <code>.delete()</code>, <code>.head()</code> and <code>.options()</code> methods are all available.</p>
+<pre><code>from rest_framework.test import APIRequestFactory
+
+# Using the standard RequestFactory API to create a form POST request
+factory = APIRequestFactory()
+request = factory.post('/notes/', {'title': 'new idea'})
+</code></pre>
+<h4 id="using-the-format-argument">Using the <code>format</code> argument</h4>
+<p>Methods which create a request body, such as <code>post</code>, <code>put</code> and <code>patch</code>, include a <code>format</code> argument, which make it easy to generate requests using a content type other than multipart form data. For example:</p>
+<pre><code># Create a JSON POST request
+factory = APIRequestFactory()
+request = factory.post('/notes/', {'title': 'new idea'}, format='json')
+</code></pre>
+<p>By default the available formats are <code>'multipart'</code> and <code>'json'</code>. For compatibility with Django's existing <code>RequestFactory</code> the default format is <code>'multipart'</code>.</p>
+<p>To support a wider set of request formats, or change the default format, <a href="#configuration">see the configuration section</a>.</p>
+<h4 id="explicitly-encoding-the-request-body">Explicitly encoding the request body</h4>
+<p>If you need to explicitly encode the request body, you can do so by setting the <code>content_type</code> flag. For example:</p>
+<pre><code>request = factory.post('/notes/', json.dumps({'title': 'new idea'}), content_type='application/json')
+</code></pre>
+<h4 id="put-and-patch-with-form-data">PUT and PATCH with form data</h4>
+<p>One difference worth noting between Django's <code>RequestFactory</code> and REST framework's <code>APIRequestFactory</code> is that multipart form data will be encoded for methods other than just <code>.post()</code>.</p>
+<p>For example, using <code>APIRequestFactory</code>, you can make a form PUT request like so:</p>
+<pre><code>factory = APIRequestFactory()
+request = factory.put('/notes/547/', {'title': 'remember to email dave'})
+</code></pre>
+<p>Using Django's <code>RequestFactory</code>, you'd need to explicitly encode the data yourself:</p>
+<pre><code>from django.test.client import encode_multipart, RequestFactory
+
+factory = RequestFactory()
+data = {'title': 'remember to email dave'}
+content = encode_multipart('BoUnDaRyStRiNg', data)
+content_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg'
+request = factory.put('/notes/547/', content, content_type=content_type)
+</code></pre>
+<h2 id="forcing-authentication">Forcing authentication</h2>
+<p>When testing views directly using a request factory, it's often convenient to be able to directly authenticate the request, rather than having to construct the correct authentication credentials.</p>
+<p>To forcibly authenticate a request, use the <code>force_authenticate()</code> method.</p>
+<pre><code>factory = APIRequestFactory()
+user = User.objects.get(username='olivia')
+view = AccountDetail.as_view()
+
+# Make an authenticated request to the view...
+request = factory.get('/accounts/django-superstars/')
+force_authenticate(request, user=user)
+response = view(request)
+</code></pre>
+<p>The signature for the method is <code>force_authenticate(request, user=None, token=None)</code>. When making the call, either or both of the user and token may be set.</p>
+<p>For example, when forcibly authenticating using a token, you might do something like the following:</p>
+<pre><code>user = User.objects.get(username='olivia')
+request = factory.get('/accounts/django-superstars/')
+force_authenticate(request, user=user, token=user.token)
+</code></pre>
+<hr />
+<p><strong>Note</strong>: When using <code>APIRequestFactory</code>, the object that is returned is Django's standard <code>HttpRequest</code>, and not REST framework's <code>Request</code> object, which is only generated once the view is called.</p>
+<p>This means that setting attributes directly on the request object may not always have the effect you expect. For example, setting <code>.token</code> directly will have no effect, and setting <code>.user</code> directly will only work if session authentication is being used.</p>
+<pre><code># Request will only authenticate if `SessionAuthentication` is in use.
+request = factory.get('/accounts/django-superstars/')
+request.user = user
+response = view(request)
+</code></pre>
+<hr />
+<h2 id="forcing-csrf-validation">Forcing CSRF validation</h2>
+<p>By default, requests created with <code>APIRequestFactory</code> will not have CSRF validation applied when passed to a REST framework view. If you need to explicitly turn CSRF validation on, you can do so by setting the <code>enforce_csrf_checks</code> flag when instantiating the factory.</p>
+<pre><code>factory = APIRequestFactory(enforce_csrf_checks=True)
+</code></pre>
+<hr />
+<p><strong>Note</strong>: It's worth noting that Django's standard <code>RequestFactory</code> doesn't need to include this option, because when using regular Django the CSRF validation takes place in middleware, which is not run when testing views directly. When using REST framework, CSRF validation takes place inside the view, so the request factory needs to disable view-level CSRF checks.</p>
+<hr />
+<h1 id="apiclient">APIClient</h1>
+<p>Extends <a href="https://docs.djangoproject.com/en/dev/topics/testing/overview/#module-django.test.client">Django's existing <code>Client</code> class</a>.</p>
+<h2 id="making-requests">Making requests</h2>
+<p>The <code>APIClient</code> class supports the same request interface as <code>APIRequestFactory</code>. This means the that standard <code>.get()</code>, <code>.post()</code>, <code>.put()</code>, <code>.patch()</code>, <code>.delete()</code>, <code>.head()</code> and <code>.options()</code> methods are all available. For example:</p>
+<pre><code>from rest_framework.test import APIClient
+
+client = APIClient()
+client.post('/notes/', {'title': 'new idea'}, format='json')
+</code></pre>
+<p>To support a wider set of request formats, or change the default format, <a href="#configuration">see the configuration section</a>.</p>
+<h2 id="authenticating">Authenticating</h2>
+<h4 id="loginkwargs">.login(**kwargs)</h4>
+<p>The <code>login</code> method functions exactly as it does with Django's regular <code>Client</code> class. This allows you to authenticate requests against any views which include <code>SessionAuthentication</code>.</p>
+<pre><code># Make all requests in the context of a logged in session.
+client = APIClient()
+client.login(username='lauren', password='secret')
+</code></pre>
+<p>To logout, call the <code>logout</code> method as usual.</p>
+<pre><code># Log out
+client.logout()
+</code></pre>
+<p>The <code>login</code> method is appropriate for testing APIs that use session authentication, for example web sites which include AJAX interaction with the API.</p>
+<h4 id="credentialskwargs">.credentials(**kwargs)</h4>
+<p>The <code>credentials</code> method can be used to set headers that will then be included on all subsequent requests by the test client.</p>
+<pre><code>from rest_framework.authtoken.models import Token
+from rest_framework.test import APIClient
+
+# Include an appropriate `Authorization:` header on all requests.
+token = Token.objects.get(user__username='lauren')
+client = APIClient()
+client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
+</code></pre>
+<p>Note that calling <code>credentials</code> a second time overwrites any existing credentials. You can unset any existing credentials by calling the method with no arguments.</p>
+<pre><code># Stop including any credentials
+client.credentials()
+</code></pre>
+<p>The <code>credentials</code> method is appropriate for testing APIs that require authentication headers, such as basic authentication, OAuth1a and OAuth2 authentication, and simple token authentication schemes.</p>
+<h4 id="force_authenticateusernone-tokennone">.force_authenticate(user=None, token=None)</h4>
+<p>Sometimes you may want to bypass authentication, and simple force all requests by the test client to be automatically treated as authenticated.</p>
+<p>This can be a useful shortcut if you're testing the API but don't want to have to construct valid authentication credentials in order to make test requests.</p>
+<pre><code>user = User.objects.get(username='lauren')
+client = APIClient()
+client.force_authenticate(user=user)
+</code></pre>
+<p>To unauthenticate subsequent requests, call <code>force_authenticate</code> setting the user and/or token to <code>None</code>.</p>
+<pre><code>client.force_authenticate(user=None)
+</code></pre>
+<h2 id="csrf-validation">CSRF validation</h2>
+<p>By default CSRF validation is not applied when using <code>APIClient</code>. If you need to explicitly enable CSRF validation, you can do so by setting the <code>enforce_csrf_checks</code> flag when instantiating the client.</p>
+<pre><code>client = APIClient(enforce_csrf_checks=True)
+</code></pre>
+<p>As usual CSRF validation will only apply to any session authenticated views. This means CSRF validation will only occur if the client has been logged in by calling <code>login()</code>.</p>
+<hr />
+<h1 id="test-cases">Test cases</h1>
+<p>REST framework includes the following test case classes, that mirror the existing Django test case classes, but use <code>APIClient</code> instead of Django's default <code>Client</code>.</p>
+<ul>
+<li><code>APISimpleTestCase</code></li>
+<li><code>APITransactionTestCase</code></li>
+<li><code>APITestCase</code></li>
+<li><code>APILiveServerTestCase</code></li>
+</ul>
+<h2 id="example">Example</h2>
+<p>You can use any of REST framework's test case classes as you would for the regular Django test case classes. The <code>self.client</code> attribute will be an <code>APIClient</code> instance.</p>
+<pre><code>from django.core.urlresolvers import reverse
+from rest_framework import status
+from rest_framework.test import APITestCase
+
+class AccountTests(APITestCase):
+ def test_create_account(self):
+ """
+ Ensure we can create a new account object.
+ """
+ url = reverse('account-list')
+ data = {'name': 'DabApps'}
+ response = self.client.post(url, data, format='json')
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ self.assertEqual(response.data, data)
+</code></pre>
+<hr />
+<h1 id="testing-responses">Testing responses</h1>
+<h2 id="checking-the-response-data">Checking the response data</h2>
+<p>When checking the validity of test responses it's often more convenient to inspect the data that the response was created with, rather than inspecting the fully rendered response.</p>
+<p>For example, it's easier to inspect <code>response.data</code>:</p>
+<pre><code>response = self.client.get('/users/4/')
+self.assertEqual(response.data, {'id': 4, 'username': 'lauren'})
+</code></pre>
+<p>Instead of inspecting the result of parsing <code>response.content</code>:</p>
+<pre><code>response = self.client.get('/users/4/')
+self.assertEqual(json.loads(response.content), {'id': 4, 'username': 'lauren'})
+</code></pre>
+<h2 id="rendering-responses">Rendering responses</h2>
+<p>If you're testing views directly using <code>APIRequestFactory</code>, the responses that are returned will not yet be rendered, as rendering of template responses is performed by Django's internal request-response cycle. In order to access <code>response.content</code>, you'll first need to render the response.</p>
+<pre><code>view = UserDetail.as_view()
+request = factory.get('/users/4')
+response = view(request, pk='4')
+response.render() # Cannot access `response.content` without this.
+self.assertEqual(response.content, '{"username": "lauren", "id": 4}')
+</code></pre>
+<hr />
+<h1 id="configuration">Configuration</h1>
+<h2 id="setting-the-default-format">Setting the default format</h2>
+<p>The default format used to make test requests may be set using the <code>TEST_REQUEST_DEFAULT_FORMAT</code> setting key. For example, to always use JSON for test requests by default instead of standard multipart form requests, set the following in your <code>settings.py</code> file:</p>
+<pre><code>REST_FRAMEWORK = {
+ ...
+ 'TEST_REQUEST_DEFAULT_FORMAT': 'json'
+}
+</code></pre>
+<h2 id="setting-the-available-formats">Setting the available formats</h2>
+<p>If you need to test requests using something other than multipart or json requests, you can do so by setting the <code>TEST_REQUEST_RENDERER_CLASSES</code> setting.</p>
+<p>For example, to add support for using <code>format='yaml'</code> in test requests, you might have something like this in your <code>settings.py</code> file.</p>
+<pre><code>REST_FRAMEWORK = {
+ ...
+ 'TEST_REQUEST_RENDERER_CLASSES': (
+ 'rest_framework.renderers.MultiPartRenderer',
+ 'rest_framework.renderers.JSONRenderer',
+ 'rest_framework.renderers.YAMLRenderer'
+ )
+}
+</code></pre>
+
+ </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/api-guide/throttling.html b/api-guide/throttling.html
deleted file mode 100644
index 1978a92a..00000000
--- a/api-guide/throttling.html
+++ /dev/null
@@ -1,388 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Throttling - 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/api-guide/throttling"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Throttling, API Reference, Custom throttles">
- <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="throttling-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="../api-guide/filtering">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/permissions"><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="#throttling">Throttling</a></li>
-<li><a href="#how-throttling-is-determined">How throttling is determined</a></li>
-<li><a href="#setting-the-throttling-policy">Setting the throttling policy</a></li>
-<li><a href="#setting-up-the-cache">Setting up the cache</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#anonratethrottle">AnonRateThrottle</a></li>
-<li><a href="#userratethrottle">UserRateThrottle</a></li>
-<li><a href="#scopedratethrottle">ScopedRateThrottle</a></li>
-<li class="main"><a href="#custom-throttles">Custom throttles</a></li>
-<li><a href="#example">Example</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/throttling.py"><span class="label label-info">throttling.py</span></a></p>
-<h1 id="throttling">Throttling</h1>
-<blockquote>
-<p>HTTP/1.1 420 Enhance Your Calm</p>
-<p><a href="https://dev.twitter.com/docs/error-codes-responses">Twitter API rate limiting response</a></p>
-</blockquote>
-<p>Throttling is similar to <a href="permissions">permissions</a>, in that it determines if a request should be authorized. Throttles indicate a temporary state, and are used to control the rate of requests that clients can make to an API.</p>
-<p>As with permissions, multiple throttles may be used. Your API might have a restrictive throttle for unauthenticated requests, and a less restrictive throttle for authenticated requests.</p>
-<p>Another scenario where you might want to use multiple throttles would be if you need to impose different constraints on different parts of the API, due to some services being particularly resource-intensive.</p>
-<p>Multiple throttles can also be used if you want to impose both burst throttling rates, and sustained throttling rates. For example, you might want to limit a user to a maximum of 60 requests per minute, and 1000 requests per day.</p>
-<p>Throttles do not necessarily only refer to rate-limiting requests. For example a storage service might also need to throttle against bandwidth, and a paid data service might want to throttle against a certain number of a records being accessed.</p>
-<h2 id="how-throttling-is-determined">How throttling is determined</h2>
-<p>As with permissions and authentication, throttling in REST framework is always defined as a list of classes.</p>
-<p>Before running the main body of the view each throttle in the list is checked.
-If any throttle check fails an <code>exceptions.Throttled</code> exception will be raised, and the main body of the view will not run.</p>
-<h2 id="setting-the-throttling-policy">Setting the throttling policy</h2>
-<p>The default throttling policy may be set globally, using the <code>DEFAULT_THROTTLE_CLASSES</code> and <code>DEFAULT_THROTTLE_RATES</code> settings. For example.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'DEFAULT_THROTTLE_CLASSES': (
- 'rest_framework.throttling.AnonRateThrottle',
- 'rest_framework.throttling.UserRateThrottle'
- ),
- 'DEFAULT_THROTTLE_RATES': {
- 'anon': '100/day',
- 'user': '1000/day'
- }
-}
-</code></pre>
-<p>The rate descriptions used in <code>DEFAULT_THROTTLE_RATES</code> may include <code>second</code>, <code>minute</code>, <code>hour</code> or <code>day</code> as the throttle period.</p>
-<p>You can also set the throttling policy on a per-view or per-viewset basis,
-using the <code>APIView</code> class based views.</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.response import Response
-from rest_framework.throttling import UserRateThrottle
-from rest_framework.views import APIView
-
-class ExampleView(APIView):
- throttle_classes = (UserRateThrottle,)
-
- def get(self, request, format=None):
- content = {
- 'status': 'request was permitted'
- }
- return Response(content)
-</code></pre>
-<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
-<pre class="prettyprint lang-py"><code>@api_view(['GET'])
-@throttle_classes([UserRateThrottle])
-def example_view(request, format=None):
- content = {
- 'status': 'request was permitted'
- }
- return Response(content)
-</code></pre>
-<h2 id="how-clients-are-identified">How clients are identified</h2>
-<p>The <code>X-Forwarded-For</code> and <code>Remote-Addr</code> HTTP headers are used to uniquely identify client IP addresses for throttling. If the <code>X-Forwarded-For</code> header is present then it will be used, otherwise the value of the <code>Remote-Addr</code> header will be used.</p>
-<p>If you need to strictly identify unique client IP addresses, you'll need to first configure the number of application proxies that the API runs behind by setting the <code>NUM_PROXIES</code> setting. This setting should be an integer of zero or more. If set to non-zero then the client IP will be identified as being the last IP address in the <code>X-Forwarded-For</code> header, once any application proxy IP addresses have first been excluded. If set to zero, then the <code>Remote-Addr</code> header will always be used as the identifying IP address.</p>
-<p>It is important to understand that if you configure the <code>NUM_PROXIES</code> setting, then all clients behind a unique <a href="http://en.wikipedia.org/wiki/Network_address_translation">NAT'd</a> gateway will be treated as a single client.</p>
-<p>Further context on how the <code>X-Forwarded-For</code> header works, and identifing a remote client IP can be <a href="http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster">found here</a>.</p>
-<h2 id="setting-up-the-cache">Setting up the cache</h2>
-<p>The throttle classes provided by REST framework use Django's cache backend. You should make sure that you've set appropriate <a href="https://docs.djangoproject.com/en/dev/ref/settings/#caches">cache settings</a>. The default value of <code>LocMemCache</code> backend should be okay for simple setups. See Django's <a href="https://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache">cache documentation</a> for more details.</p>
-<p>If you need to use a cache other than <code>'default'</code>, you can do so by creating a custom throttle class and setting the <code>cache</code> attribute. For example:</p>
-<pre class="prettyprint lang-py"><code>class CustomAnonRateThrottle(AnonRateThrottle):
- cache = get_cache('alternate')
-</code></pre>
-<p>You'll need to rememeber to also set your custom throttle class in the <code>'DEFAULT_THROTTLE_CLASSES'</code> settings key, or using the <code>throttle_classes</code> view attribute.</p>
-<hr />
-<h1 id="api-reference">API Reference</h1>
-<h2 id="anonratethrottle">AnonRateThrottle</h2>
-<p>The <code>AnonRateThrottle</code> will only ever throttle unauthenticated users. The IP address of the incoming request is used to generate a unique key to throttle against.</p>
-<p>The allowed request rate is determined from one of the following (in order of preference).</p>
-<ul>
-<li>The <code>rate</code> property on the class, which may be provided by overriding <code>AnonRateThrottle</code> and setting the property.</li>
-<li>The <code>DEFAULT_THROTTLE_RATES['anon']</code> setting.</li>
-</ul>
-<p><code>AnonRateThrottle</code> is suitable if you want to restrict the rate of requests from unknown sources.</p>
-<h2 id="userratethrottle">UserRateThrottle</h2>
-<p>The <code>UserRateThrottle</code> will throttle users to a given rate of requests across the API. The user id is used to generate a unique key to throttle against. Unauthenticated requests will fall back to using the IP address of the incoming request to generate a unique key to throttle against.</p>
-<p>The allowed request rate is determined from one of the following (in order of preference).</p>
-<ul>
-<li>The <code>rate</code> property on the class, which may be provided by overriding <code>UserRateThrottle</code> and setting the property.</li>
-<li>The <code>DEFAULT_THROTTLE_RATES['user']</code> setting.</li>
-</ul>
-<p>An API may have multiple <code>UserRateThrottles</code> in place at the same time. To do so, override <code>UserRateThrottle</code> and set a unique "scope" for each class.</p>
-<p>For example, multiple user throttle rates could be implemented by using the following classes...</p>
-<pre class="prettyprint lang-py"><code>class BurstRateThrottle(UserRateThrottle):
- scope = 'burst'
-
-class SustainedRateThrottle(UserRateThrottle):
- scope = 'sustained'
-</code></pre>
-<p>...and the following settings.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'DEFAULT_THROTTLE_CLASSES': (
- 'example.throttles.BurstRateThrottle',
- 'example.throttles.SustainedRateThrottle'
- ),
- 'DEFAULT_THROTTLE_RATES': {
- 'burst': '60/min',
- 'sustained': '1000/day'
- }
-}
-</code></pre>
-<p><code>UserRateThrottle</code> is suitable if you want simple global rate restrictions per-user.</p>
-<h2 id="scopedratethrottle">ScopedRateThrottle</h2>
-<p>The <code>ScopedRateThrottle</code> class can be used to restrict access to specific parts of the API. This throttle will only be applied if the view that is being accessed includes a <code>.throttle_scope</code> property. The unique throttle key will then be formed by concatenating the "scope" of the request with the unique user id or IP address.</p>
-<p>The allowed request rate is determined by the <code>DEFAULT_THROTTLE_RATES</code> setting using a key from the request "scope".</p>
-<p>For example, given the following views...</p>
-<pre class="prettyprint lang-py"><code>class ContactListView(APIView):
- throttle_scope = 'contacts'
- ...
-
-class ContactDetailView(ApiView):
- throttle_scope = 'contacts'
- ...
-
-class UploadView(APIView):
- throttle_scope = 'uploads'
- ...
-</code></pre>
-<p>...and the following settings.</p>
-<pre class="prettyprint lang-py"><code>REST_FRAMEWORK = {
- 'DEFAULT_THROTTLE_CLASSES': (
- 'rest_framework.throttling.ScopedRateThrottle',
- ),
- 'DEFAULT_THROTTLE_RATES': {
- 'contacts': '1000/day',
- 'uploads': '20/day'
- }
-}
-</code></pre>
-<p>User requests to either <code>ContactListView</code> or <code>ContactDetailView</code> would be restricted to a total of 1000 requests per-day. User requests to <code>UploadView</code> would be restricted to 20 requests per day.</p>
-<hr />
-<h1 id="custom-throttles">Custom throttles</h1>
-<p>To create a custom throttle, override <code>BaseThrottle</code> and implement <code>.allow_request(self, request, view)</code>. The method should return <code>True</code> if the request should be allowed, and <code>False</code> otherwise.</p>
-<p>Optionally you may also override the <code>.wait()</code> method. If implemented, <code>.wait()</code> should return a recommended number of seconds to wait before attempting the next request, or <code>None</code>. The <code>.wait()</code> method will only be called if <code>.allow_request()</code> has previously returned <code>False</code>.</p>
-<h2 id="example">Example</h2>
-<p>The following is an example of a rate throttle, that will randomly throttle 1 in every 10 requests.</p>
-<pre class="prettyprint lang-py"><code>class RandomRateThrottle(throttles.BaseThrottle):
- def allow_request(self, request, view):
- return random.randint(1, 10) == 1
-</code></pre>
- </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/api-guide/throttling/index.html b/api-guide/throttling/index.html
new file mode 100644
index 00000000..be4c727f
--- /dev/null
+++ b/api-guide/throttling/index.html
@@ -0,0 +1,604 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Throttling - 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/api-guide/throttling/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Throttling">
+ <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="../filtering">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../permissions">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#throttling">Throttling</a>
+ </li>
+
+
+ <li>
+ <a href="#how-throttling-is-determined">How throttling is determined</a>
+ </li>
+
+ <li>
+ <a href="#setting-the-throttling-policy">Setting the throttling policy</a>
+ </li>
+
+ <li>
+ <a href="#how-clients-are-identified">How clients are identified</a>
+ </li>
+
+ <li>
+ <a href="#setting-up-the-cache">Setting up the cache</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#anonratethrottle">AnonRateThrottle</a>
+ </li>
+
+ <li>
+ <a href="#userratethrottle">UserRateThrottle</a>
+ </li>
+
+ <li>
+ <a href="#scopedratethrottle">ScopedRateThrottle</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-throttles">Custom throttles</a>
+ </li>
+
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/throttling.py">
+ <span class="label label-info">throttling.py</span>
+ </a>
+
+
+
+ <h1 id="throttling">Throttling</h1>
+<blockquote>
+<p>HTTP/1.1 420 Enhance Your Calm</p>
+<p><a href="https://dev.twitter.com/docs/error-codes-responses">Twitter API rate limiting response</a></p>
+</blockquote>
+<p>Throttling is similar to <a href="../permissions">permissions</a>, in that it determines if a request should be authorized. Throttles indicate a temporary state, and are used to control the rate of requests that clients can make to an API.</p>
+<p>As with permissions, multiple throttles may be used. Your API might have a restrictive throttle for unauthenticated requests, and a less restrictive throttle for authenticated requests.</p>
+<p>Another scenario where you might want to use multiple throttles would be if you need to impose different constraints on different parts of the API, due to some services being particularly resource-intensive.</p>
+<p>Multiple throttles can also be used if you want to impose both burst throttling rates, and sustained throttling rates. For example, you might want to limit a user to a maximum of 60 requests per minute, and 1000 requests per day.</p>
+<p>Throttles do not necessarily only refer to rate-limiting requests. For example a storage service might also need to throttle against bandwidth, and a paid data service might want to throttle against a certain number of a records being accessed.</p>
+<h2 id="how-throttling-is-determined">How throttling is determined</h2>
+<p>As with permissions and authentication, throttling in REST framework is always defined as a list of classes.</p>
+<p>Before running the main body of the view each throttle in the list is checked.
+If any throttle check fails an <code>exceptions.Throttled</code> exception will be raised, and the main body of the view will not run.</p>
+<h2 id="setting-the-throttling-policy">Setting the throttling policy</h2>
+<p>The default throttling policy may be set globally, using the <code>DEFAULT_THROTTLE_CLASSES</code> and <code>DEFAULT_THROTTLE_RATES</code> settings. For example.</p>
+<pre><code>REST_FRAMEWORK = {
+ 'DEFAULT_THROTTLE_CLASSES': (
+ 'rest_framework.throttling.AnonRateThrottle',
+ 'rest_framework.throttling.UserRateThrottle'
+ ),
+ 'DEFAULT_THROTTLE_RATES': {
+ 'anon': '100/day',
+ 'user': '1000/day'
+ }
+}
+</code></pre>
+<p>The rate descriptions used in <code>DEFAULT_THROTTLE_RATES</code> may include <code>second</code>, <code>minute</code>, <code>hour</code> or <code>day</code> as the throttle period.</p>
+<p>You can also set the throttling policy on a per-view or per-viewset basis,
+using the <code>APIView</code> class based views.</p>
+<pre><code>from rest_framework.response import Response
+from rest_framework.throttling import UserRateThrottle
+from rest_framework.views import APIView
+
+class ExampleView(APIView):
+ throttle_classes = (UserRateThrottle,)
+
+ def get(self, request, format=None):
+ content = {
+ 'status': 'request was permitted'
+ }
+ return Response(content)
+</code></pre>
+<p>Or, if you're using the <code>@api_view</code> decorator with function based views.</p>
+<pre><code>@api_view(['GET'])
+@throttle_classes([UserRateThrottle])
+def example_view(request, format=None):
+ content = {
+ 'status': 'request was permitted'
+ }
+ return Response(content)
+</code></pre>
+<h2 id="how-clients-are-identified">How clients are identified</h2>
+<p>The <code>X-Forwarded-For</code> and <code>Remote-Addr</code> HTTP headers are used to uniquely identify client IP addresses for throttling. If the <code>X-Forwarded-For</code> header is present then it will be used, otherwise the value of the <code>Remote-Addr</code> header will be used.</p>
+<p>If you need to strictly identify unique client IP addresses, you'll need to first configure the number of application proxies that the API runs behind by setting the <code>NUM_PROXIES</code> setting. This setting should be an integer of zero or more. If set to non-zero then the client IP will be identified as being the last IP address in the <code>X-Forwarded-For</code> header, once any application proxy IP addresses have first been excluded. If set to zero, then the <code>Remote-Addr</code> header will always be used as the identifying IP address.</p>
+<p>It is important to understand that if you configure the <code>NUM_PROXIES</code> setting, then all clients behind a unique <a href="http://en.wikipedia.org/wiki/Network_address_translation">NAT'd</a> gateway will be treated as a single client.</p>
+<p>Further context on how the <code>X-Forwarded-For</code> header works, and identifying a remote client IP can be <a href="http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster">found here</a>.</p>
+<h2 id="setting-up-the-cache">Setting up the cache</h2>
+<p>The throttle classes provided by REST framework use Django's cache backend. You should make sure that you've set appropriate <a href="https://docs.djangoproject.com/en/dev/ref/settings/#caches">cache settings</a>. The default value of <code>LocMemCache</code> backend should be okay for simple setups. See Django's <a href="https://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache">cache documentation</a> for more details.</p>
+<p>If you need to use a cache other than <code>'default'</code>, you can do so by creating a custom throttle class and setting the <code>cache</code> attribute. For example:</p>
+<pre><code>class CustomAnonRateThrottle(AnonRateThrottle):
+ cache = get_cache('alternate')
+</code></pre>
+<p>You'll need to remember to also set your custom throttle class in the <code>'DEFAULT_THROTTLE_CLASSES'</code> settings key, or using the <code>throttle_classes</code> view attribute.</p>
+<hr />
+<h1 id="api-reference">API Reference</h1>
+<h2 id="anonratethrottle">AnonRateThrottle</h2>
+<p>The <code>AnonRateThrottle</code> will only ever throttle unauthenticated users. The IP address of the incoming request is used to generate a unique key to throttle against.</p>
+<p>The allowed request rate is determined from one of the following (in order of preference).</p>
+<ul>
+<li>The <code>rate</code> property on the class, which may be provided by overriding <code>AnonRateThrottle</code> and setting the property.</li>
+<li>The <code>DEFAULT_THROTTLE_RATES['anon']</code> setting.</li>
+</ul>
+<p><code>AnonRateThrottle</code> is suitable if you want to restrict the rate of requests from unknown sources.</p>
+<h2 id="userratethrottle">UserRateThrottle</h2>
+<p>The <code>UserRateThrottle</code> will throttle users to a given rate of requests across the API. The user id is used to generate a unique key to throttle against. Unauthenticated requests will fall back to using the IP address of the incoming request to generate a unique key to throttle against.</p>
+<p>The allowed request rate is determined from one of the following (in order of preference).</p>
+<ul>
+<li>The <code>rate</code> property on the class, which may be provided by overriding <code>UserRateThrottle</code> and setting the property.</li>
+<li>The <code>DEFAULT_THROTTLE_RATES['user']</code> setting.</li>
+</ul>
+<p>An API may have multiple <code>UserRateThrottles</code> in place at the same time. To do so, override <code>UserRateThrottle</code> and set a unique "scope" for each class.</p>
+<p>For example, multiple user throttle rates could be implemented by using the following classes...</p>
+<pre><code>class BurstRateThrottle(UserRateThrottle):
+ scope = 'burst'
+
+class SustainedRateThrottle(UserRateThrottle):
+ scope = 'sustained'
+</code></pre>
+<p>...and the following settings.</p>
+<pre><code>REST_FRAMEWORK = {
+ 'DEFAULT_THROTTLE_CLASSES': (
+ 'example.throttles.BurstRateThrottle',
+ 'example.throttles.SustainedRateThrottle'
+ ),
+ 'DEFAULT_THROTTLE_RATES': {
+ 'burst': '60/min',
+ 'sustained': '1000/day'
+ }
+}
+</code></pre>
+<p><code>UserRateThrottle</code> is suitable if you want simple global rate restrictions per-user.</p>
+<h2 id="scopedratethrottle">ScopedRateThrottle</h2>
+<p>The <code>ScopedRateThrottle</code> class can be used to restrict access to specific parts of the API. This throttle will only be applied if the view that is being accessed includes a <code>.throttle_scope</code> property. The unique throttle key will then be formed by concatenating the "scope" of the request with the unique user id or IP address.</p>
+<p>The allowed request rate is determined by the <code>DEFAULT_THROTTLE_RATES</code> setting using a key from the request "scope".</p>
+<p>For example, given the following views...</p>
+<pre><code>class ContactListView(APIView):
+ throttle_scope = 'contacts'
+ ...
+
+class ContactDetailView(ApiView):
+ throttle_scope = 'contacts'
+ ...
+
+class UploadView(APIView):
+ throttle_scope = 'uploads'
+ ...
+</code></pre>
+<p>...and the following settings.</p>
+<pre><code>REST_FRAMEWORK = {
+ 'DEFAULT_THROTTLE_CLASSES': (
+ 'rest_framework.throttling.ScopedRateThrottle',
+ ),
+ 'DEFAULT_THROTTLE_RATES': {
+ 'contacts': '1000/day',
+ 'uploads': '20/day'
+ }
+}
+</code></pre>
+<p>User requests to either <code>ContactListView</code> or <code>ContactDetailView</code> would be restricted to a total of 1000 requests per-day. User requests to <code>UploadView</code> would be restricted to 20 requests per day.</p>
+<hr />
+<h1 id="custom-throttles">Custom throttles</h1>
+<p>To create a custom throttle, override <code>BaseThrottle</code> and implement <code>.allow_request(self, request, view)</code>. The method should return <code>True</code> if the request should be allowed, and <code>False</code> otherwise.</p>
+<p>Optionally you may also override the <code>.wait()</code> method. If implemented, <code>.wait()</code> should return a recommended number of seconds to wait before attempting the next request, or <code>None</code>. The <code>.wait()</code> method will only be called if <code>.allow_request()</code> has previously returned <code>False</code>.</p>
+<p>If the <code>.wait()</code> method is implemented and the request is throttled, then a <code>Retry-After</code> header will be included in the response.</p>
+<h2 id="example">Example</h2>
+<p>The following is an example of a rate throttle, that will randomly throttle 1 in every 10 requests.</p>
+<pre><code>class RandomRateThrottle(throttles.BaseThrottle):
+ def allow_request(self, request, view):
+ return random.randint(1, 10) == 1
+</code></pre>
+
+ </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/api-guide/validators.html b/api-guide/validators.html
deleted file mode 100644
index de19736e..00000000
--- a/api-guide/validators.html
+++ /dev/null
@@ -1,388 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Validators - 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//api-guide/validators.html"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Validators, Writing custom validators">
- <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="validators-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="../api-guide/authentication.html">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/relations.html"><i class="icon-arrow-left icon-white"></i> Previous</a>
- <a class="repo-link btn btn-inverse btn-small" href="#searchModal" data-toggle="modal"><i class="icon-search icon-white"></i> Search</a>
- <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- </a>
- <a class="brand" href="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 class="main"><a href="#validators">Validators</a></li>
-<li><a href="#uniquevalidator">UniqueValidator</a></li>
-<li><a href="#uniquefordatevalidator">UniqueForDateValidator</a></li>
-<li><a href="#uniqueformonthvalidator">UniqueForMonthValidator</a></li>
-<li><a href="#uniqueforyearvalidator">UniqueForYearValidator</a></li>
-<li class="main"><a href="#writing-custom-validators">Writing custom validators</a></li>
-<li><a href="#function-based">Function based</a></li>
-<li><a href="#class-based">Class based</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/validators.py"><span class="label label-info">validators.py</span></a></p>
-<h1 id="validators">Validators</h1>
-<blockquote>
-<p>Validators can be useful for re-using validation logic between different types of fields.</p>
-<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/validators/">Django documentation</a></p>
-</blockquote>
-<p>Most of the time you're dealing with validation in REST framework you'll simply be relying on the default field validation, or writing explicit validation methods on serializer or field classes.</p>
-<p>Sometimes you'll want to place your validation logic into reusable components, so that it can easily be reused throughout your codebase. This can be achieved by using validator functions and validator classes.</p>
-<h2 id="validation-in-rest-framework">Validation in REST framework</h2>
-<p>Validation in Django REST framework serializers is handled a little differently to how validation works in Django's <code>ModelForm</code> class.</p>
-<p>With <code>ModelForm</code> the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class. This is advantageous for the following reasons:</p>
-<ul>
-<li>It introduces a proper separation of concerns, making your code behaviour more obvious.</li>
-<li>It is easy to switch between using shortcut <code>ModelSerializer</code> classes and using explicit <code>Serializer</code> classes. Any validation behaviour being used for <code>ModelSerializer</code> is simple to replicate.</li>
-<li>Printing the <code>repr</code> of a serializer instance will show you exactly what validation rules it applies. There's no extra hidden validation behaviour being called on the model instance.</li>
-</ul>
-<p>When you're using <code>ModelSerializer</code> all of this is handled automatically for you. If you want to drop down to using a <code>Serializer</code> classes instead, then you need to define the validation rules explicitly.</p>
-<h4 id="example">Example</h4>
-<p>As an example of how REST framework uses explicit validation, we'll take a simple model class that has a field with a uniqueness constraint.</p>
-<pre class="prettyprint lang-py"><code>class CustomerReportRecord(models.Model):
- time_raised = models.DateTimeField(default=timezone.now, editable=False)
- reference = models.CharField(unique=True, max_length=20)
- description = models.TextField()
-</code></pre>
-<p>Here's a basic <code>ModelSerializer</code> that we can use for creating or updating instances of <code>CustomerReportRecord</code>:</p>
-<pre class="prettyprint lang-py"><code>class CustomerReportSerializer(serializers.ModelSerializer):
- class Meta:
- model = CustomerReportRecord
-</code></pre>
-<p>If we open up the Django shell using <code>manage.py shell</code> we can now </p>
-<pre class="prettyprint lang-py"><code>&gt;&gt;&gt; from project.example.serializers import CustomerReportSerializer
-&gt;&gt;&gt; serializer = CustomerReportSerializer()
-&gt;&gt;&gt; print(repr(serializer))
-CustomerReportSerializer():
- id = IntegerField(label='ID', read_only=True)
- time_raised = DateTimeField(read_only=True)
- reference = CharField(max_length=20, validators=[&lt;UniqueValidator(queryset=CustomerReportRecord.objects.all())&gt;])
- description = CharField(style={'type': 'textarea'})
-</code></pre>
-<p>The interesting bit here is the <code>reference</code> field. We can see that the uniqueness constraint is being explicitly enforced by a validator on the serializer field.</p>
-<p>Because of this more explicit style REST framework includes a few validator classes that are not available in core Django. These classes are detailed below.</p>
-<hr />
-<h2 id="uniquevalidator">UniqueValidator</h2>
-<p>This validator can be used to enforce the <code>unique=True</code> constraint on model fields.
-It takes a single required argument, and an optional <code>messages</code> argument:</p>
-<ul>
-<li><code>queryset</code> <em>required</em> - This is the queryset against which uniqueness should be enforced.</li>
-<li><code>message</code> - The error message that should be used when validation fails.</li>
-</ul>
-<p>This validator should be applied to <em>serializer fields</em>, like so:</p>
-<pre class="prettyprint lang-py"><code>slug = SlugField(
- max_length=100,
- validators=[UniqueValidator(queryset=BlogPost.objects.all())]
-)
-</code></pre>
-<h2 id="uniquetogethervalidator">UniqueTogetherValidator</h2>
-<p>This validator can be used to enforce <code>unique_together</code> constraints on model instances.
-It has two required arguments, and a single optional <code>messages</code> argument:</p>
-<ul>
-<li><code>queryset</code> <em>required</em> - This is the queryset against which uniqueness should be enforced.</li>
-<li><code>fields</code> <em>required</em> - A list or tuple of field names which should make a unique set. These must exist as fields on the serializer class.</li>
-<li><code>message</code> - The error message that should be used when validation fails.</li>
-</ul>
-<p>The validator should be applied to <em>serializer classes</em>, like so:</p>
-<pre class="prettyprint lang-py"><code>class ExampleSerializer(serializers.Serializer):
- # ...
- class Meta:
- # ToDo items belong to a parent list, and have an ordering defined
- # by the 'position' field. No two items in a given list may share
- # the same position.
- validators = [
- UniqueTogetherValidator(
- queryset=ToDoItem.objects.all(),
- fields=('list', 'position')
- )
- ]
-</code></pre>
-<h2 id="uniquefordatevalidator">UniqueForDateValidator</h2>
-<h2 id="uniqueformonthvalidator">UniqueForMonthValidator</h2>
-<h2 id="uniqueforyearvalidator">UniqueForYearValidator</h2>
-<p>These validators can be used to enforce the <code>unique_for_date</code>, <code>unique_for_month</code> and <code>unique_for_year</code> constraints on model instances. They take the following arguments:</p>
-<ul>
-<li><code>queryset</code> <em>required</em> - This is the queryset against which uniqueness should be enforced.</li>
-<li><code>field</code> <em>required</em> - A field name against which uniqueness in the given date range will be validated. This must exist as a field on the serializer class.</li>
-<li><code>date_field</code> <em>required</em> - A field name which will be used to determine date range for the uniqueness constrain. This must exist as a field on the serializer class.</li>
-<li><code>message</code> - The error message that should be used when validation fails.</li>
-</ul>
-<p>The validator should be applied to <em>serializer classes</em>, like so:</p>
-<pre class="prettyprint lang-py"><code>class ExampleSerializer(serializers.Serializer):
- # ...
- class Meta:
- # Blog posts should have a slug that is unique for the current year.
- validators = [
- UniqueForYearValidator(
- queryset=BlogPostItem.objects.all(),
- field='slug',
- date_field='published'
- )
- ]
-</code></pre>
-<p>The date field that is used for the validation is always required to be present on the serializer class. You can't simply rely on a model class <code>default=...</code>, because the value being used for the default wouldn't be generated until after the validation has run.</p>
-<p>There are a couple of styles you may want to use for this depending on how you want your API to behave. If you're using <code>ModelSerializer</code> you'll probably simply rely on the defaults that REST framework generates for you, but if you are using <code>Serializer</code> or simply want more explicit control, use on of the styles demonstrated below.</p>
-<h4 id="using-with-a-writable-date-field">Using with a writable date field.</h4>
-<p>If you want the date field to be writable the only thing worth noting is that you should ensure that it is always available in the input data, either by setting a <code>default</code> argument, or by setting <code>required=True</code>.</p>
-<pre class="prettyprint lang-py"><code>published = serializers.DateTimeField(required=True)
-</code></pre>
-<h4 id="using-with-a-read-only-date-field">Using with a read-only date field.</h4>
-<p>If you want the date field to be visible, but not editable by the user, then set <code>read_only=True</code> and additionally set a <code>default=...</code> argument.</p>
-<pre class="prettyprint lang-py"><code>published = serializers.DateTimeField(read_only=True, default=timezone.now)
-</code></pre>
-<p>The field will not be writable to the user, but the default value will still be passed through to the <code>validated_data</code>.</p>
-<h4 id="using-with-a-hidden-date-field">Using with a hidden date field.</h4>
-<p>If you want the date field to be entirely hidden from the user, then use <code>HiddenField</code>. This field type does not accept user input, but instead always returns it's default value to the <code>validated_data</code> in the serializer.</p>
-<pre class="prettyprint lang-py"><code>published = serializers.HiddenField(default=timezone.now)
-</code></pre>
-<hr />
-<h1 id="writing-custom-validators">Writing custom validators</h1>
-<p>You can use any of Django's existing validators, or write your own custom validators.</p>
-<h2 id="function-based">Function based</h2>
-<p>A validator may be any callable that raises a <code>serializers.ValidationError</code> on failure.</p>
-<pre class="prettyprint lang-py"><code>def even_number(value):
- if value % 2 != 0:
- raise serializers.ValidationError('This field must be an even number.')
-</code></pre>
-<h2 id="class-based">Class based</h2>
-<p>To write a class based validator, use the <code>__call__</code> method. Class based validators are useful as they allow you to parameterize and reuse behavior.</p>
-<pre class="prettyprint lang-py"><code>class MultipleOf:
- def __init__(self, base):
- self.base = base
-
- def __call__(self, value):
- if value % self.base != 0
- message = 'This field must be a multiple of %d.' % self.base
- raise serializers.ValidationError(message)
-</code></pre>
-<h4 id="using-set_context">Using <code>set_context()</code></h4>
-<p>In some advanced cases you might want a validator to be passed the serializer field it is being used with as additional context. You can do so by declaring a <code>set_context</code> method on a class based validator.</p>
-<pre class="prettyprint lang-py"><code>def set_context(self, serializer_field):
- # Determine if this is an update or a create operation.
- # In `__call__` we can then use that information to modify the validation behavior.
- self.is_update = serializer_field.parent.instance is not None
-</code></pre>
- </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/api-guide/validators/index.html b/api-guide/validators/index.html
new file mode 100644
index 00000000..7d75da1f
--- /dev/null
+++ b/api-guide/validators/index.html
@@ -0,0 +1,635 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Validators - 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/api-guide/validators/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Validators">
+ <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="../authentication">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../relations">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#validators">Validators</a>
+ </li>
+
+
+ <li>
+ <a href="#validation-in-rest-framework">Validation in REST framework</a>
+ </li>
+
+ <li>
+ <a href="#uniquevalidator">UniqueValidator</a>
+ </li>
+
+ <li>
+ <a href="#uniquetogethervalidator">UniqueTogetherValidator</a>
+ </li>
+
+ <li>
+ <a href="#uniquefordatevalidator">UniqueForDateValidator</a>
+ </li>
+
+ <li>
+ <a href="#uniqueformonthvalidator">UniqueForMonthValidator</a>
+ </li>
+
+ <li>
+ <a href="#uniqueforyearvalidator">UniqueForYearValidator</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#advanced-default-argument-usage">Advanced 'default' argument usage</a>
+ </li>
+
+
+ <li>
+ <a href="#currentuserdefault">CurrentUserDefault</a>
+ </li>
+
+ <li>
+ <a href="#createonlydefault">CreateOnlyDefault</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#writing-custom-validators">Writing custom validators</a>
+ </li>
+
+
+ <li>
+ <a href="#function-based">Function based</a>
+ </li>
+
+ <li>
+ <a href="#class-based">Class based</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <p><a class="github" href="validators.py"></a></p>
+<h1 id="validators">Validators</h1>
+<blockquote>
+<p>Validators can be useful for re-using validation logic between different types of fields.</p>
+<p>&mdash; <a href="https://docs.djangoproject.com/en/dev/ref/validators/">Django documentation</a></p>
+</blockquote>
+<p>Most of the time you're dealing with validation in REST framework you'll simply be relying on the default field validation, or writing explicit validation methods on serializer or field classes.</p>
+<p>However, sometimes you'll want to place your validation logic into reusable components, so that it can easily be reused throughout your codebase. This can be achieved by using validator functions and validator classes.</p>
+<h2 id="validation-in-rest-framework">Validation in REST framework</h2>
+<p>Validation in Django REST framework serializers is handled a little differently to how validation works in Django's <code>ModelForm</code> class.</p>
+<p>With <code>ModelForm</code> the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class. This is advantageous for the following reasons:</p>
+<ul>
+<li>It introduces a proper separation of concerns, making your code behavior more obvious.</li>
+<li>It is easy to switch between using shortcut <code>ModelSerializer</code> classes and using explicit <code>Serializer</code> classes. Any validation behavior being used for <code>ModelSerializer</code> is simple to replicate.</li>
+<li>Printing the <code>repr</code> of a serializer instance will show you exactly what validation rules it applies. There's no extra hidden validation behavior being called on the model instance.</li>
+</ul>
+<p>When you're using <code>ModelSerializer</code> all of this is handled automatically for you. If you want to drop down to using a <code>Serializer</code> classes instead, then you need to define the validation rules explicitly.</p>
+<h4 id="example">Example</h4>
+<p>As an example of how REST framework uses explicit validation, we'll take a simple model class that has a field with a uniqueness constraint.</p>
+<pre><code>class CustomerReportRecord(models.Model):
+ time_raised = models.DateTimeField(default=timezone.now, editable=False)
+ reference = models.CharField(unique=True, max_length=20)
+ description = models.TextField()
+</code></pre>
+<p>Here's a basic <code>ModelSerializer</code> that we can use for creating or updating instances of <code>CustomerReportRecord</code>:</p>
+<pre><code>class CustomerReportSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = CustomerReportRecord
+</code></pre>
+<p>If we open up the Django shell using <code>manage.py shell</code> we can now </p>
+<pre><code>&gt;&gt;&gt; from project.example.serializers import CustomerReportSerializer
+&gt;&gt;&gt; serializer = CustomerReportSerializer()
+&gt;&gt;&gt; print(repr(serializer))
+CustomerReportSerializer():
+ id = IntegerField(label='ID', read_only=True)
+ time_raised = DateTimeField(read_only=True)
+ reference = CharField(max_length=20, validators=[&lt;UniqueValidator(queryset=CustomerReportRecord.objects.all())&gt;])
+ description = CharField(style={'type': 'textarea'})
+</code></pre>
+<p>The interesting bit here is the <code>reference</code> field. We can see that the uniqueness constraint is being explicitly enforced by a validator on the serializer field.</p>
+<p>Because of this more explicit style REST framework includes a few validator classes that are not available in core Django. These classes are detailed below.</p>
+<hr />
+<h2 id="uniquevalidator">UniqueValidator</h2>
+<p>This validator can be used to enforce the <code>unique=True</code> constraint on model fields.
+It takes a single required argument, and an optional <code>messages</code> argument:</p>
+<ul>
+<li><code>queryset</code> <em>required</em> - This is the queryset against which uniqueness should be enforced.</li>
+<li><code>message</code> - The error message that should be used when validation fails.</li>
+</ul>
+<p>This validator should be applied to <em>serializer fields</em>, like so:</p>
+<pre><code>slug = SlugField(
+ max_length=100,
+ validators=[UniqueValidator(queryset=BlogPost.objects.all())]
+)
+</code></pre>
+<h2 id="uniquetogethervalidator">UniqueTogetherValidator</h2>
+<p>This validator can be used to enforce <code>unique_together</code> constraints on model instances.
+It has two required arguments, and a single optional <code>messages</code> argument:</p>
+<ul>
+<li><code>queryset</code> <em>required</em> - This is the queryset against which uniqueness should be enforced.</li>
+<li><code>fields</code> <em>required</em> - A list or tuple of field names which should make a unique set. These must exist as fields on the serializer class.</li>
+<li><code>message</code> - The error message that should be used when validation fails.</li>
+</ul>
+<p>The validator should be applied to <em>serializer classes</em>, like so:</p>
+<pre><code>class ExampleSerializer(serializers.Serializer):
+ # ...
+ class Meta:
+ # ToDo items belong to a parent list, and have an ordering defined
+ # by the 'position' field. No two items in a given list may share
+ # the same position.
+ validators = [
+ UniqueTogetherValidator(
+ queryset=ToDoItem.objects.all(),
+ fields=('list', 'position')
+ )
+ ]
+</code></pre>
+<hr />
+<p><strong>Note</strong>: The <code>UniqueTogetherValidation</code> class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with <code>default</code> values are an exception to this as they always supply a value even when omitted from user input.</p>
+<hr />
+<h2 id="uniquefordatevalidator">UniqueForDateValidator</h2>
+<h2 id="uniqueformonthvalidator">UniqueForMonthValidator</h2>
+<h2 id="uniqueforyearvalidator">UniqueForYearValidator</h2>
+<p>These validators can be used to enforce the <code>unique_for_date</code>, <code>unique_for_month</code> and <code>unique_for_year</code> constraints on model instances. They take the following arguments:</p>
+<ul>
+<li><code>queryset</code> <em>required</em> - This is the queryset against which uniqueness should be enforced.</li>
+<li><code>field</code> <em>required</em> - A field name against which uniqueness in the given date range will be validated. This must exist as a field on the serializer class.</li>
+<li><code>date_field</code> <em>required</em> - A field name which will be used to determine date range for the uniqueness constrain. This must exist as a field on the serializer class.</li>
+<li><code>message</code> - The error message that should be used when validation fails.</li>
+</ul>
+<p>The validator should be applied to <em>serializer classes</em>, like so:</p>
+<pre><code>class ExampleSerializer(serializers.Serializer):
+ # ...
+ class Meta:
+ # Blog posts should have a slug that is unique for the current year.
+ validators = [
+ UniqueForYearValidator(
+ queryset=BlogPostItem.objects.all(),
+ field='slug',
+ date_field='published'
+ )
+ ]
+</code></pre>
+<p>The date field that is used for the validation is always required to be present on the serializer class. You can't simply rely on a model class <code>default=...</code>, because the value being used for the default wouldn't be generated until after the validation has run.</p>
+<p>There are a couple of styles you may want to use for this depending on how you want your API to behave. If you're using <code>ModelSerializer</code> you'll probably simply rely on the defaults that REST framework generates for you, but if you are using <code>Serializer</code> or simply want more explicit control, use on of the styles demonstrated below.</p>
+<h4 id="using-with-a-writable-date-field">Using with a writable date field.</h4>
+<p>If you want the date field to be writable the only thing worth noting is that you should ensure that it is always available in the input data, either by setting a <code>default</code> argument, or by setting <code>required=True</code>.</p>
+<pre><code>published = serializers.DateTimeField(required=True)
+</code></pre>
+<h4 id="using-with-a-read-only-date-field">Using with a read-only date field.</h4>
+<p>If you want the date field to be visible, but not editable by the user, then set <code>read_only=True</code> and additionally set a <code>default=...</code> argument.</p>
+<pre><code>published = serializers.DateTimeField(read_only=True, default=timezone.now)
+</code></pre>
+<p>The field will not be writable to the user, but the default value will still be passed through to the <code>validated_data</code>.</p>
+<h4 id="using-with-a-hidden-date-field">Using with a hidden date field.</h4>
+<p>If you want the date field to be entirely hidden from the user, then use <code>HiddenField</code>. This field type does not accept user input, but instead always returns it's default value to the <code>validated_data</code> in the serializer.</p>
+<pre><code>published = serializers.HiddenField(default=timezone.now)
+</code></pre>
+<hr />
+<p><strong>Note</strong>: The <code>UniqueFor&lt;Range&gt;Validation</code> classes always imposes an implicit constraint that the fields they are applied to are always treated as required. Fields with <code>default</code> values are an exception to this as they always supply a value even when omitted from user input.</p>
+<hr />
+<h1 id="advanced-default-argument-usage">Advanced 'default' argument usage</h1>
+<p>Validators that are applied across multiple fields in the serializer can sometimes require a field input that should not be provided by the API client, but that <em>is</em> available as input to the validator.</p>
+<p>Two patterns that you may want to use for this sort of validation include:</p>
+<ul>
+<li>Using <code>HiddenField</code>. This field will be present in <code>validated_data</code> but <em>will not</em> be used in the serializer output representation.</li>
+<li>Using a standard field with <code>read_only=True</code>, but that also includes a <code>default=…</code> argument. This field <em>will</em> be used in the serializer output representation, but cannot be set directly by the user.</li>
+</ul>
+<p>REST framework includes a couple of defaults that may be useful in this context.</p>
+<h4 id="currentuserdefault">CurrentUserDefault</h4>
+<p>A default class that can be used to represent the current user. In order to use this, the 'request' must have been provided as part of the context dictionary when instantiating the serializer.</p>
+<pre><code>owner = serializers.HiddenField(
+ default=CurrentUserDefault()
+)
+</code></pre>
+<h4 id="createonlydefault">CreateOnlyDefault</h4>
+<p>A default class that can be used to <em>only set a default argument during create operations</em>. During updates the field is omitted.</p>
+<p>It takes a single argument, which is the default value or callable that should be used during create operations.</p>
+<pre><code>created_at = serializers.DateTimeField(
+ read_only=True,
+ default=CreateOnlyDefault(timezone.now)
+)
+</code></pre>
+<hr />
+<h1 id="writing-custom-validators">Writing custom validators</h1>
+<p>You can use any of Django's existing validators, or write your own custom validators.</p>
+<h2 id="function-based">Function based</h2>
+<p>A validator may be any callable that raises a <code>serializers.ValidationError</code> on failure.</p>
+<pre><code>def even_number(value):
+ if value % 2 != 0:
+ raise serializers.ValidationError('This field must be an even number.')
+</code></pre>
+<h2 id="class-based">Class based</h2>
+<p>To write a class based validator, use the <code>__call__</code> method. Class based validators are useful as they allow you to parameterize and reuse behavior.</p>
+<pre><code>class MultipleOf:
+ def __init__(self, base):
+ self.base = base
+
+ def __call__(self, value):
+ if value % self.base != 0
+ message = 'This field must be a multiple of %d.' % self.base
+ raise serializers.ValidationError(message)
+</code></pre>
+<h4 id="using-set_context">Using <code>set_context()</code></h4>
+<p>In some advanced cases you might want a validator to be passed the serializer field it is being used with as additional context. You can do so by declaring a <code>set_context</code> method on a class based validator.</p>
+<pre><code>def set_context(self, serializer_field):
+ # Determine if this is an update or a create operation.
+ # In `__call__` we can then use that information to modify the validation behavior.
+ self.is_update = serializer_field.parent.instance is not None
+</code></pre>
+
+ </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/api-guide/views.html b/api-guide/views.html
deleted file mode 100644
index ef7db67e..00000000
--- a/api-guide/views.html
+++ /dev/null
@@ -1,360 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Class Based Views - 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/api-guide/views"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, Class Based Views, Function Based Views">
- <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="views-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="../api-guide/generic-views">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/responses"><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="#class-based-views">Class Based Views</a></li>
-<li><a href="#api-policy-attributes">API policy attributes</a></li>
-<li><a href="#api-policy-instantiation-methods">API policy instantiation methods</a></li>
-<li><a href="#api-policy-implementation-methods">API policy implementation methods</a></li>
-<li><a href="#dispatch-methods">Dispatch methods</a></li>
-<li class="main"><a href="#function-based-views">Function Based Views</a></li>
-<li><a href="#@api_view()">@api_view()</a></li>
-<li><a href="#api-policy-decorators">API policy decorators</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/decorators.py"><span class="label label-info">decorators.py</span></a> <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/views.py"><span class="label label-info">views.py</span></a></p>
-<h1 id="class-based-views">Class Based Views</h1>
-<blockquote>
-<p>Django's class based views are a welcome departure from the old-style views.</p>
-<p>&mdash; <a href="http://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html">Reinout van Rees</a></p>
-</blockquote>
-<p>REST framework provides an <code>APIView</code> class, which subclasses Django's <code>View</code> class.</p>
-<p><code>APIView</code> classes are different from regular <code>View</code> classes in the following ways:</p>
-<ul>
-<li>Requests passed to the handler methods will be REST framework's <code>Request</code> instances, not Django's <code>HttpRequest</code> instances.</li>
-<li>Handler methods may return REST framework's <code>Response</code>, instead of Django's <code>HttpResponse</code>. The view will manage content negotiation and setting the correct renderer on the response.</li>
-<li>Any <code>APIException</code> exceptions will be caught and mediated into appropriate responses.</li>
-<li>Incoming requests will be authenticated and appropriate permission and/or throttle checks will be run before dispatching the request to the handler method.</li>
-</ul>
-<p>Using the <code>APIView</code> class is pretty much the same as using a regular <code>View</code> class, as usual, the incoming request is dispatched to an appropriate handler method such as <code>.get()</code> or <code>.post()</code>. Additionally, a number of attributes may be set on the class that control various aspects of the API policy.</p>
-<p>For example:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.views import APIView
-from rest_framework.response import Response
-from rest_framework import authentication, permissions
-
-class ListUsers(APIView):
- """
- View to list all users in the system.
-
- * Requires token authentication.
- * Only admin users are able to access this view.
- """
- authentication_classes = (authentication.TokenAuthentication,)
- permission_classes = (permissions.IsAdminUser,)
-
- def get(self, request, format=None):
- """
- Return a list of all users.
- """
- usernames = [user.username for user in User.objects.all()]
- return Response(usernames)
-</code></pre>
-<h2 id="api-policy-attributes">API policy attributes</h2>
-<p>The following attributes control the pluggable aspects of API views.</p>
-<h3 id="renderer_classes">.renderer_classes</h3>
-<h3 id="parser_classes">.parser_classes</h3>
-<h3 id="authentication_classes">.authentication_classes</h3>
-<h3 id="throttle_classes">.throttle_classes</h3>
-<h3 id="permission_classes">.permission_classes</h3>
-<h3 id="content_negotiation_class">.content_negotiation_class</h3>
-<h2 id="api-policy-instantiation-methods">API policy instantiation methods</h2>
-<p>The following methods are used by REST framework to instantiate the various pluggable API policies. You won't typically need to override these methods.</p>
-<h3 id="get_renderersself">.get_renderers(self)</h3>
-<h3 id="get_parsersself">.get_parsers(self)</h3>
-<h3 id="get_authenticatorsself">.get_authenticators(self)</h3>
-<h3 id="get_throttlesself">.get_throttles(self)</h3>
-<h3 id="get_permissionsself">.get_permissions(self)</h3>
-<h3 id="get_content_negotiatorself">.get_content_negotiator(self)</h3>
-<h2 id="api-policy-implementation-methods">API policy implementation methods</h2>
-<p>The following methods are called before dispatching to the handler method.</p>
-<h3 id="check_permissionsself-request">.check_permissions(self, request)</h3>
-<h3 id="check_throttlesself-request">.check_throttles(self, request)</h3>
-<h3 id="perform_content_negotiationself-request-forcefalse">.perform_content_negotiation(self, request, force=False)</h3>
-<h2 id="dispatch-methods">Dispatch methods</h2>
-<p>The following methods are called directly by the view's <code>.dispatch()</code> method.
-These perform any actions that need to occur before or after calling the handler methods such as <code>.get()</code>, <code>.post()</code>, <code>put()</code>, <code>patch()</code> and <code>.delete()</code>.</p>
-<h3 id="initialself-request-42args-kwargs">.initial(self, request, *args, **kwargs)</h3>
-<p>Performs any actions that need to occur before the handler method gets called.
-This method is used to enforce permissions and throttling, and perform content negotiation.</p>
-<p>You won't typically need to override this method.</p>
-<h3 id="handle_exceptionself-exc">.handle_exception(self, exc)</h3>
-<p>Any exception thrown by the handler method will be passed to this method, which either returns a <code>Response</code> instance, or re-raises the exception.</p>
-<p>The default implementation handles any subclass of <code>rest_framework.exceptions.APIException</code>, as well as Django's <code>Http404</code> and <code>PermissionDenied</code> exceptions, and returns an appropriate error response.</p>
-<p>If you need to customize the error responses your API returns you should subclass this method.</p>
-<h3 id="initialize_requestself-request-42args-kwargs">.initialize_request(self, request, *args, **kwargs)</h3>
-<p>Ensures that the request object that is passed to the handler method is an instance of <code>Request</code>, rather than the usual Django <code>HttpRequest</code>.</p>
-<p>You won't typically need to override this method.</p>
-<h3 id="finalize_responseself-request-response-42args-kwargs">.finalize_response(self, request, response, *args, **kwargs)</h3>
-<p>Ensures that any <code>Response</code> object returned from the handler method will be rendered into the correct content type, as determined by the content negotiation.</p>
-<p>You won't typically need to override this method.</p>
-<hr />
-<h1 id="function-based-views">Function Based Views</h1>
-<blockquote>
-<p>Saying [that Class based views] is always the superior solution is a mistake.</p>
-<p>&mdash; <a href="http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html">Nick Coghlan</a></p>
-</blockquote>
-<p>REST framework also allows you to work with regular function based views. It provides a set of simple decorators that wrap your function based views to ensure they receive an instance of <code>Request</code> (rather than the usual Django <code>HttpRequest</code>) and allows them to return a <code>Response</code> (instead of a Django <code>HttpResponse</code>), and allow you to configure how the request is processed.</p>
-<h2 id="api_view">@api_view()</h2>
-<p><strong>Signature:</strong> <code>@api_view(http_method_names)</code></p>
-<p>The core of this functionality is the <code>api_view</code> decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.decorators import api_view
-
-@api_view(['GET'])
-def hello_world(request):
- return Response({"message": "Hello, world!"})
-</code></pre>
-<p>This view will use the default renderers, parsers, authentication classes etc specified in the <a href="settings">settings</a>.</p>
-<h2 id="api-policy-decorators">API policy decorators</h2>
-<p>To override the default settings, REST framework provides a set of additional decorators which can be added to your views. These must come <em>after</em> (below) the <code>@api_view</code> decorator. For example, to create a view that uses a <a href="throttling">throttle</a> to ensure it can only be called once per day by a particular user, use the <code>@throttle_classes</code> decorator, passing a list of throttle classes:</p>
-<pre class="prettyprint lang-py"><code>from rest_framework.decorators import api_view, throttle_classes
-from rest_framework.throttling import UserRateThrottle
-
-class OncePerDayUserThrottle(UserRateThrottle):
- rate = '1/day'
-
-@api_view(['GET'])
-@throttle_classes([OncePerDayUserThrottle])
-def view(request):
- return Response({"message": "Hello for today! See you tomorrow!"})
-</code></pre>
-<p>These decorators correspond to the attributes set on <code>APIView</code> subclasses, described above.</p>
-<p>The available decorators are:</p>
-<ul>
-<li><code>@renderer_classes(...)</code></li>
-<li><code>@parser_classes(...)</code></li>
-<li><code>@authentication_classes(...)</code></li>
-<li><code>@throttle_classes(...)</code></li>
-<li><code>@permission_classes(...)</code></li>
-</ul>
-<p>Each of these decorators takes a single argument which must be a list or tuple of classes.</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/api-guide/views/index.html b/api-guide/views/index.html
new file mode 100644
index 00000000..daec3039
--- /dev/null
+++ b/api-guide/views/index.html
@@ -0,0 +1,565 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Views - 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/api-guide/views/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Views">
+ <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="../generic-views">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../responses">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li >
+ <a href="../viewsets">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#class-based-views">Class Based Views</a>
+ </li>
+
+
+ <li>
+ <a href="#api-policy-attributes">API policy attributes</a>
+ </li>
+
+ <li>
+ <a href="#api-policy-instantiation-methods">API policy instantiation methods</a>
+ </li>
+
+ <li>
+ <a href="#api-policy-implementation-methods">API policy implementation methods</a>
+ </li>
+
+ <li>
+ <a href="#dispatch-methods">Dispatch methods</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#function-based-views">Function Based Views</a>
+ </li>
+
+
+ <li>
+ <a href="#api_view">@api_view()</a>
+ </li>
+
+ <li>
+ <a href="#api-policy-decorators">API policy decorators</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/decorators.py">
+ <span class="label label-info">decorators.py</span>
+ </a>
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/views.py">
+ <span class="label label-info">views.py</span>
+ </a>
+
+
+
+ <h1 id="class-based-views">Class Based Views</h1>
+<blockquote>
+<p>Django's class based views are a welcome departure from the old-style views.</p>
+<p>&mdash; <a href="http://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html">Reinout van Rees</a></p>
+</blockquote>
+<p>REST framework provides an <code>APIView</code> class, which subclasses Django's <code>View</code> class.</p>
+<p><code>APIView</code> classes are different from regular <code>View</code> classes in the following ways:</p>
+<ul>
+<li>Requests passed to the handler methods will be REST framework's <code>Request</code> instances, not Django's <code>HttpRequest</code> instances.</li>
+<li>Handler methods may return REST framework's <code>Response</code>, instead of Django's <code>HttpResponse</code>. The view will manage content negotiation and setting the correct renderer on the response.</li>
+<li>Any <code>APIException</code> exceptions will be caught and mediated into appropriate responses.</li>
+<li>Incoming requests will be authenticated and appropriate permission and/or throttle checks will be run before dispatching the request to the handler method.</li>
+</ul>
+<p>Using the <code>APIView</code> class is pretty much the same as using a regular <code>View</code> class, as usual, the incoming request is dispatched to an appropriate handler method such as <code>.get()</code> or <code>.post()</code>. Additionally, a number of attributes may be set on the class that control various aspects of the API policy.</p>
+<p>For example:</p>
+<pre><code>from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import authentication, permissions
+
+class ListUsers(APIView):
+ """
+ View to list all users in the system.
+
+ * Requires token authentication.
+ * Only admin users are able to access this view.
+ """
+ authentication_classes = (authentication.TokenAuthentication,)
+ permission_classes = (permissions.IsAdminUser,)
+
+ def get(self, request, format=None):
+ """
+ Return a list of all users.
+ """
+ usernames = [user.username for user in User.objects.all()]
+ return Response(usernames)
+</code></pre>
+<h2 id="api-policy-attributes">API policy attributes</h2>
+<p>The following attributes control the pluggable aspects of API views.</p>
+<h3 id="renderer_classes">.renderer_classes</h3>
+<h3 id="parser_classes">.parser_classes</h3>
+<h3 id="authentication_classes">.authentication_classes</h3>
+<h3 id="throttle_classes">.throttle_classes</h3>
+<h3 id="permission_classes">.permission_classes</h3>
+<h3 id="content_negotiation_class">.content_negotiation_class</h3>
+<h2 id="api-policy-instantiation-methods">API policy instantiation methods</h2>
+<p>The following methods are used by REST framework to instantiate the various pluggable API policies. You won't typically need to override these methods.</p>
+<h3 id="get_renderersself">.get_renderers(self)</h3>
+<h3 id="get_parsersself">.get_parsers(self)</h3>
+<h3 id="get_authenticatorsself">.get_authenticators(self)</h3>
+<h3 id="get_throttlesself">.get_throttles(self)</h3>
+<h3 id="get_permissionsself">.get_permissions(self)</h3>
+<h3 id="get_content_negotiatorself">.get_content_negotiator(self)</h3>
+<h2 id="api-policy-implementation-methods">API policy implementation methods</h2>
+<p>The following methods are called before dispatching to the handler method.</p>
+<h3 id="check_permissionsself-request">.check_permissions(self, request)</h3>
+<h3 id="check_throttlesself-request">.check_throttles(self, request)</h3>
+<h3 id="perform_content_negotiationself-request-forcefalse">.perform_content_negotiation(self, request, force=False)</h3>
+<h2 id="dispatch-methods">Dispatch methods</h2>
+<p>The following methods are called directly by the view's <code>.dispatch()</code> method.
+These perform any actions that need to occur before or after calling the handler methods such as <code>.get()</code>, <code>.post()</code>, <code>put()</code>, <code>patch()</code> and <code>.delete()</code>.</p>
+<h3 id="initialself-request-42args-kwargs">.initial(self, request, *args, **kwargs)</h3>
+<p>Performs any actions that need to occur before the handler method gets called.
+This method is used to enforce permissions and throttling, and perform content negotiation.</p>
+<p>You won't typically need to override this method.</p>
+<h3 id="handle_exceptionself-exc">.handle_exception(self, exc)</h3>
+<p>Any exception thrown by the handler method will be passed to this method, which either returns a <code>Response</code> instance, or re-raises the exception.</p>
+<p>The default implementation handles any subclass of <code>rest_framework.exceptions.APIException</code>, as well as Django's <code>Http404</code> and <code>PermissionDenied</code> exceptions, and returns an appropriate error response.</p>
+<p>If you need to customize the error responses your API returns you should subclass this method.</p>
+<h3 id="initialize_requestself-request-42args-kwargs">.initialize_request(self, request, *args, **kwargs)</h3>
+<p>Ensures that the request object that is passed to the handler method is an instance of <code>Request</code>, rather than the usual Django <code>HttpRequest</code>.</p>
+<p>You won't typically need to override this method.</p>
+<h3 id="finalize_responseself-request-response-42args-kwargs">.finalize_response(self, request, response, *args, **kwargs)</h3>
+<p>Ensures that any <code>Response</code> object returned from the handler method will be rendered into the correct content type, as determined by the content negotiation.</p>
+<p>You won't typically need to override this method.</p>
+<hr />
+<h1 id="function-based-views">Function Based Views</h1>
+<blockquote>
+<p>Saying [that Class based views] is always the superior solution is a mistake.</p>
+<p>&mdash; <a href="http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html">Nick Coghlan</a></p>
+</blockquote>
+<p>REST framework also allows you to work with regular function based views. It provides a set of simple decorators that wrap your function based views to ensure they receive an instance of <code>Request</code> (rather than the usual Django <code>HttpRequest</code>) and allows them to return a <code>Response</code> (instead of a Django <code>HttpResponse</code>), and allow you to configure how the request is processed.</p>
+<h2 id="api_view">@api_view()</h2>
+<p><strong>Signature:</strong> <code>@api_view(http_method_names)</code></p>
+<p>The core of this functionality is the <code>api_view</code> decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data:</p>
+<pre><code>from rest_framework.decorators import api_view
+
+@api_view(['GET'])
+def hello_world(request):
+ return Response({"message": "Hello, world!"})
+</code></pre>
+<p>This view will use the default renderers, parsers, authentication classes etc specified in the <a href="../settings">settings</a>.</p>
+<h2 id="api-policy-decorators">API policy decorators</h2>
+<p>To override the default settings, REST framework provides a set of additional decorators which can be added to your views. These must come <em>after</em> (below) the <code>@api_view</code> decorator. For example, to create a view that uses a <a href="../throttling">throttle</a> to ensure it can only be called once per day by a particular user, use the <code>@throttle_classes</code> decorator, passing a list of throttle classes:</p>
+<pre><code>from rest_framework.decorators import api_view, throttle_classes
+from rest_framework.throttling import UserRateThrottle
+
+class OncePerDayUserThrottle(UserRateThrottle):
+ rate = '1/day'
+
+@api_view(['GET'])
+@throttle_classes([OncePerDayUserThrottle])
+def view(request):
+ return Response({"message": "Hello for today! See you tomorrow!"})
+</code></pre>
+<p>These decorators correspond to the attributes set on <code>APIView</code> subclasses, described above.</p>
+<p>The available decorators are:</p>
+<ul>
+<li><code>@renderer_classes(...)</code></li>
+<li><code>@parser_classes(...)</code></li>
+<li><code>@authentication_classes(...)</code></li>
+<li><code>@throttle_classes(...)</code></li>
+<li><code>@permission_classes(...)</code></li>
+</ul>
+<p>Each of these decorators takes a single argument which must be a list or tuple of classes.</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/api-guide/viewsets.html b/api-guide/viewsets.html
deleted file mode 100644
index f239a271..00000000
--- a/api-guide/viewsets.html
+++ /dev/null
@@ -1,445 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>ViewSets - 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/api-guide/viewsets"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="Django, API, REST, ViewSets, API Reference, Custom ViewSet base classes">
- <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="viewsets-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="../api-guide/routers">Next <i class="icon-arrow-right icon-white"></i></a>
- <a class="repo-link btn btn-inverse btn-small " href="../api-guide/generic-views"><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="#viewsets">ViewSets</a></li>
-<li><a href="#example">Example</a></li>
-<li><a href="#marking-extra-actions-for-routing">Marking extra actions for routing</a></li>
-<li class="main"><a href="#api-reference">API Reference</a></li>
-<li><a href="#viewset">ViewSet</a></li>
-<li><a href="#genericviewset">GenericViewSet</a></li>
-<li><a href="#modelviewset">ModelViewSet</a></li>
-<li><a href="#readonlymodelviewset">ReadOnlyModelViewSet</a></li>
-<li class="main"><a href="#custom-viewset-base-classes">Custom ViewSet base classes</a></li>
-<li><a href="#example">Example</a></li>
-
- <div class="promo">
-
- </div>
-</ul>
-
- </div>
- </div>
-
- <div id="main-content" class="span9">
- <p><a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/viewsets.py"><span class="label label-info">viewsets.py</span></a></p>
-<h1 id="viewsets">ViewSets</h1>
-<blockquote>
-<p>After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output.</p>
-<p>&mdash; <a href="http://guides.rubyonrails.org/routing.html">Ruby on Rails Documentation</a></p>
-</blockquote>
-<p>Django REST framework allows you to combine the logic for a set of related views in a single class, called a <code>ViewSet</code>. In other frameworks you may also find conceptually similar implementations named something like 'Resources' or 'Controllers'.</p>
-<p>A <code>ViewSet</code> class is simply <strong>a type of class-based View, that does not provide any method handlers</strong> such as <code>.get()</code> or <code>.post()</code>, and instead provides actions such as <code>.list()</code> and <code>.create()</code>.</p>
-<p>The method handlers for a <code>ViewSet</code> are only bound to the corresponding actions at the point of finalizing the view, using the <code>.as_view()</code> method.</p>
-<p>Typically, rather than explicitly registering the views in a viewset in the urlconf, you'll register the viewset with a router class, that automatically determines the urlconf for you.</p>
-<h2 id="example">Example</h2>
-<p>Let's define a simple viewset that can be used to list or retrieve all the users in the system.</p>
-<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
-from django.shortcuts import get_object_or_404
-from myapps.serializers import UserSerializer
-from rest_framework import viewsets
-from rest_framework.response import Response
-
-class UserViewSet(viewsets.ViewSet):
- """
- A simple ViewSet that for listing or retrieving users.
- """
- def list(self, request):
- queryset = User.objects.all()
- serializer = UserSerializer(queryset, many=True)
- return Response(serializer.data)
-
- def retrieve(self, request, pk=None):
- queryset = User.objects.all()
- user = get_object_or_404(queryset, pk=pk)
- serializer = UserSerializer(user)
- return Response(serializer.data)
-</code></pre>
-<p>If we need to, we can bind this viewset into two separate views, like so:</p>
-<pre class="prettyprint lang-py"><code>user_list = UserViewSet.as_view({'get': 'list'})
-user_detail = UserViewSet.as_view({'get': 'retrieve'})
-</code></pre>
-<p>Typically we wouldn't do this, but would instead register the viewset with a router, and allow the urlconf to be automatically generated.</p>
-<pre class="prettyprint lang-py"><code>from myapp.views import UserViewSet
-from rest_framework.routers import DefaultRouter
-
-router = DefaultRouter()
-router.register(r'users', UserViewSet)
-urlpatterns = router.urls
-</code></pre>
-<p>Rather than writing your own viewsets, you'll often want to use the existing base classes that provide a default set of behavior. For example:</p>
-<pre class="prettyprint lang-py"><code>class UserViewSet(viewsets.ModelViewSet):
- """
- A viewset for viewing and editing user instances.
- """
- serializer_class = UserSerializer
- queryset = User.objects.all()
-</code></pre>
-<p>There are two main advantages of using a <code>ViewSet</code> class over using a <code>View</code> class.</p>
-<ul>
-<li>Repeated logic can be combined into a single class. In the above example, we only need to specify the <code>queryset</code> once, and it'll be used across multiple views.</li>
-<li>By using routers, we no longer need to deal with wiring up the URL conf ourselves.</li>
-</ul>
-<p>Both of these come with a trade-off. Using regular views and URL confs is more explicit and gives you more control. ViewSets are helpful if you want to get up and running quickly, or when you have a large API and you want to enforce a consistent URL configuration throughout.</p>
-<h2 id="marking-extra-actions-for-routing">Marking extra actions for routing</h2>
-<p>The default routers included with REST framework will provide routes for a standard set of create/retrieve/update/destroy style operations, as shown below:</p>
-<pre class="prettyprint lang-py"><code>class UserViewSet(viewsets.ViewSet):
- """
- Example empty viewset demonstrating the standard
- actions that will be handled by a router class.
-
- If you're using format suffixes, make sure to also include
- the `format=None` keyword argument for each action.
- """
-
- def list(self, request):
- pass
-
- def create(self, request):
- pass
-
- def retrieve(self, request, pk=None):
- pass
-
- def update(self, request, pk=None):
- pass
-
- def partial_update(self, request, pk=None):
- pass
-
- def destroy(self, request, pk=None):
- pass
-</code></pre>
-<p>If you have ad-hoc methods that you need to be routed to, you can mark them as requiring routing using the <code>@detail_route</code> or <code>@list_route</code> decorators.</p>
-<p>The <code>@detail_route</code> decorator contains <code>pk</code> in its URL pattern and is intended for methods which require a single instance. The <code>@list_route</code> decorator is intended for methods which operate on a list of objects.</p>
-<p>For example:</p>
-<pre class="prettyprint lang-py"><code>from django.contrib.auth.models import User
-from rest_framework import status
-from rest_framework import viewsets
-from rest_framework.decorators import detail_route, list_route
-from rest_framework.response import Response
-from myapp.serializers import UserSerializer, PasswordSerializer
-
-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>The decorators can additionally take extra arguments that will be set for the routed view only. For example...</p>
-<pre class="prettyprint lang-py"><code> @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
- def set_password(self, request, pk=None):
- ...
-</code></pre>
-<p>Theses decorators will route <code>GET</code> requests by default, but may also accept other HTTP methods, by using the <code>methods</code> argument. For example:</p>
-<pre class="prettyprint lang-py"><code> @detail_route(methods=['post', 'delete'])
- def unset_password(self, request, pk=None):
- ...
-</code></pre>
-<p>The two new actions will then be available at the urls <code>^users/{pk}/set_password/$</code> and <code>^users/{pk}/unset_password/$</code></p>
-<hr />
-<h1 id="api-reference">API Reference</h1>
-<h2 id="viewset">ViewSet</h2>
-<p>The <code>ViewSet</code> class inherits from <code>APIView</code>. You can use any of the standard attributes such as <code>permission_classes</code>, <code>authentication_classes</code> in order to control the API policy on the viewset.</p>
-<p>The <code>ViewSet</code> class does not provide any implementations of actions. In order to use a <code>ViewSet</code> class you'll override the class and define the action implementations explicitly.</p>
-<h2 id="genericviewset">GenericViewSet</h2>
-<p>The <code>GenericViewSet</code> class inherits from <code>GenericAPIView</code>, and provides the default set of <code>get_object</code>, <code>get_queryset</code> methods and other generic view base behavior, but does not include any actions by default.</p>
-<p>In order to use a <code>GenericViewSet</code> class you'll override the class and either mixin the required mixin classes, or define the action implementations explicitly.</p>
-<h2 id="modelviewset">ModelViewSet</h2>
-<p>The <code>ModelViewSet</code> class inherits from <code>GenericAPIView</code> and includes implementations for various actions, by mixing in the behavior of the various mixin classes.</p>
-<p>The actions provided by the <code>ModelViewSet</code> class are <code>.list()</code>, <code>.retrieve()</code>, <code>.create()</code>, <code>.update()</code>, and <code>.destroy()</code>.</p>
-<h4 id="example_1">Example</h4>
-<p>Because <code>ModelViewSet</code> extends <code>GenericAPIView</code>, you'll normally need to provide at least the <code>queryset</code> and <code>serializer_class</code> attributes, or the <code>model</code> attribute shortcut. For example:</p>
-<pre class="prettyprint lang-py"><code>class AccountViewSet(viewsets.ModelViewSet):
- """
- A simple ViewSet for viewing and editing accounts.
- """
- queryset = Account.objects.all()
- serializer_class = AccountSerializer
- permission_classes = [IsAccountAdminOrReadOnly]
-</code></pre>
-<p>Note that you can use any of the standard attributes or method overrides provided by <code>GenericAPIView</code>. For example, to use a <code>ViewSet</code> that dynamically determines the queryset it should operate on, you might do something like this:</p>
-<pre class="prettyprint lang-py"><code>class AccountViewSet(viewsets.ModelViewSet):
- """
- A simple ViewSet for viewing and editing the accounts
- associated with the user.
- """
- serializer_class = AccountSerializer
- permission_classes = [IsAccountAdminOrReadOnly]
-
- def get_queryset(self):
- return self.request.user.accounts.all()
-</code></pre>
-<p>Also note that although this class provides the complete set of create/list/retrieve/update/destroy actions by default, you can restrict the available operations by using the standard permission classes.</p>
-<h2 id="readonlymodelviewset">ReadOnlyModelViewSet</h2>
-<p>The <code>ReadOnlyModelViewSet</code> class also inherits from <code>GenericAPIView</code>. As with <code>ModelViewSet</code> it also includes implementations for various actions, but unlike <code>ModelViewSet</code> only provides the 'read-only' actions, <code>.list()</code> and <code>.retrieve()</code>.</p>
-<h4 id="example_2">Example</h4>
-<p>As with <code>ModelViewSet</code>, you'll normally need to provide at least the <code>queryset</code> and <code>serializer_class</code> attributes. For example:</p>
-<pre class="prettyprint lang-py"><code>class AccountViewSet(viewsets.ReadOnlyModelViewSet):
- """
- A simple ViewSet for viewing accounts.
- """
- queryset = Account.objects.all()
- serializer_class = AccountSerializer
-</code></pre>
-<p>Again, as with <code>ModelViewSet</code>, you can use any of the standard attributes and method overrides available to <code>GenericAPIView</code>.</p>
-<h1 id="custom-viewset-base-classes">Custom ViewSet base classes</h1>
-<p>You may need to provide custom <code>ViewSet</code> classes that do not have the full set of <code>ModelViewSet</code> actions, or that customize the behavior in some other way.</p>
-<h2 id="example_3">Example</h2>
-<p>To create a base viewset class that provides <code>create</code>, <code>list</code> and <code>retrieve</code> operations, inherit from <code>GenericViewSet</code>, and mixin the required actions:</p>
-<pre class="prettyprint lang-py"><code>class CreateListRetrieveViewSet(mixins.CreateModelMixin,
- mixins.ListModelMixin,
- mixins.RetrieveModelMixin,
- viewsets.GenericViewSet):
- """
- A viewset that provides `retrieve`, `create`, and `list` actions.
-
- To use it, override the class and set the `.queryset` and
- `.serializer_class` attributes.
- """
- pass
-</code></pre>
-<p>By creating your own base <code>ViewSet</code> classes, you can provide common behavior that can be reused in multiple viewsets across your API.</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/api-guide/viewsets/index.html b/api-guide/viewsets/index.html
new file mode 100644
index 00000000..6e0e84e2
--- /dev/null
+++ b/api-guide/viewsets/index.html
@@ -0,0 +1,656 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Viewsets - 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/api-guide/viewsets/" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="Django, API, REST, Viewsets">
+ <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="../routers">
+ Next <i class="icon-arrow-right icon-white"></i>
+ </a>
+ <a class="repo-link btn btn-inverse btn-small " rel="next" href="../generic-views">
+ <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 active">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+
+ <li >
+ <a href="../requests">Requests</a>
+ </li>
+
+ <li >
+ <a href="../responses">Responses</a>
+ </li>
+
+ <li >
+ <a href="../views">Views</a>
+ </li>
+
+ <li >
+ <a href="../generic-views">Generic views</a>
+ </li>
+
+ <li class="active" >
+ <a href=".">Viewsets</a>
+ </li>
+
+ <li >
+ <a href="../routers">Routers</a>
+ </li>
+
+ <li >
+ <a href="../parsers">Parsers</a>
+ </li>
+
+ <li >
+ <a href="../renderers">Renderers</a>
+ </li>
+
+ <li >
+ <a href="../serializers">Serializers</a>
+ </li>
+
+ <li >
+ <a href="../fields">Serializer fields</a>
+ </li>
+
+ <li >
+ <a href="../relations">Serializer relations</a>
+ </li>
+
+ <li >
+ <a href="../validators">Validators</a>
+ </li>
+
+ <li >
+ <a href="../authentication">Authentication</a>
+ </li>
+
+ <li >
+ <a href="../permissions">Permissions</a>
+ </li>
+
+ <li >
+ <a href="../throttling">Throttling</a>
+ </li>
+
+ <li >
+ <a href="../filtering">Filtering</a>
+ </li>
+
+ <li >
+ <a href="../pagination">Pagination</a>
+ </li>
+
+ <li >
+ <a href="../content-negotiation">Content negotiation</a>
+ </li>
+
+ <li >
+ <a href="../format-suffixes">Format suffixes</a>
+ </li>
+
+ <li >
+ <a href="../reverse">Returning URLs</a>
+ </li>
+
+ <li >
+ <a href="../exceptions">Exceptions</a>
+ </li>
+
+ <li >
+ <a href="../status-codes">Status codes</a>
+ </li>
+
+ <li >
+ <a href="../testing">Testing</a>
+ </li>
+
+ <li >
+ <a href="../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="../../topics/documenting-your-api">Documenting your API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/ajax-csrf-cors">AJAX, CSRF & CORS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browser-enhancements">Browser enhancements</a>
+ </li>
+
+ <li >
+ <a href="../../topics/browsable-api">The Browsable API</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a>
+ </li>
+
+ <li >
+ <a href="../../topics/third-party-resources">Third Party Resources</a>
+ </li>
+
+ <li >
+ <a href="../../topics/contributing">Contributing to REST framework</a>
+ </li>
+
+ <li >
+ <a href="../../topics/rest-framework-2-announcement">2.0 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.2-announcement">2.2 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.3-announcement">2.3 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/2.4-announcement">2.4 Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/kickstarter-announcement">Kickstarter Announcement</a>
+ </li>
+
+ <li >
+ <a href="../../topics/release-notes">Release Notes</a>
+ </li>
+
+ <li >
+ <a href="../../topics/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="#viewsets">ViewSets</a>
+ </li>
+
+
+ <li>
+ <a href="#example">Example</a>
+ </li>
+
+ <li>
+ <a href="#marking-extra-actions-for-routing">Marking extra actions for routing</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#api-reference">API Reference</a>
+ </li>
+
+
+ <li>
+ <a href="#viewset">ViewSet</a>
+ </li>
+
+ <li>
+ <a href="#genericviewset">GenericViewSet</a>
+ </li>
+
+ <li>
+ <a href="#modelviewset">ModelViewSet</a>
+ </li>
+
+ <li>
+ <a href="#readonlymodelviewset">ReadOnlyModelViewSet</a>
+ </li>
+
+
+
+
+ <li class="main">
+ <a href="#custom-viewset-base-classes">Custom ViewSet base classes</a>
+ </li>
+
+
+ <li>
+ <a href="#example_3">Example</a>
+ </li>
+
+
+
+
+
+
+ </ul>
+
+ </div>
+ </div>
+
+ <div id="main-content" class="span9">
+
+
+ <a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/viewsets.py">
+ <span class="label label-info">viewsets.py</span>
+ </a>
+
+
+
+ <h1 id="viewsets">ViewSets</h1>
+<blockquote>
+<p>After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output.</p>
+<p>&mdash; <a href="http://guides.rubyonrails.org/routing.html">Ruby on Rails Documentation</a></p>
+</blockquote>
+<p>Django REST framework allows you to combine the logic for a set of related views in a single class, called a <code>ViewSet</code>. In other frameworks you may also find conceptually similar implementations named something like 'Resources' or 'Controllers'.</p>
+<p>A <code>ViewSet</code> class is simply <strong>a type of class-based View, that does not provide any method handlers</strong> such as <code>.get()</code> or <code>.post()</code>, and instead provides actions such as <code>.list()</code> and <code>.create()</code>.</p>
+<p>The method handlers for a <code>ViewSet</code> are only bound to the corresponding actions at the point of finalizing the view, using the <code>.as_view()</code> method.</p>
+<p>Typically, rather than explicitly registering the views in a viewset in the urlconf, you'll register the viewset with a router class, that automatically determines the urlconf for you.</p>
+<h2 id="example">Example</h2>
+<p>Let's define a simple viewset that can be used to list or retrieve all the users in the system.</p>
+<pre><code>from django.contrib.auth.models import User
+from django.shortcuts import get_object_or_404
+from myapps.serializers import UserSerializer
+from rest_framework import viewsets
+from rest_framework.response import Response
+
+class UserViewSet(viewsets.ViewSet):
+ """
+ A simple ViewSet that for listing or retrieving users.
+ """
+ def list(self, request):
+ queryset = User.objects.all()
+ serializer = UserSerializer(queryset, many=True)
+ return Response(serializer.data)
+
+ def retrieve(self, request, pk=None):
+ queryset = User.objects.all()
+ user = get_object_or_404(queryset, pk=pk)
+ serializer = UserSerializer(user)
+ return Response(serializer.data)
+</code></pre>
+<p>If we need to, we can bind this viewset into two separate views, like so:</p>
+<pre><code>user_list = UserViewSet.as_view({'get': 'list'})
+user_detail = UserViewSet.as_view({'get': 'retrieve'})
+</code></pre>
+<p>Typically we wouldn't do this, but would instead register the viewset with a router, and allow the urlconf to be automatically generated.</p>
+<pre><code>from myapp.views import UserViewSet
+from rest_framework.routers import DefaultRouter
+
+router = DefaultRouter()
+router.register(r'users', UserViewSet)
+urlpatterns = router.urls
+</code></pre>
+<p>Rather than writing your own viewsets, you'll often want to use the existing base classes that provide a default set of behavior. For example:</p>
+<pre><code>class UserViewSet(viewsets.ModelViewSet):
+ """
+ A viewset for viewing and editing user instances.
+ """
+ serializer_class = UserSerializer
+ queryset = User.objects.all()
+</code></pre>
+<p>There are two main advantages of using a <code>ViewSet</code> class over using a <code>View</code> class.</p>
+<ul>
+<li>Repeated logic can be combined into a single class. In the above example, we only need to specify the <code>queryset</code> once, and it'll be used across multiple views.</li>
+<li>By using routers, we no longer need to deal with wiring up the URL conf ourselves.</li>
+</ul>
+<p>Both of these come with a trade-off. Using regular views and URL confs is more explicit and gives you more control. ViewSets are helpful if you want to get up and running quickly, or when you have a large API and you want to enforce a consistent URL configuration throughout.</p>
+<h2 id="marking-extra-actions-for-routing">Marking extra actions for routing</h2>
+<p>The default routers included with REST framework will provide routes for a standard set of create/retrieve/update/destroy style operations, as shown below:</p>
+<pre><code>class UserViewSet(viewsets.ViewSet):
+ """
+ Example empty viewset demonstrating the standard
+ actions that will be handled by a router class.
+
+ If you're using format suffixes, make sure to also include
+ the `format=None` keyword argument for each action.
+ """
+
+ def list(self, request):
+ pass
+
+ def create(self, request):
+ pass
+
+ def retrieve(self, request, pk=None):
+ pass
+
+ def update(self, request, pk=None):
+ pass
+
+ def partial_update(self, request, pk=None):
+ pass
+
+ def destroy(self, request, pk=None):
+ pass
+</code></pre>
+<p>If you have ad-hoc methods that you need to be routed to, you can mark them as requiring routing using the <code>@detail_route</code> or <code>@list_route</code> decorators.</p>
+<p>The <code>@detail_route</code> decorator contains <code>pk</code> in its URL pattern and is intended for methods which require a single instance. The <code>@list_route</code> decorator is intended for methods which operate on a list of objects.</p>
+<p>For example:</p>
+<pre><code>from django.contrib.auth.models import User
+from rest_framework import status
+from rest_framework import viewsets
+from rest_framework.decorators import detail_route, list_route
+from rest_framework.response import Response
+from myapp.serializers import UserSerializer, PasswordSerializer
+
+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>The decorators can additionally take extra arguments that will be set for the routed view only. For example...</p>
+<pre><code> @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
+ def set_password(self, request, pk=None):
+ ...
+</code></pre>
+<p>Theses decorators will route <code>GET</code> requests by default, but may also accept other HTTP methods, by using the <code>methods</code> argument. For example:</p>
+<pre><code> @detail_route(methods=['post', 'delete'])
+ def unset_password(self, request, pk=None):
+ ...
+</code></pre>
+<p>The two new actions will then be available at the urls <code>^users/{pk}/set_password/$</code> and <code>^users/{pk}/unset_password/$</code></p>
+<hr />
+<h1 id="api-reference">API Reference</h1>
+<h2 id="viewset">ViewSet</h2>
+<p>The <code>ViewSet</code> class inherits from <code>APIView</code>. You can use any of the standard attributes such as <code>permission_classes</code>, <code>authentication_classes</code> in order to control the API policy on the viewset.</p>
+<p>The <code>ViewSet</code> class does not provide any implementations of actions. In order to use a <code>ViewSet</code> class you'll override the class and define the action implementations explicitly.</p>
+<h2 id="genericviewset">GenericViewSet</h2>
+<p>The <code>GenericViewSet</code> class inherits from <code>GenericAPIView</code>, and provides the default set of <code>get_object</code>, <code>get_queryset</code> methods and other generic view base behavior, but does not include any actions by default.</p>
+<p>In order to use a <code>GenericViewSet</code> class you'll override the class and either mixin the required mixin classes, or define the action implementations explicitly.</p>
+<h2 id="modelviewset">ModelViewSet</h2>
+<p>The <code>ModelViewSet</code> class inherits from <code>GenericAPIView</code> and includes implementations for various actions, by mixing in the behavior of the various mixin classes.</p>
+<p>The actions provided by the <code>ModelViewSet</code> class are <code>.list()</code>, <code>.retrieve()</code>, <code>.create()</code>, <code>.update()</code>, and <code>.destroy()</code>.</p>
+<h4 id="example_1">Example</h4>
+<p>Because <code>ModelViewSet</code> extends <code>GenericAPIView</code>, you'll normally need to provide at least the <code>queryset</code> and <code>serializer_class</code> attributes, or the <code>model</code> attribute shortcut. For example:</p>
+<pre><code>class AccountViewSet(viewsets.ModelViewSet):
+ """
+ A simple ViewSet for viewing and editing accounts.
+ """
+ queryset = Account.objects.all()
+ serializer_class = AccountSerializer
+ permission_classes = [IsAccountAdminOrReadOnly]
+</code></pre>
+<p>Note that you can use any of the standard attributes or method overrides provided by <code>GenericAPIView</code>. For example, to use a <code>ViewSet</code> that dynamically determines the queryset it should operate on, you might do something like this:</p>
+<pre><code>class AccountViewSet(viewsets.ModelViewSet):
+ """
+ A simple ViewSet for viewing and editing the accounts
+ associated with the user.
+ """
+ serializer_class = AccountSerializer
+ permission_classes = [IsAccountAdminOrReadOnly]
+
+ def get_queryset(self):
+ return self.request.user.accounts.all()
+</code></pre>
+<p>Also note that although this class provides the complete set of create/list/retrieve/update/destroy actions by default, you can restrict the available operations by using the standard permission classes.</p>
+<h2 id="readonlymodelviewset">ReadOnlyModelViewSet</h2>
+<p>The <code>ReadOnlyModelViewSet</code> class also inherits from <code>GenericAPIView</code>. As with <code>ModelViewSet</code> it also includes implementations for various actions, but unlike <code>ModelViewSet</code> only provides the 'read-only' actions, <code>.list()</code> and <code>.retrieve()</code>.</p>
+<h4 id="example_2">Example</h4>
+<p>As with <code>ModelViewSet</code>, you'll normally need to provide at least the <code>queryset</code> and <code>serializer_class</code> attributes. For example:</p>
+<pre><code>class AccountViewSet(viewsets.ReadOnlyModelViewSet):
+ """
+ A simple ViewSet for viewing accounts.
+ """
+ queryset = Account.objects.all()
+ serializer_class = AccountSerializer
+</code></pre>
+<p>Again, as with <code>ModelViewSet</code>, you can use any of the standard attributes and method overrides available to <code>GenericAPIView</code>.</p>
+<h1 id="custom-viewset-base-classes">Custom ViewSet base classes</h1>
+<p>You may need to provide custom <code>ViewSet</code> classes that do not have the full set of <code>ModelViewSet</code> actions, or that customize the behavior in some other way.</p>
+<h2 id="example_3">Example</h2>
+<p>To create a base viewset class that provides <code>create</code>, <code>list</code> and <code>retrieve</code> operations, inherit from <code>GenericViewSet</code>, and mixin the required actions:</p>
+<pre><code>class CreateListRetrieveViewSet(mixins.CreateModelMixin,
+ mixins.ListModelMixin,
+ mixins.RetrieveModelMixin,
+ viewsets.GenericViewSet):
+ """
+ A viewset that provides `retrieve`, `create`, and `list` actions.
+
+ To use it, override the class and set the `.queryset` and
+ `.serializer_class` attributes.
+ """
+ pass
+</code></pre>
+<p>By creating your own base <code>ViewSet</code> classes, you can provide common behavior that can be reused in multiple viewsets across your API.</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