mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-12-12 12:44:11 +03:00
Deployed de497a9b with MkDocs version: 1.0.4
This commit is contained in:
parent
a50183a988
commit
77a24aad40
610
404.html
610
404.html
|
|
@ -1,167 +1,475 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>George Floyd</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous"
|
||||
<meta name="theme-color" content="#563d7c">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<title>Django REST framework</title>
|
||||
<link href="//img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="/." />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Django, API, REST">
|
||||
<meta name="author" content="Tom Christie">
|
||||
|
||||
<style>
|
||||
/*
|
||||
* Globals
|
||||
*/
|
||||
<!-- 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">
|
||||
|
||||
/* Links */
|
||||
a,
|
||||
a:focus,
|
||||
a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
<!-- 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]-->
|
||||
|
||||
/* Custom default button */
|
||||
.btn-secondary,
|
||||
.btn-secondary:hover,
|
||||
.btn-secondary:focus {
|
||||
color: #333;
|
||||
text-shadow: none; /* Prevent inheritance from `body` */
|
||||
background-color: #fff;
|
||||
border: .05rem solid #fff;
|
||||
}
|
||||
<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>
|
||||
|
||||
/*
|
||||
* Base structure
|
||||
*/
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
body {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
color: #fff;
|
||||
text-shadow: 0 .05rem .1rem rgba(0, 0, 0, .5);
|
||||
box-shadow: inset 0 0 5rem rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
.cover-container {
|
||||
max-width: 42em;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Header
|
||||
*/
|
||||
.masthead {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.masthead-brand {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.nav-masthead .nav-link {
|
||||
padding: .25rem 0;
|
||||
font-weight: 700;
|
||||
color: rgba(255, 255, 255, .5);
|
||||
background-color: transparent;
|
||||
border-bottom: .25rem solid transparent;
|
||||
}
|
||||
|
||||
.nav-masthead .nav-link:hover,
|
||||
.nav-masthead .nav-link:focus {
|
||||
border-bottom-color: rgba(255, 255, 255, .25);
|
||||
}
|
||||
|
||||
.nav-masthead .nav-link + .nav-link {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.nav-masthead .active {
|
||||
color: #fff;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
|
||||
@media (min-width: 48em) {
|
||||
.masthead-brand {
|
||||
float: left;
|
||||
<style>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.nav-masthead {
|
||||
float: right;
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Cover
|
||||
*/
|
||||
.cover {
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
.cover .btn-lg {
|
||||
padding: .75rem 1.25rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Footer
|
||||
*/
|
||||
.mastfoot {
|
||||
color: rgba(255, 255, 255, .5);
|
||||
}
|
||||
.bd-placeholder-img {
|
||||
font-size: 1.125rem;
|
||||
text-anchor: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
@media (max-width: 767px) {
|
||||
div.promo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="prettyPrint()" class="-page">
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.bd-placeholder-img-lg {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="cover.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="text-center">
|
||||
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
||||
<header class="masthead mb-auto">
|
||||
<!--
|
||||
<div class="inner">
|
||||
<h3 class="masthead-brand">Cover</h3>
|
||||
<nav class="nav nav-masthead justify-content-center">
|
||||
<a class="nav-link active" href="#">Home</a>
|
||||
<a class="nav-link" href="#">Features</a>
|
||||
<a class="nav-link" href="#">Contact</a>
|
||||
</nav>
|
||||
<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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small disabled" rel="next" >
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small disabled" rel="prev" >
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://www.django-rest-framework.org/">Django REST framework</a>
|
||||
<div class="nav-collapse collapse">
|
||||
|
||||
<!-- Main navigation -->
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
<li >
|
||||
<a href="/.">Home</a>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="/tutorial/quickstart/">Quickstart</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/tutorial/1-serialization/">1 - Serialization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/tutorial/2-requests-and-responses/">2 - Requests and responses</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/tutorial/3-class-based-views/">3 - Class based views</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/tutorial/4-authentication-and-permissions/">4 - Authentication and permissions</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/tutorial/5-relationships-and-hyperlinked-apis/">5 - Relationships and hyperlinked APIs</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/tutorial/6-viewsets-and-routers/">6 - Viewsets and routers</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/requests/">Requests</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/responses/">Responses</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/views/">Views</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/generic-views/">Generic views</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/viewsets/">Viewsets</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/routers/">Routers</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/parsers/">Parsers</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/renderers/">Renderers</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/serializers/">Serializers</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/fields/">Serializer fields</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/relations/">Serializer relations</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/validators/">Validators</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/authentication/">Authentication</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/permissions/">Permissions</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/caching/">Caching</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/throttling/">Throttling</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/filtering/">Filtering</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/pagination/">Pagination</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/schemas/">Schemas</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/format-suffixes/">Format suffixes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/reverse/">Returning URLs</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/exceptions/">Exceptions</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/status-codes/">Status codes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/testing/">Testing</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/api-guide/settings/">Settings</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="/community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="/community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</header>
|
||||
|
||||
<main role="main" class="inner cover">
|
||||
<h1 class="cover-heading">George Floyd</h1>
|
||||
<p class="lead mastfoot">Natosha McDade, Yassin Mohamed, Finan H. Berhe, Sean Reed, Steven Demarco Taylor, Breonna Taylor, Ariane McCree, Terrance Franklin, Miles Hall, Darius Tarver, William Green, Samuel David Mallard, Kwame Jones, De’von Bailey, Christopher Whitfield, Anthony Hill, De’Von Bailey, Eric Logan, Jamarion Robinson, Gregory Hill Jr, JaQuavion Slaton, Ryan Twyman, Brandon Webber, Jimmy Atchison, Willie McCoy, Emantic Fitzgerald Bradford J, D’ettrick Griffin, Jemel Roberson, DeAndre Ballard, Botham Shem Jean, Robert Lawrence White, Anthony Lamar Smith, Ramarley Graham, Manuel Loggins Jr, Trayvon Martin, Wendell Allen, Kendrec McDade, Larry Jackson Jr, Jonathan Ferrell, Jordan Baker, Victor White III, Dontre Hamilton, Eric Garner, John Crawford III, Michael Brown, Ezell Ford, Dante Parker, Kajieme Powell, Laquan McDonald, Akai Gurley, Tamir Rice, Rumain Brisbon, Jerame Reid, Charly Keunang, Tony Robinson, Walter Scott, Freddie Gray, Brendon Glenn, Samuel DuBose, Christian Taylor, Jamar Clark, Mario Woods, Quintonio LeGrier, Gregory Gunn, Akiel Denkins, Alton Sterling, Philando Castile, Terrence Sterling, Terence Crutcher, Keith Lamont Scott, Alfred Olango, Jordan Edwards, Stephon Clark, Danny Ray Thomas, DeJuan Guillory, Patrick Harmon, Jonathan Hart, Maurice Granton, Julius Johnson, Jamee Johnson, Michael Dean...</p>
|
||||
<!--<p class="lead">
|
||||
<a href="#" class="btn btn-lg btn-secondary">Learn more</a>
|
||||
</p>-->
|
||||
</main>
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<footer class="mastfoot mt-auto">
|
||||
<div class="inner">
|
||||
<p>This site is currently offline, as a small mark of respect, and expression of solidarity.<br/>The <a href="https://github.com/encode/django-rest-framework/tree/master/docs">REST framework documentation</a> remains accessible on <a href="https://github.com/encode/django-rest-framework">the GitHub repo</a>.</p>
|
||||
<p>Organisations that could use your financial support include <a href="https://blacklivesmatter.com/">Black Lives Matter</a>, <a href="https://www.naacpldf.org">The NAACP Legal Defense and Educational Fund</a>, <a href="https://eji.org">The Equal Justice Initiative</a>, <a href="https://www.wetheprotesters.org">We The Protesters</a>, and the <a href="https://www.gofundme.com/f/georgefloyd">George Floyd Memorial Fund</a>.</p>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<div id="table-of-contents">
|
||||
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
<h1 id="404-page-not-found" style="text-align: center">404</h1>
|
||||
<p style="text-align: center"><strong>Page not found</strong></p>
|
||||
<p style="text-align: center">Try the <a href="https://www.django-rest-framework.org/">homepage</a>, or <a href="#searchModal" data-toggle="modal">search the documentation</a>.</p>
|
||||
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
</div> <!--/row-->
|
||||
</div> <!--/.fluid-container-->
|
||||
</div> <!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div> <!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="//js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '/';</script>
|
||||
|
||||
<script src="/search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
880
api-guide/authentication/index.html
Normal file
880
api-guide/authentication/index.html
Normal file
|
|
@ -0,0 +1,880 @@
|
|||
<!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="../../img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="https://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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../permissions/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../validators/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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 class="active" >
|
||||
<a href="./">Authentication</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../permissions/">Permissions</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<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="#remoteuserauthentication">RemoteUserAuthentication</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="#django-oauth-toolkit">Django OAuth Toolkit</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#django-rest-framework-oauth">Django REST framework OAuth</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>
|
||||
|
||||
<li>
|
||||
<a href="#django-rest-auth">django-rest-auth</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#django-rest-framework-social-oauth2">django-rest-framework-social-oauth2</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#django-rest-knox">django-rest-knox</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#drfpasswordless">drfpasswordless</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<a class="github" href="https://github.com/encode/django-rest-framework/tree/master/rest_framework/authentication.py">
|
||||
<span class="label label-info">authentication.py</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<h1 id="authentication"><a class="toclink" href="#authentication">Authentication</a></h1>
|
||||
<blockquote>
|
||||
<p>Auth needs to be pluggable.</p>
|
||||
<p>— Jacob Kaplan-Moss, <a href="https://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>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>
|
||||
<hr />
|
||||
<h2 id="how-authentication-is-determined"><a class="toclink" href="#how-authentication-is-determined">How authentication is determined</a></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>
|
||||
<p>If no class authenticates, <code>request.user</code> will be set to an instance of <code>django.contrib.auth.models.AnonymousUser</code>, and <code>request.auth</code> will be set to <code>None</code>.</p>
|
||||
<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"><a class="toclink" href="#setting-the-authentication-scheme">Setting the authentication scheme</a></h2>
|
||||
<p>The default authentication schemes may be set globally, using the <code>DEFAULT_AUTHENTICATION_CLASSES</code> setting. For example.</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
]
|
||||
}
|
||||
</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><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
|
||||
|
||||
class ExampleView(APIView):
|
||||
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get(self, request, format=None):
|
||||
content = {
|
||||
'user': unicode(request.user), # `django.contrib.auth.User` instance.
|
||||
'auth': unicode(request.auth), # None
|
||||
}
|
||||
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'])
|
||||
@authentication_classes([SessionAuthentication, BasicAuthentication])
|
||||
@permission_classes([IsAuthenticated])
|
||||
def example_view(request, format=None):
|
||||
content = {
|
||||
'user': unicode(request.user), # `django.contrib.auth.User` instance.
|
||||
'auth': unicode(request.auth), # None
|
||||
}
|
||||
return Response(content)
|
||||
</code></pre>
|
||||
<h2 id="unauthorized-and-forbidden-responses"><a class="toclink" href="#unauthorized-and-forbidden-responses">Unauthorized and Forbidden responses</a></h2>
|
||||
<p>When an unauthenticated request is denied permission there are two different error codes that may be appropriate.</p>
|
||||
<ul>
|
||||
<li><a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">HTTP 401 Unauthorized</a></li>
|
||||
<li><a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4">HTTP 403 Permission Denied</a></li>
|
||||
</ul>
|
||||
<p>HTTP 401 responses must always include a <code>WWW-Authenticate</code> header, that instructs the client how to authenticate. HTTP 403 responses do not include the <code>WWW-Authenticate</code> header.</p>
|
||||
<p>The kind of response that will be used depends on the authentication scheme. Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. <strong>The first authentication class set on the view is used when determining the type of response</strong>.</p>
|
||||
<p>Note that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a <code>403 Permission Denied</code> response will always be used, regardless of the authentication scheme.</p>
|
||||
<h2 id="apache-mod_wsgi-specific-configuration"><a class="toclink" href="#apache-mod_wsgi-specific-configuration">Apache mod_wsgi specific configuration</a></h2>
|
||||
<p>Note that if deploying to <a href="https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIPassAuthorization.html">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><code># this can go in either server config, virtual host, directory or .htaccess
|
||||
WSGIPassAuthorization On
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h1 id="api-reference"><a class="toclink" href="#api-reference">API Reference</a></h1>
|
||||
<h2 id="basicauthentication"><a class="toclink" href="#basicauthentication">BasicAuthentication</a></h2>
|
||||
<p>This authentication scheme uses <a href="https://tools.ietf.org/html/rfc2617">HTTP Basic Authentication</a>, signed against a user's username and password. Basic authentication is generally only appropriate for testing.</p>
|
||||
<p>If successfully authenticated, <code>BasicAuthentication</code> provides the following credentials.</p>
|
||||
<ul>
|
||||
<li><code>request.user</code> will be a Django <code>User</code> instance.</li>
|
||||
<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><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"><a class="toclink" href="#tokenauthentication">TokenAuthentication</a></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><code>INSTALLED_APPS = [
|
||||
...
|
||||
'rest_framework.authtoken'
|
||||
]
|
||||
</code></pre>
|
||||
<hr />
|
||||
<p><strong>Note:</strong> Make sure to run <code>manage.py migrate</code> after changing your settings. The <code>rest_framework.authtoken</code> app provides Django database migrations.</p>
|
||||
<hr />
|
||||
<p>You'll also need to create tokens for your users.</p>
|
||||
<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><code>Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
|
||||
</code></pre>
|
||||
<p><strong>Note:</strong> If you want to use a different keyword in the header, such as <code>Bearer</code>, simply subclass <code>TokenAuthentication</code> and set the <code>keyword</code> class variable.</p>
|
||||
<p>If successfully authenticated, <code>TokenAuthentication</code> provides the following credentials.</p>
|
||||
<ul>
|
||||
<li><code>request.user</code> will be a Django <code>User</code> instance.</li>
|
||||
<li><code>request.auth</code> will be a <code>rest_framework.authtoken.models.Token</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><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><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"><a class="toclink" href="#generating-tokens">Generating Tokens</a></h4>
|
||||
<h5 id="by-using-signals"><a class="toclink" href="#by-using-signals">By using signals</a></h5>
|
||||
<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><code>from django.conf import settings
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
|
||||
def create_auth_token(sender, instance=None, created=False, **kwargs):
|
||||
if created:
|
||||
Token.objects.create(user=instance)
|
||||
</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><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>
|
||||
<h5 id="by-exposing-an-api-endpoint"><a class="toclink" href="#by-exposing-an-api-endpoint">By exposing an api endpoint</a></h5>
|
||||
<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><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><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.</p>
|
||||
<p>By default there are no permissions or throttling applied to the <code>obtain_auth_token</code> view. If you do wish to apply throttling you'll need to override the view class,
|
||||
and include them using the <code>throttle_classes</code> attribute.</p>
|
||||
<p>If you need a customized version of the <code>obtain_auth_token</code> view, you can do so by subclassing the <code>ObtainAuthToken</code> view class, and using that in your url conf instead.</p>
|
||||
<p>For example, you may return additional user information beyond the <code>token</code> value:</p>
|
||||
<pre><code>from rest_framework.authtoken.views import ObtainAuthToken
|
||||
from rest_framework.authtoken.models import Token
|
||||
from rest_framework.response import Response
|
||||
|
||||
class CustomAuthToken(ObtainAuthToken):
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
serializer = self.serializer_class(data=request.data,
|
||||
context={'request': request})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
user = serializer.validated_data['user']
|
||||
token, created = Token.objects.get_or_create(user=user)
|
||||
return Response({
|
||||
'token': token.key,
|
||||
'user_id': user.pk,
|
||||
'email': user.email
|
||||
})
|
||||
</code></pre>
|
||||
<p>And in your <code>urls.py</code>:</p>
|
||||
<pre><code>urlpatterns += [
|
||||
url(r'^api-token-auth/', CustomAuthToken.as_view())
|
||||
]
|
||||
</code></pre>
|
||||
<h5 id="with-django-admin"><a class="toclink" href="#with-django-admin">With Django admin</a></h5>
|
||||
<p>It is also possible to create Tokens manually through admin interface. In case you are using a large user base, we recommend that you monkey patch the <code>TokenAdmin</code> class to customize it to your needs, more specifically by declaring the <code>user</code> field as <code>raw_field</code>.</p>
|
||||
<p><code>your_app/admin.py</code>:</p>
|
||||
<pre><code>from rest_framework.authtoken.admin import TokenAdmin
|
||||
|
||||
TokenAdmin.raw_id_fields = ['user']
|
||||
</code></pre>
|
||||
<h4 id="using-django-managepy-command"><a class="toclink" href="#using-django-managepy-command">Using Django manage.py command</a></h4>
|
||||
<p>Since version 3.6.4 it's possible to generate a user token using the following command:</p>
|
||||
<pre><code>./manage.py drf_create_token <username>
|
||||
</code></pre>
|
||||
<p>this command will return the API token for the given user, creating it if it doesn't exist:</p>
|
||||
<pre><code>Generated token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b for user user1
|
||||
</code></pre>
|
||||
<p>In case you want to regenerate the token (for example if it has been compromised or leaked) you can pass an additional parameter:</p>
|
||||
<pre><code>./manage.py drf_create_token -r <username>
|
||||
</code></pre>
|
||||
<h2 id="sessionauthentication"><a class="toclink" href="#sessionauthentication">SessionAuthentication</a></h2>
|
||||
<p>This authentication scheme uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website.</p>
|
||||
<p>If successfully authenticated, <code>SessionAuthentication</code> provides the following credentials.</p>
|
||||
<ul>
|
||||
<li><code>request.user</code> will be a Django <code>User</code> instance.</li>
|
||||
<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 403 Forbidden</code> response.</p>
|
||||
<p>If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as <code>PUT</code>, <code>PATCH</code>, <code>POST</code> or <code>DELETE</code> requests. See the <a href="https://docs.djangoproject.com/en/stable/ref/csrf/#ajax">Django CSRF documentation</a> for more details.</p>
|
||||
<p><strong>Warning</strong>: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.</p>
|
||||
<p>CSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied.</p>
|
||||
<h2 id="remoteuserauthentication"><a class="toclink" href="#remoteuserauthentication">RemoteUserAuthentication</a></h2>
|
||||
<p>This authentication scheme allows you to delegate authentication to your web server, which sets the <code>REMOTE_USER</code>
|
||||
environment variable.</p>
|
||||
<p>To use it, you must have <code>django.contrib.auth.backends.RemoteUserBackend</code> (or a subclass) in your
|
||||
<code>AUTHENTICATION_BACKENDS</code> setting. By default, <code>RemoteUserBackend</code> creates <code>User</code> objects for usernames that don't
|
||||
already exist. To change this and other behaviour, consult the
|
||||
<a href="https://docs.djangoproject.com/en/stable/howto/auth-remote-user/">Django documentation</a>.</p>
|
||||
<p>If successfully authenticated, <code>RemoteUserAuthentication</code> provides the following credentials:</p>
|
||||
<ul>
|
||||
<li><code>request.user</code> will be a Django <code>User</code> instance.</li>
|
||||
<li><code>request.auth</code> will be <code>None</code>.</li>
|
||||
</ul>
|
||||
<p>Consult your web server's documentation for information about configuring an authentication method, e.g.:</p>
|
||||
<ul>
|
||||
<li><a href="https://httpd.apache.org/docs/2.4/howto/auth.html">Apache Authentication How-To</a></li>
|
||||
<li><a href="https://www.nginx.com/resources/admin-guide/#restricting_access">NGINX (Restricting Access)</a></li>
|
||||
</ul>
|
||||
<h1 id="custom-authentication"><a class="toclink" href="#custom-authentication">Custom authentication</a></h1>
|
||||
<p>To implement a custom authentication scheme, subclass <code>BaseAuthentication</code> and override the <code>.authenticate(self, request)</code> method. The method should return a two-tuple of <code>(user, auth)</code> if authentication succeeds, or <code>None</code> otherwise.</p>
|
||||
<p>In some circumstances instead of returning <code>None</code>, you may want to raise an <code>AuthenticationFailed</code> exception from the <code>.authenticate()</code> method.</p>
|
||||
<p>Typically the approach you should take is:</p>
|
||||
<ul>
|
||||
<li>If authentication is not attempted, return <code>None</code>. Any other authentication schemes also in use will still be checked.</li>
|
||||
<li>If authentication is attempted but fails, raise a <code>AuthenticationFailed</code> exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes.</li>
|
||||
</ul>
|
||||
<p>You <em>may</em> also override the <code>.authenticate_header(self, request)</code> method. If implemented, it should return a string that will be used as the value of the <code>WWW-Authenticate</code> header in a <code>HTTP 401 Unauthorized</code> response.</p>
|
||||
<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>
|
||||
<hr />
|
||||
<p><strong>Note:</strong> When your custom authenticator is invoked by the request object's <code>.user</code> or <code>.auth</code> properties, you may see an <code>AttributeError</code> re-raised as a <code>WrappedAttributeError</code>. This is necessary to prevent the original exception from being suppressed by the outer property access. Python will not recognize that the <code>AttributeError</code> originates from your custom authenticator and will instead assume that the request object does not have a <code>.user</code> or <code>.auth</code> property. These errors should be fixed or otherwise handled by your authenticator.</p>
|
||||
<hr />
|
||||
<h2 id="example"><a class="toclink" href="#example">Example</a></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><code>from django.contrib.auth.models import User
|
||||
from rest_framework import authentication
|
||||
from rest_framework import exceptions
|
||||
|
||||
class ExampleAuthentication(authentication.BaseAuthentication):
|
||||
def authenticate(self, request):
|
||||
username = request.META.get('HTTP_X_USERNAME')
|
||||
if not username:
|
||||
return None
|
||||
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
raise exceptions.AuthenticationFailed('No such user')
|
||||
|
||||
return (user, None)
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h1 id="third-party-packages"><a class="toclink" href="#third-party-packages">Third party packages</a></h1>
|
||||
<p>The following third party packages are also available.</p>
|
||||
<h2 id="django-oauth-toolkit"><a class="toclink" href="#django-oauth-toolkit">Django OAuth Toolkit</a></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 3.4+. 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 well supported and is currently our <strong>recommended package for OAuth 2.0 support</strong>.</p>
|
||||
<h4 id="installation-configuration"><a class="toclink" href="#installation-configuration">Installation & configuration</a></h4>
|
||||
<p>Install using <code>pip</code>.</p>
|
||||
<pre><code>pip install django-oauth-toolkit
|
||||
</code></pre>
|
||||
<p>Add the package to your <code>INSTALLED_APPS</code> and modify your REST framework settings.</p>
|
||||
<pre><code>INSTALLED_APPS = [
|
||||
...
|
||||
'oauth2_provider',
|
||||
]
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<p>For more details see the <a href="https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html">Django REST framework - Getting started</a> documentation.</p>
|
||||
<h2 id="django-rest-framework-oauth"><a class="toclink" href="#django-rest-framework-oauth">Django REST framework OAuth</a></h2>
|
||||
<p>The <a href="https://jpadilla.github.io/django-rest-framework-oauth/">Django REST framework OAuth</a> package provides both OAuth1 and OAuth2 support for REST framework.</p>
|
||||
<p>This package was previously included directly in REST framework but is now supported and maintained as a third party package.</p>
|
||||
<h4 id="installation-configuration_1"><a class="toclink" href="#installation-configuration_1">Installation & configuration</a></h4>
|
||||
<p>Install the package using <code>pip</code>.</p>
|
||||
<pre><code>pip install djangorestframework-oauth
|
||||
</code></pre>
|
||||
<p>For details on configuration and usage see the Django REST framework OAuth documentation for <a href="https://jpadilla.github.io/django-rest-framework-oauth/authentication/">authentication</a> and <a href="https://jpadilla.github.io/django-rest-framework-oauth/permissions/">permissions</a>.</p>
|
||||
<h2 id="json-web-token-authentication"><a class="toclink" href="#json-web-token-authentication">JSON Web Token Authentication</a></h2>
|
||||
<p>JSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. A package for JWT authentication is <a href="https://github.com/davesque/django-rest-framework-simplejwt">djangorestframework-simplejwt</a> which provides some features as well as a pluggable token blacklist app.</p>
|
||||
<h2 id="hawk-http-authentication"><a class="toclink" href="#hawk-http-authentication">Hawk HTTP Authentication</a></h2>
|
||||
<p>The <a href="https://hawkrest.readthedocs.io/en/latest/">HawkREST</a> library builds on the <a href="https://mohawk.readthedocs.io/en/latest/">Mohawk</a> library to let you work with <a href="https://github.com/hueniverse/hawk">Hawk</a> signed requests and responses in your API. <a href="https://github.com/hueniverse/hawk">Hawk</a> lets two parties securely communicate with each other using messages signed by a shared key. It is based on <a href="https://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05">HTTP MAC access authentication</a> (which was based on parts of <a href="https://oauth.net/core/1.0a/">OAuth 1.0</a>).</p>
|
||||
<h2 id="http-signature-authentication"><a class="toclink" href="#http-signature-authentication">HTTP Signature Authentication</a></h2>
|
||||
<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="https://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> (outdated) package which provides an easy to use HTTP Signature Authentication mechanism. You can use the updated fork version of <a href="https://github.com/etoccalino/django-rest-framework-httpsignature">djangorestframework-httpsignature</a>, which is <a href="https://github.com/ahknight/drf-httpsig">drf-httpsig</a>.</p>
|
||||
<h2 id="djoser"><a class="toclink" href="#djoser">Djoser</a></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>
|
||||
<h2 id="django-rest-auth"><a class="toclink" href="#django-rest-auth">django-rest-auth</a></h2>
|
||||
<p><a href="https://github.com/Tivix/django-rest-auth">Django-rest-auth</a> library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.</p>
|
||||
<h2 id="django-rest-framework-social-oauth2"><a class="toclink" href="#django-rest-framework-social-oauth2">django-rest-framework-social-oauth2</a></h2>
|
||||
<p><a href="https://github.com/PhilipGarnero/django-rest-framework-social-oauth2">Django-rest-framework-social-oauth2</a> library provides an easy way to integrate social plugins (facebook, twitter, google, etc.) to your authentication system and an easy oauth2 setup. With this library, you will be able to authenticate users based on external tokens (e.g. facebook access token), convert these tokens to "in-house" oauth2 tokens and use and generate oauth2 tokens to authenticate your users.</p>
|
||||
<h2 id="django-rest-knox"><a class="toclink" href="#django-rest-knox">django-rest-knox</a></h2>
|
||||
<p><a href="https://github.com/James1345/django-rest-knox">Django-rest-knox</a> library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).</p>
|
||||
<h2 id="drfpasswordless"><a class="toclink" href="#drfpasswordless">drfpasswordless</a></h2>
|
||||
<p><a href="https://github.com/aaronn/django-rest-framework-passwordless">drfpasswordless</a> adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's own TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number.</p>
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
</div> <!--/row-->
|
||||
</div> <!--/.fluid-container-->
|
||||
</div> <!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div> <!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
531
api-guide/caching/index.html
Normal file
531
api-guide/caching/index.html
Normal file
|
|
@ -0,0 +1,531 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<title>Caching - Django REST framework</title>
|
||||
<link href="../../img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="https://www.django-rest-framework.org/api-guide/caching/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Django, API, REST, Caching">
|
||||
<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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../throttling/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../permissions/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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="./">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<div id="table-of-contents">
|
||||
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
|
||||
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#caching">Caching</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#using-cache-with-apiview-and-viewsets">Using cache with apiview and viewsets</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<h1 id="caching"><a class="toclink" href="#caching">Caching</a></h1>
|
||||
<blockquote>
|
||||
<p>A certain woman had a very sharp consciousness but almost no
|
||||
memory ... She remembered enough to work, and she worked hard.
|
||||
- Lydia Davis</p>
|
||||
</blockquote>
|
||||
<p>Caching in REST Framework works well with the cache utilities
|
||||
provided in Django.</p>
|
||||
<hr />
|
||||
<h2 id="using-cache-with-apiview-and-viewsets"><a class="toclink" href="#using-cache-with-apiview-and-viewsets">Using cache with apiview and viewsets</a></h2>
|
||||
<p>Django provides a <a href="https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/#decorating-the-class"><code>method_decorator</code></a> to use
|
||||
decorators with class based views. This can be used with
|
||||
other cache decorators such as <a href="https://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache"><code>cache_page</code></a> and
|
||||
<a href="https://docs.djangoproject.com/en/dev/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie"><code>vary_on_cookie</code></a>.</p>
|
||||
<pre><code class="python">from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.cache import cache_page
|
||||
from django.views.decorators.vary import vary_on_cookie
|
||||
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import viewsets
|
||||
|
||||
|
||||
class UserViewSet(viewsets.ViewSet):
|
||||
|
||||
# Cache requested url for each user for 2 hours
|
||||
@method_decorator(cache_page(60*60*2))
|
||||
@method_decorator(vary_on_cookie)
|
||||
def list(self, request, format=None):
|
||||
content = {
|
||||
'user_feed': request.user.get_user_feed()
|
||||
}
|
||||
return Response(content)
|
||||
|
||||
|
||||
class PostView(APIView):
|
||||
|
||||
# Cache page for the requested url
|
||||
@method_decorator(cache_page(60*60*2))
|
||||
def get(self, request, format=None):
|
||||
content = {
|
||||
'title': 'Post title',
|
||||
'body': 'Post content'
|
||||
}
|
||||
return Response(content)
|
||||
</code></pre>
|
||||
|
||||
<p><strong>NOTE:</strong> The <a href="https://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache"><code>cache_page</code></a> decorator only caches the
|
||||
<code>GET</code> and <code>HEAD</code> responses with status 200.</p>
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
</div> <!--/row-->
|
||||
</div> <!--/.fluid-container-->
|
||||
</div> <!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div> <!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
574
api-guide/content-negotiation/index.html
Normal file
574
api-guide/content-negotiation/index.html
Normal file
|
|
@ -0,0 +1,574 @@
|
|||
<!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="https://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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../metadata/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../versioning/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li class="active" >
|
||||
<a href="./">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<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">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<a class="github" href="https://github.com/encode/django-rest-framework/tree/master/rest_framework/negotiation.py">
|
||||
<span class="label label-info">negotiation.py</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<h1 id="content-negotiation"><a class="toclink" href="#content-negotiation">Content negotiation</a></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>— <a href="https://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"><a class="toclink" href="#determining-the-accepted-renderer">Determining the accepted renderer</a></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="https://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"><a class="toclink" href="#custom-content-negotiation">Custom content negotiation</a></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"><a class="toclink" href="#example">Example</a></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"><a class="toclink" href="#setting-the-content-negotiation">Setting the content negotiation</a></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>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
732
api-guide/exceptions/index.html
Normal file
732
api-guide/exceptions/index.html
Normal file
|
|
@ -0,0 +1,732 @@
|
|||
<!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="https://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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../status-codes/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../reverse/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<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="#notfound">NotFound</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#methodnotallowed">MethodNotAllowed</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#notacceptable">NotAcceptable</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#unsupportedmediatype">UnsupportedMediaType</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#throttled">Throttled</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#validationerror">ValidationError</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#generic-error-views">Generic Error Views</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#rest_frameworkexceptionsserver_error">rest_framework.exceptions.server_error</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#rest_frameworkexceptionsbad_request">rest_framework.exceptions.bad_request</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<a class="github" href="https://github.com/encode/django-rest-framework/tree/master/rest_framework/exceptions.py">
|
||||
<span class="label label-info">exceptions.py</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<h1 id="exceptions"><a class="toclink" href="#exceptions">Exceptions</a></h1>
|
||||
<blockquote>
|
||||
<p>Exceptions… allow error handling to be organized cleanly in a central or high-level place within the program structure.</p>
|
||||
<p>— Doug Hellmann, <a href="https://doughellmann.com/blog/2009/06/19/python-exception-handling-techniques/">Python Exception Handling Techniques</a></p>
|
||||
</blockquote>
|
||||
<h2 id="exception-handling-in-rest-framework-views"><a class="toclink" href="#exception-handling-in-rest-framework-views">Exception handling in REST framework views</a></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>Most error responses will include a key <code>detail</code> in the body of the response.</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>
|
||||
<p>Validation errors are handled slightly differently, and will include the field names as the keys in the response. If the validation error was not specific to a particular field then it will use the "non_field_errors" key, or whatever string value has been set for the <code>NON_FIELD_ERRORS_KEY</code> setting.</p>
|
||||
<p>Any example validation error might look like this:</p>
|
||||
<pre><code>HTTP/1.1 400 Bad Request
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{"amount": ["A valid integer is required."], "description": ["This field may not be blank."]}
|
||||
</code></pre>
|
||||
<h2 id="custom-exception-handling"><a class="toclink" href="#custom-exception-handling">Custom exception handling</a></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 pair of arguments, the first is the exception to be handled, and the second is a dictionary containing any extra context such as the view currently being handled. The exception handler function 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, context):
|
||||
# Call REST framework's default exception handler first,
|
||||
# to get the standard error response.
|
||||
response = exception_handler(exc, context)
|
||||
|
||||
# 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 context argument is not used by the default handler, but can be useful if the exception handler needs further information such as the view currently being handled, which can be accessed as <code>context['view']</code>.</p>
|
||||
<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"><a class="toclink" href="#api-reference">API Reference</a></h1>
|
||||
<h2 id="apiexception"><a class="toclink" href="#apiexception">APIException</a></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>, <code>.default_detail</code>, and <code>default_code</code> attributes 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.'
|
||||
default_code = 'service_unavailable'
|
||||
</code></pre>
|
||||
<h4 id="inspecting-api-exceptions"><a class="toclink" href="#inspecting-api-exceptions">Inspecting API exceptions</a></h4>
|
||||
<p>There are a number of different properties available for inspecting the status
|
||||
of an API exception. You can use these to build custom exception handling
|
||||
for your project.</p>
|
||||
<p>The available attributes and methods are:</p>
|
||||
<ul>
|
||||
<li><code>.detail</code> - Return the textual description of the error.</li>
|
||||
<li><code>.get_codes()</code> - Return the code identifier of the error.</li>
|
||||
<li><code>.get_full_details()</code> - Return both the textual description and the code identifier.</li>
|
||||
</ul>
|
||||
<p>In most cases the error detail will be a simple item:</p>
|
||||
<pre><code>>>> print(exc.detail)
|
||||
You do not have permission to perform this action.
|
||||
>>> print(exc.get_codes())
|
||||
permission_denied
|
||||
>>> print(exc.get_full_details())
|
||||
{'message':'You do not have permission to perform this action.','code':'permission_denied'}
|
||||
</code></pre>
|
||||
<p>In the case of validation errors the error detail will be either a list or
|
||||
dictionary of items:</p>
|
||||
<pre><code>>>> print(exc.detail)
|
||||
{"name":"This field is required.","age":"A valid integer is required."}
|
||||
>>> print(exc.get_codes())
|
||||
{"name":"required","age":"invalid"}
|
||||
>>> print(exc.get_full_details())
|
||||
{"name":{"message":"This field is required.","code":"required"},"age":{"message":"A valid integer is required.","code":"invalid"}}
|
||||
</code></pre>
|
||||
<h2 id="parseerror"><a class="toclink" href="#parseerror">ParseError</a></h2>
|
||||
<p><strong>Signature:</strong> <code>ParseError(detail=None, code=None)</code></p>
|
||||
<p>Raised if the request contains malformed data when accessing <code>request.data</code>.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "400 Bad Request".</p>
|
||||
<h2 id="authenticationfailed"><a class="toclink" href="#authenticationfailed">AuthenticationFailed</a></h2>
|
||||
<p><strong>Signature:</strong> <code>AuthenticationFailed(detail=None, code=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"><a class="toclink" href="#notauthenticated">NotAuthenticated</a></h2>
|
||||
<p><strong>Signature:</strong> <code>NotAuthenticated(detail=None, code=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"><a class="toclink" href="#permissiondenied">PermissionDenied</a></h2>
|
||||
<p><strong>Signature:</strong> <code>PermissionDenied(detail=None, code=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="notfound"><a class="toclink" href="#notfound">NotFound</a></h2>
|
||||
<p><strong>Signature:</strong> <code>NotFound(detail=None, code=None)</code></p>
|
||||
<p>Raised when a resource does not exists at the given URL. This exception is equivalent to the standard <code>Http404</code> Django exception.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "404 Not Found".</p>
|
||||
<h2 id="methodnotallowed"><a class="toclink" href="#methodnotallowed">MethodNotAllowed</a></h2>
|
||||
<p><strong>Signature:</strong> <code>MethodNotAllowed(method, detail=None, code=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="notacceptable"><a class="toclink" href="#notacceptable">NotAcceptable</a></h2>
|
||||
<p><strong>Signature:</strong> <code>NotAcceptable(detail=None, code=None)</code></p>
|
||||
<p>Raised when an incoming request occurs with an <code>Accept</code> header that cannot be satisfied by any of the available renderers.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "406 Not Acceptable".</p>
|
||||
<h2 id="unsupportedmediatype"><a class="toclink" href="#unsupportedmediatype">UnsupportedMediaType</a></h2>
|
||||
<p><strong>Signature:</strong> <code>UnsupportedMediaType(media_type, detail=None, code=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>.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "415 Unsupported Media Type".</p>
|
||||
<h2 id="throttled"><a class="toclink" href="#throttled">Throttled</a></h2>
|
||||
<p><strong>Signature:</strong> <code>Throttled(wait=None, detail=None, code=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>
|
||||
<h2 id="validationerror"><a class="toclink" href="#validationerror">ValidationError</a></h2>
|
||||
<p><strong>Signature:</strong> <code>ValidationError(detail, code=None)</code></p>
|
||||
<p>The <code>ValidationError</code> exception is slightly different from the other <code>APIException</code> classes:</p>
|
||||
<ul>
|
||||
<li>The <code>detail</code> argument is mandatory, not optional.</li>
|
||||
<li>The <code>detail</code> argument may be a list or dictionary of error details, and may also be a nested data structure.</li>
|
||||
<li>By convention you should import the serializers module and use a fully qualified <code>ValidationError</code> style, in order to differentiate it from Django's built-in validation error. For example. <code>raise serializers.ValidationError('This field must be an integer value.')</code></li>
|
||||
</ul>
|
||||
<p>The <code>ValidationError</code> class should be used for serializer and field validation, and by validator classes. It is also raised when calling <code>serializer.is_valid</code> with the <code>raise_exception</code> keyword argument:</p>
|
||||
<pre><code>serializer.is_valid(raise_exception=True)
|
||||
</code></pre>
|
||||
<p>The generic views use the <code>raise_exception=True</code> flag, which means that you can override the style of validation error responses globally in your API. To do so, use a custom exception handler, as described above.</p>
|
||||
<p>By default this exception results in a response with the HTTP status code "400 Bad Request".</p>
|
||||
<hr />
|
||||
<h1 id="generic-error-views"><a class="toclink" href="#generic-error-views">Generic Error Views</a></h1>
|
||||
<p>Django REST Framework provides two error views suitable for providing generic JSON <code>500</code> Server Error and
|
||||
<code>400</code> Bad Request responses. (Django's default error views provide HTML responses, which may not be appropriate for an
|
||||
API-only application.)</p>
|
||||
<p>Use these as per <a href="https://docs.djangoproject.com/en/dev/topics/http/views/#customizing-error-views">Django's Customizing error views documentation</a>.</p>
|
||||
<h2 id="rest_frameworkexceptionsserver_error"><a class="toclink" href="#rest_frameworkexceptionsserver_error"><code>rest_framework.exceptions.server_error</code></a></h2>
|
||||
<p>Returns a response with status code <code>500</code> and <code>application/json</code> content type.</p>
|
||||
<p>Set as <code>handler500</code>:</p>
|
||||
<pre><code>handler500 = 'rest_framework.exceptions.server_error'
|
||||
</code></pre>
|
||||
<h2 id="rest_frameworkexceptionsbad_request"><a class="toclink" href="#rest_frameworkexceptionsbad_request"><code>rest_framework.exceptions.bad_request</code></a></h2>
|
||||
<p>Returns a response with status code <code>400</code> and <code>application/json</code> content type.</p>
|
||||
<p>Set as <code>handler400</code>:</p>
|
||||
<pre><code>handler400 = 'rest_framework.exceptions.bad_request'
|
||||
</code></pre>
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
</div> <!--/row-->
|
||||
</div> <!--/.fluid-container-->
|
||||
</div> <!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div> <!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
1310
api-guide/fields/index.html
Normal file
1310
api-guide/fields/index.html
Normal file
File diff suppressed because it is too large
Load Diff
826
api-guide/filtering/index.html
Normal file
826
api-guide/filtering/index.html
Normal file
|
|
@ -0,0 +1,826 @@
|
|||
<!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="../../img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="https://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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../pagination/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../throttling/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<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 class="main">
|
||||
<a href="#custom-generic-filtering">Custom generic filtering</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#example">Example</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#customizing-the-interface">Customizing the interface</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#pagination-schemas">Pagination & schemas</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#third-party-packages">Third party packages</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#django-rest-framework-filters-package">Django REST framework filters package</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#django-rest-framework-full-word-search-filter">Django REST framework full word search filter</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#django-url-filter">Django URL Filter</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#drf-url-filters">drf-url-filters</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<a class="github" href="https://github.com/encode/django-rest-framework/tree/master/rest_framework/filters.py">
|
||||
<span class="label label-info">filters.py</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<h1 id="filtering"><a class="toclink" href="#filtering">Filtering</a></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>— <a href="https://docs.djangoproject.com/en/stable/topics/db/queries/#retrieving-specific-objects-with-filters">Django documentation</a></p>
|
||||
</blockquote>
|
||||
<p>The default behavior of REST framework's generic list views is to return the entire queryset for a model manager. Often you will want your API to restrict the items that are returned by the queryset.</p>
|
||||
<p>The simplest way to filter the queryset of any view that subclasses <code>GenericAPIView</code> is to override the <code>.get_queryset()</code> method.</p>
|
||||
<p>Overriding this method allows you to customize the queryset returned by the view in a number of different ways.</p>
|
||||
<h2 id="filtering-against-the-current-user"><a class="toclink" href="#filtering-against-the-current-user">Filtering against the current user</a></h2>
|
||||
<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><code>from myapp.models import Purchase
|
||||
from myapp.serializers import PurchaseSerializer
|
||||
from rest_framework import generics
|
||||
|
||||
class PurchaseList(generics.ListAPIView):
|
||||
serializer_class = PurchaseSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
This view should return a list of all the purchases
|
||||
for the currently authenticated user.
|
||||
"""
|
||||
user = self.request.user
|
||||
return Purchase.objects.filter(purchaser=user)
|
||||
</code></pre>
|
||||
<h2 id="filtering-against-the-url"><a class="toclink" href="#filtering-against-the-url">Filtering against the URL</a></h2>
|
||||
<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><code>url('^purchases/(?P<username>.+)/$', 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><code>class PurchaseList(generics.ListAPIView):
|
||||
serializer_class = PurchaseSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
This view should return a list of all the purchases for
|
||||
the user as determined by the username portion of the URL.
|
||||
"""
|
||||
username = self.kwargs['username']
|
||||
return Purchase.objects.filter(purchaser__username=username)
|
||||
</code></pre>
|
||||
<h2 id="filtering-against-query-parameters"><a class="toclink" href="#filtering-against-query-parameters">Filtering against query parameters</a></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><code>class PurchaseList(generics.ListAPIView):
|
||||
serializer_class = PurchaseSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
Optionally restricts the returned purchases to a given user,
|
||||
by filtering against a `username` query parameter in the URL.
|
||||
"""
|
||||
queryset = Purchase.objects.all()
|
||||
username = self.request.query_params.get('username', None)
|
||||
if username is not None:
|
||||
queryset = queryset.filter(purchaser__username=username)
|
||||
return queryset
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h1 id="generic-filtering"><a class="toclink" href="#generic-filtering">Generic Filtering</a></h1>
|
||||
<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>
|
||||
<p>Generic filters can also present themselves as HTML controls in the browsable API and admin API.</p>
|
||||
<p><img alt="Filter Example" src="../../img/filter-controls.png" /></p>
|
||||
<h2 id="setting-filter-backends"><a class="toclink" href="#setting-filter-backends">Setting filter backends</a></h2>
|
||||
<p>The default filter backends may be set globally, using the <code>DEFAULT_FILTER_BACKENDS</code> setting. For example.</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.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><code>import django_filters.rest_framework
|
||||
from django.contrib.auth.models import User
|
||||
from myapp.serializers import UserSerializer
|
||||
from rest_framework import generics
|
||||
|
||||
class UserListView(generics.ListAPIView):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
filter_backends = [django_filters.rest_framework.DjangoFilterBackend]
|
||||
</code></pre>
|
||||
<h2 id="filtering-and-object-lookups"><a class="toclink" href="#filtering-and-object-lookups">Filtering and object lookups</a></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><code>http://example.com/api/products/4675/?category=clothing&max_price=10.00
|
||||
</code></pre>
|
||||
<h2 id="overriding-the-initial-queryset"><a class="toclink" href="#overriding-the-initial-queryset">Overriding the initial queryset</a></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><code>class PurchasedProductsList(generics.ListAPIView):
|
||||
"""
|
||||
Return a list of all the products that the authenticated
|
||||
user has ever purchased, with optional filtering.
|
||||
"""
|
||||
model = Product
|
||||
serializer_class = ProductSerializer
|
||||
filterset_class = ProductFilter
|
||||
|
||||
def get_queryset(self):
|
||||
user = self.request.user
|
||||
return user.purchase_set.all()
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h1 id="api-guide"><a class="toclink" href="#api-guide">API Guide</a></h1>
|
||||
<h2 id="djangofilterbackend"><a class="toclink" href="#djangofilterbackend">DjangoFilterBackend</a></h2>
|
||||
<p>The <a href="https://django-filter.readthedocs.io/en/latest/index.html"><code>django-filter</code></a> library includes a <code>DjangoFilterBackend</code> class which
|
||||
supports highly customizable field filtering for REST framework.</p>
|
||||
<p>To use <code>DjangoFilterBackend</code>, first install <code>django-filter</code>. Then add <code>django_filters</code> to Django's <code>INSTALLED_APPS</code></p>
|
||||
<pre><code>pip install django-filter
|
||||
</code></pre>
|
||||
<p>You should now either add the filter backend to your settings:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
|
||||
}
|
||||
</code></pre>
|
||||
<p>Or add the filter backend to an individual View or ViewSet.</p>
|
||||
<pre><code>from django_filters.rest_framework import DjangoFilterBackend
|
||||
|
||||
class UserListView(generics.ListAPIView):
|
||||
...
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
</code></pre>
|
||||
<p>If all you need is simple equality-based filtering, you can set a <code>filterset_fields</code> attribute on the view, or viewset, listing the set of fields you wish to filter against.</p>
|
||||
<pre><code>class ProductList(generics.ListAPIView):
|
||||
queryset = Product.objects.all()
|
||||
serializer_class = ProductSerializer
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_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><code>http://example.com/api/products?category=clothing&in_stock=True
|
||||
</code></pre>
|
||||
<p>For more advanced filtering requirements you can specify a <code>FilterSet</code> class that should be used by the view.
|
||||
You can read more about <code>FilterSet</code>s in the <a href="https://django-filter.readthedocs.io/en/latest/index.html">django-filter documentation</a>.
|
||||
It's also recommended that you read the section on <a href="https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html">DRF integration</a>.</p>
|
||||
<h2 id="searchfilter"><a class="toclink" href="#searchfilter">SearchFilter</a></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/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields">Django admin's search functionality</a>.</p>
|
||||
<p>When in use, the browsable API will include a <code>SearchFilter</code> control:</p>
|
||||
<p><img alt="Search Filter" src="../../img/search-filter.png" /></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><code>from rest_framework import filters
|
||||
|
||||
class UserListView(generics.ListAPIView):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = 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><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><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>
|
||||
<ul>
|
||||
<li>'^' Starts-with search.</li>
|
||||
<li>'=' Exact matches.</li>
|
||||
<li>'@' Full-text search. (Currently only supported Django's MySQL backend.)</li>
|
||||
<li>'$' Regex search.</li>
|
||||
</ul>
|
||||
<p>For example:</p>
|
||||
<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>To dynamically change search fields based on request content, it's possible to subclass the <code>SearchFilter</code> and override the <code>get_search_fields()</code> function. For example, the following subclass will only search on <code>title</code> if the query parameter <code>title_only</code> is in the request:</p>
|
||||
<pre><code>from rest_framework import filters
|
||||
|
||||
class CustomSearchFilter(filters.SearchFilter):
|
||||
def get_search_fields(self, view, request):
|
||||
if request.query_params.get('title_only'):
|
||||
return ['title']
|
||||
return super(CustomSearchFilter, self).get_search_fields(view, request)
|
||||
</code></pre>
|
||||
<p>For more details, see the <a href="https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields">Django documentation</a>.</p>
|
||||
<hr />
|
||||
<h2 id="orderingfilter"><a class="toclink" href="#orderingfilter">OrderingFilter</a></h2>
|
||||
<p>The <code>OrderingFilter</code> class supports simple query parameter controlled ordering of results.</p>
|
||||
<p><img alt="Ordering Filter" src="../../img/ordering-filter.png" /></p>
|
||||
<p>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><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><code>http://example.com/api/users?ordering=-username
|
||||
</code></pre>
|
||||
<p>Multiple orderings may also be specified:</p>
|
||||
<pre><code>http://example.com/api/users?ordering=account,username
|
||||
</code></pre>
|
||||
<h3 id="specifying-which-fields-may-be-ordered-against"><a class="toclink" href="#specifying-which-fields-may-be-ordered-against">Specifying which fields may be ordered against</a></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><code>class UserListView(generics.ListAPIView):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
filter_backends = [filters.OrderingFilter]
|
||||
ordering_fields = ['username', 'email']
|
||||
</code></pre>
|
||||
<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><code>class BookingsListView(generics.ListAPIView):
|
||||
queryset = Booking.objects.all()
|
||||
serializer_class = BookingSerializer
|
||||
filter_backends = [filters.OrderingFilter]
|
||||
ordering_fields = '__all__'
|
||||
</code></pre>
|
||||
<h3 id="specifying-a-default-ordering"><a class="toclink" href="#specifying-a-default-ordering">Specifying a default ordering</a></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><code>class UserListView(generics.ListAPIView):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
filter_backends = [filters.OrderingFilter]
|
||||
ordering_fields = ['username', 'email']
|
||||
ordering = ['username']
|
||||
</code></pre>
|
||||
<p>The <code>ordering</code> attribute may be either a string or a list/tuple of strings.</p>
|
||||
<hr />
|
||||
<h1 id="custom-generic-filtering"><a class="toclink" href="#custom-generic-filtering">Custom generic filtering</a></h1>
|
||||
<p>You can also provide your own generic filtering backend, or write an installable app for other developers to use.</p>
|
||||
<p>To do so override <code>BaseFilterBackend</code>, and override the <code>.filter_queryset(self, request, queryset, view)</code> method. The method should return a new, filtered queryset.</p>
|
||||
<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"><a class="toclink" href="#example">Example</a></h2>
|
||||
<p>For example, you might need to restrict users to only being able to see objects they created.</p>
|
||||
<pre><code>class IsOwnerFilterBackend(filters.BaseFilterBackend):
|
||||
"""
|
||||
Filter that only allows users to see their own objects.
|
||||
"""
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
return queryset.filter(owner=request.user)
|
||||
</code></pre>
|
||||
<p>We could achieve the same behavior by overriding <code>get_queryset()</code> on the views, but using a filter backend allows you to more easily add this restriction to multiple views, or to apply it across the entire API.</p>
|
||||
<h2 id="customizing-the-interface"><a class="toclink" href="#customizing-the-interface">Customizing the interface</a></h2>
|
||||
<p>Generic filters may also present an interface in the browsable API. To do so you should implement a <code>to_html()</code> method which returns a rendered HTML representation of the filter. This method should have the following signature:</p>
|
||||
<p><code>to_html(self, request, queryset, view)</code></p>
|
||||
<p>The method should return a rendered HTML string.</p>
|
||||
<h2 id="pagination-schemas"><a class="toclink" href="#pagination-schemas">Pagination & schemas</a></h2>
|
||||
<p>You can also make the filter controls available to the schema autogeneration
|
||||
that REST framework provides, by implementing a <code>get_schema_fields()</code> method. This method should have the following signature:</p>
|
||||
<p><code>get_schema_fields(self, view)</code></p>
|
||||
<p>The method should return a list of <code>coreapi.Field</code> instances.</p>
|
||||
<h1 id="third-party-packages"><a class="toclink" href="#third-party-packages">Third party packages</a></h1>
|
||||
<p>The following third party packages provide additional filter implementations.</p>
|
||||
<h2 id="django-rest-framework-filters-package"><a class="toclink" href="#django-rest-framework-filters-package">Django REST framework filters package</a></h2>
|
||||
<p>The <a href="https://github.com/philipn/django-rest-framework-filters">django-rest-framework-filters 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>
|
||||
<h2 id="django-rest-framework-full-word-search-filter"><a class="toclink" href="#django-rest-framework-full-word-search-filter">Django REST framework full word search filter</a></h2>
|
||||
<p>The <a href="https://github.com/trollknurr/django-rest-framework-word-search-filter">djangorestframework-word-filter</a> developed as alternative to <code>filters.SearchFilter</code> which will search full word in text, or exact match.</p>
|
||||
<h2 id="django-url-filter"><a class="toclink" href="#django-url-filter">Django URL Filter</a></h2>
|
||||
<p><a href="https://github.com/miki725/django-url-filter">django-url-filter</a> provides a safe way to filter data via human-friendly URLs. It works very similar to DRF serializers and fields in a sense that they can be nested except they are called filtersets and filters. That provides easy way to filter related data. Also this library is generic-purpose so it can be used to filter other sources of data and not only Django <code>QuerySet</code>s.</p>
|
||||
<h2 id="drf-url-filters"><a class="toclink" href="#drf-url-filters">drf-url-filters</a></h2>
|
||||
<p><a href="https://github.com/manjitkumar/drf-url-filters">drf-url-filter</a> is a simple Django app to apply filters on drf <code>ModelViewSet</code>'s <code>Queryset</code> in a clean, simple and configurable way. It also supports validations on incoming query params and their values. A beautiful python package <code>Voluptuous</code> is being used for validations on the incoming query parameters. The best part about voluptuous is you can define your own validations as per your query params requirements.</p>
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
</div> <!--/row-->
|
||||
</div> <!--/.fluid-container-->
|
||||
</div> <!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div> <!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
561
api-guide/format-suffixes/index.html
Normal file
561
api-guide/format-suffixes/index.html
Normal file
|
|
@ -0,0 +1,561 @@
|
|||
<!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="https://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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../reverse/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../schemas/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<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="#query-parameter-formats">Query parameter formats</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#accept-headers-vs-format-suffixes">Accept headers vs. format suffixes</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<a class="github" href="https://github.com/encode/django-rest-framework/tree/master/rest_framework/urlpatterns.py">
|
||||
<span class="label label-info">urlpatterns.py</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<h1 id="format-suffixes"><a class="toclink" href="#format-suffixes">Format suffixes</a></h1>
|
||||
<blockquote>
|
||||
<p>Section 6.2.1 does not say that content negotiation should be
|
||||
used all the time.</p>
|
||||
<p>— 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"><a class="toclink" href="#format_suffix_patterns">format_suffix_patterns</a></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<pk>[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>
|
||||
<h3 id="using-with-i18n_patterns"><a class="toclink" href="#using-with-i18n_patterns">Using with <code>i18n_patterns</code></a></h3>
|
||||
<p>If using the <code>i18n_patterns</code> function provided by Django, as well as <code>format_suffix_patterns</code> you should make sure that the <code>i18n_patterns</code> function is applied as the final, or outermost function. For example:</p>
|
||||
<pre><code>url patterns = [
|
||||
…
|
||||
]
|
||||
|
||||
urlpatterns = i18n_patterns(
|
||||
format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
|
||||
)
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h2 id="query-parameter-formats"><a class="toclink" href="#query-parameter-formats">Query parameter formats</a></h2>
|
||||
<p>An alternative to the format suffixes is to include the requested format in a query parameter. REST framework provides this option by default, and it is used in the browsable API to switch between differing available representations.</p>
|
||||
<p>To select a representation using its short format, use the <code>format</code> query parameter. For example: <code>http://example.com/organizations/?format=csv</code>.</p>
|
||||
<p>The name of this query parameter can be modified using the <code>URL_FORMAT_OVERRIDE</code> setting. Set the value to <code>None</code> to disable this behavior.</p>
|
||||
<hr />
|
||||
<h2 id="accept-headers-vs-format-suffixes"><a class="toclink" href="#accept-headers-vs-format-suffixes">Accept headers vs. format suffixes</a></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>“That's why I always prefer extensions. Neither choice has anything to do with REST.” — Roy Fielding, <a href="https://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/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>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
854
api-guide/generic-views/index.html
Normal file
854
api-guide/generic-views/index.html
Normal file
|
|
@ -0,0 +1,854 @@
|
|||
<!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="../../img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="https://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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../viewsets/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../views/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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 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="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<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="#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-multiple-models">Django Rest Multiple Models</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<a class="github" href="https://github.com/encode/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/encode/django-rest-framework/tree/master/rest_framework/generics.py">
|
||||
<span class="label label-info">generics.py</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<h1 id="generic-views"><a class="toclink" href="#generic-views">Generic views</a></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>— <a href="https://docs.djangoproject.com/en/stable/ref/class-based-views/#base-vs-generic-views">Django Documentation</a></p>
|
||||
</blockquote>
|
||||
<p>One of the key benefits of class-based views is the way they allow you to compose bits of reusable behavior. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns.</p>
|
||||
<p>The generic views provided by REST framework allow you to quickly build API views that map closely to your database models.</p>
|
||||
<p>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"><a class="toclink" href="#examples">Examples</a></h2>
|
||||
<p>Typically when using the generic views, you'll override the view, and set several class attributes.</p>
|
||||
<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
|
||||
|
||||
class UserList(generics.ListCreateAPIView):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
permission_classes = [IsAdminUser]
|
||||
</code></pre>
|
||||
<p>For more complex cases you might also want to override various methods on the view class. For example.</p>
|
||||
<pre><code>class UserList(generics.ListCreateAPIView):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
permission_classes = [IsAdminUser]
|
||||
|
||||
def list(self, request):
|
||||
# Note the use of `get_queryset()` instead of `self.queryset`
|
||||
queryset = self.get_queryset()
|
||||
serializer = UserSerializer(queryset, many=True)
|
||||
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><code>url(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h1 id="api-reference"><a class="toclink" href="#api-reference">API Reference</a></h1>
|
||||
<h2 id="genericapiview"><a class="toclink" href="#genericapiview">GenericAPIView</a></h2>
|
||||
<p>This class extends REST framework's <code>APIView</code> class, adding commonly required behavior for standard list and detail views.</p>
|
||||
<p>Each of the concrete generic views provided is built by combining <code>GenericAPIView</code>, with one or more mixin classes.</p>
|
||||
<h3 id="attributes"><a class="toclink" href="#attributes">Attributes</a></h3>
|
||||
<p><strong>Basic settings</strong>:</p>
|
||||
<p>The following attributes control the basic view behavior.</p>
|
||||
<ul>
|
||||
<li><code>queryset</code> - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the <code>get_queryset()</code> method. If you are overriding a view method, it is important that you call <code>get_queryset()</code> instead of accessing this property directly, as <code>queryset</code> will get evaluated once, and those results will be cached for all subsequent requests.</li>
|
||||
<li><code>serializer_class</code> - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the <code>get_serializer_class()</code> method.</li>
|
||||
<li><code>lookup_field</code> - The model field that should be used to for performing object lookup of individual model instances. Defaults to <code>'pk'</code>. Note that when using hyperlinked APIs you'll need to ensure that <em>both</em> the API views <em>and</em> the serializer classes set the lookup fields if you need to use a custom value.</li>
|
||||
<li><code>lookup_url_kwarg</code> - The URL keyword argument that should be used for object lookup. The URL conf should include a keyword argument corresponding to this value. If unset this defaults to using the same value as <code>lookup_field</code>.</li>
|
||||
</ul>
|
||||
<p><strong>Pagination</strong>:</p>
|
||||
<p>The following attributes are used to control pagination when used with list views.</p>
|
||||
<ul>
|
||||
<li><code>pagination_class</code> - The pagination class that should be used when paginating list results. Defaults to the same value as the <code>DEFAULT_PAGINATION_CLASS</code> setting, which is <code>'rest_framework.pagination.PageNumberPagination'</code>. Setting <code>pagination_class=None</code> will disable pagination on this view.</li>
|
||||
</ul>
|
||||
<p><strong>Filtering</strong>:</p>
|
||||
<ul>
|
||||
<li><code>filter_backends</code> - A list of filter backend classes that should be used for filtering the queryset. Defaults to the same value as the <code>DEFAULT_FILTER_BACKENDS</code> setting.</li>
|
||||
</ul>
|
||||
<h3 id="methods"><a class="toclink" href="#methods">Methods</a></h3>
|
||||
<p><strong>Base methods</strong>:</p>
|
||||
<h4 id="get_querysetself"><a class="toclink" href="#get_querysetself"><code>get_queryset(self)</code></a></h4>
|
||||
<p>Returns the queryset that should be used for list views, and that should be used as the base for lookups in detail views. Defaults to returning the queryset specified by the <code>queryset</code> attribute.</p>
|
||||
<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><code>def get_queryset(self):
|
||||
user = self.request.user
|
||||
return user.accounts.all()
|
||||
</code></pre>
|
||||
<h4 id="get_objectself"><a class="toclink" href="#get_objectself"><code>get_object(self)</code></a></h4>
|
||||
<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><code>def get_object(self):
|
||||
queryset = self.get_queryset()
|
||||
filter = {}
|
||||
for field in self.multiple_lookup_fields:
|
||||
filter[field] = self.kwargs[field]
|
||||
|
||||
obj = get_object_or_404(queryset, **filter)
|
||||
self.check_object_permissions(self.request, obj)
|
||||
return obj
|
||||
</code></pre>
|
||||
<p>Note that if your API doesn't include any object level permissions, you may optionally exclude the <code>self.check_object_permissions</code>, and simply return the object from the <code>get_object_or_404</code> lookup.</p>
|
||||
<h4 id="filter_querysetself-queryset"><a class="toclink" href="#filter_querysetself-queryset"><code>filter_queryset(self, queryset)</code></a></h4>
|
||||
<p>Given a queryset, filter it with whichever filter backends are in use, returning a new queryset.</p>
|
||||
<p>For example:</p>
|
||||
<pre><code>def filter_queryset(self, queryset):
|
||||
filter_backends = [CategoryFilter]
|
||||
|
||||
if 'geo_route' in self.request.query_params:
|
||||
filter_backends = [GeoRouteFilter, CategoryFilter]
|
||||
elif 'geo_point' in self.request.query_params:
|
||||
filter_backends = [GeoPointFilter, CategoryFilter]
|
||||
|
||||
for backend in list(filter_backends):
|
||||
queryset = backend().filter_queryset(self.request, queryset, view=self)
|
||||
|
||||
return queryset
|
||||
</code></pre>
|
||||
<h4 id="get_serializer_classself"><a class="toclink" href="#get_serializer_classself"><code>get_serializer_class(self)</code></a></h4>
|
||||
<p>Returns the class that should be used for the serializer. Defaults to returning the <code>serializer_class</code> attribute.</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><code>def get_serializer_class(self):
|
||||
if self.request.user.is_staff:
|
||||
return FullAccountSerializer
|
||||
return BasicAccountSerializer
|
||||
</code></pre>
|
||||
<p><strong>Save and deletion hooks</strong>:</p>
|
||||
<p>The following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior.</p>
|
||||
<ul>
|
||||
<li><code>perform_create(self, serializer)</code> - Called by <code>CreateModelMixin</code> when saving a new object instance.</li>
|
||||
<li><code>perform_update(self, serializer)</code> - Called by <code>UpdateModelMixin</code> when saving an existing object instance.</li>
|
||||
<li><code>perform_destroy(self, instance)</code> - Called by <code>DestroyModelMixin</code> when deleting an object instance.</li>
|
||||
</ul>
|
||||
<p>These hooks are particularly useful for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument.</p>
|
||||
<pre><code>def perform_create(self, serializer):
|
||||
serializer.save(user=self.request.user)
|
||||
</code></pre>
|
||||
<p>These override points are also particularly useful for adding behavior that occurs before or after saving an object, such as emailing a confirmation, or logging the update.</p>
|
||||
<pre><code>def perform_update(self, serializer):
|
||||
instance = serializer.save()
|
||||
send_email_confirmation(user=self.request.user, modified=instance)
|
||||
</code></pre>
|
||||
<p>You can also use these hooks to provide additional validation, by raising a <code>ValidationError()</code>. This can be useful if you need some validation logic to apply at the point of database save. For example:</p>
|
||||
<pre><code>def perform_create(self, serializer):
|
||||
queryset = SignupRequest.objects.filter(user=self.request.user)
|
||||
if queryset.exists():
|
||||
raise ValidationError('You have already signed up')
|
||||
serializer.save(user=self.request.user)
|
||||
</code></pre>
|
||||
<p><strong>Note</strong>: These methods replace the old-style version 2.x <code>pre_save</code>, <code>post_save</code>, <code>pre_delete</code> and <code>post_delete</code> methods, which are no longer available.</p>
|
||||
<p><strong>Other methods</strong>:</p>
|
||||
<p>You won't typically need to override the following methods, although you might need to call into them if you're writing custom views using <code>GenericAPIView</code>.</p>
|
||||
<ul>
|
||||
<li><code>get_serializer_context(self)</code> - Returns a dictionary containing any extra context that should be supplied to the serializer. Defaults to including <code>'request'</code>, <code>'view'</code> and <code>'format'</code> keys.</li>
|
||||
<li><code>get_serializer(self, instance=None, data=None, many=False, partial=False)</code> - Returns a serializer instance.</li>
|
||||
<li><code>get_paginated_response(self, data)</code> - Returns a paginated style <code>Response</code> object.</li>
|
||||
<li><code>paginate_queryset(self, queryset)</code> - Paginate a queryset if required, either returning a page object, or <code>None</code> if pagination is not configured for this view.</li>
|
||||
<li><code>filter_queryset(self, queryset)</code> - Given a queryset, filter it with whichever filter backends are in use, returning a new queryset.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h1 id="mixins"><a class="toclink" href="#mixins">Mixins</a></h1>
|
||||
<p>The mixin classes provide the actions that are used to provide the basic view behavior. Note that the mixin classes provide action methods rather than defining the handler methods, such as <code>.get()</code> and <code>.post()</code>, directly. This allows for more flexible composition of behavior.</p>
|
||||
<p>The mixin classes can be imported from <code>rest_framework.mixins</code>.</p>
|
||||
<h2 id="listmodelmixin"><a class="toclink" href="#listmodelmixin">ListModelMixin</a></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>
|
||||
<h2 id="createmodelmixin"><a class="toclink" href="#createmodelmixin">CreateModelMixin</a></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>
|
||||
<p>If the request data provided for creating the object was invalid, a <code>400 Bad Request</code> response will be returned, with the error details as the body of the response.</p>
|
||||
<h2 id="retrievemodelmixin"><a class="toclink" href="#retrievemodelmixin">RetrieveModelMixin</a></h2>
|
||||
<p>Provides a <code>.retrieve(request, *args, **kwargs)</code> method, that implements returning an existing model instance in a response.</p>
|
||||
<p>If an object can be retrieved this returns a <code>200 OK</code> response, with a serialized representation of the object as the body of the response. Otherwise it will return a <code>404 Not Found</code>.</p>
|
||||
<h2 id="updatemodelmixin"><a class="toclink" href="#updatemodelmixin">UpdateModelMixin</a></h2>
|
||||
<p>Provides a <code>.update(request, *args, **kwargs)</code> method, that implements updating and saving an existing model instance.</p>
|
||||
<p>Also provides a <code>.partial_update(request, *args, **kwargs)</code> method, which is similar to the <code>update</code> method, except that all fields for the update will be optional. This allows support for HTTP <code>PATCH</code> requests.</p>
|
||||
<p>If an object is updated this returns a <code>200 OK</code> response, with a serialized representation of the object as the body of the response.</p>
|
||||
<p>If the request data provided for updating the object was invalid, a <code>400 Bad Request</code> response will be returned, with the error details as the body of the response.</p>
|
||||
<h2 id="destroymodelmixin"><a class="toclink" href="#destroymodelmixin">DestroyModelMixin</a></h2>
|
||||
<p>Provides a <code>.destroy(request, *args, **kwargs)</code> method, that implements deletion of an existing model instance.</p>
|
||||
<p>If an object is deleted this returns a <code>204 No Content</code> response, otherwise it will return a <code>404 Not Found</code>.</p>
|
||||
<hr />
|
||||
<h1 id="concrete-view-classes"><a class="toclink" href="#concrete-view-classes">Concrete View Classes</a></h1>
|
||||
<p>The following classes are the concrete generic views. If you're using generic views this is normally the level you'll be working at unless you need heavily customized behavior.</p>
|
||||
<p>The view classes can be imported from <code>rest_framework.generics</code>.</p>
|
||||
<h2 id="createapiview"><a class="toclink" href="#createapiview">CreateAPIView</a></h2>
|
||||
<p>Used for <strong>create-only</strong> endpoints.</p>
|
||||
<p>Provides a <code>post</code> method handler.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#createmodelmixin">CreateModelMixin</a></p>
|
||||
<h2 id="listapiview"><a class="toclink" href="#listapiview">ListAPIView</a></h2>
|
||||
<p>Used for <strong>read-only</strong> endpoints to represent a <strong>collection of model instances</strong>.</p>
|
||||
<p>Provides a <code>get</code> method handler.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#listmodelmixin">ListModelMixin</a></p>
|
||||
<h2 id="retrieveapiview"><a class="toclink" href="#retrieveapiview">RetrieveAPIView</a></h2>
|
||||
<p>Used for <strong>read-only</strong> endpoints to represent a <strong>single model instance</strong>.</p>
|
||||
<p>Provides a <code>get</code> method handler.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#retrievemodelmixin">RetrieveModelMixin</a></p>
|
||||
<h2 id="destroyapiview"><a class="toclink" href="#destroyapiview">DestroyAPIView</a></h2>
|
||||
<p>Used for <strong>delete-only</strong> endpoints for a <strong>single model instance</strong>.</p>
|
||||
<p>Provides a <code>delete</code> method handler.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#destroymodelmixin">DestroyModelMixin</a></p>
|
||||
<h2 id="updateapiview"><a class="toclink" href="#updateapiview">UpdateAPIView</a></h2>
|
||||
<p>Used for <strong>update-only</strong> endpoints for a <strong>single model instance</strong>.</p>
|
||||
<p>Provides <code>put</code> and <code>patch</code> method handlers.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#updatemodelmixin">UpdateModelMixin</a></p>
|
||||
<h2 id="listcreateapiview"><a class="toclink" href="#listcreateapiview">ListCreateAPIView</a></h2>
|
||||
<p>Used for <strong>read-write</strong> endpoints to represent a <strong>collection of model instances</strong>.</p>
|
||||
<p>Provides <code>get</code> and <code>post</code> method handlers.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#listmodelmixin">ListModelMixin</a>, <a href="#createmodelmixin">CreateModelMixin</a></p>
|
||||
<h2 id="retrieveupdateapiview"><a class="toclink" href="#retrieveupdateapiview">RetrieveUpdateAPIView</a></h2>
|
||||
<p>Used for <strong>read or update</strong> endpoints to represent a <strong>single model instance</strong>.</p>
|
||||
<p>Provides <code>get</code>, <code>put</code> and <code>patch</code> method handlers.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#retrievemodelmixin">RetrieveModelMixin</a>, <a href="#updatemodelmixin">UpdateModelMixin</a></p>
|
||||
<h2 id="retrievedestroyapiview"><a class="toclink" href="#retrievedestroyapiview">RetrieveDestroyAPIView</a></h2>
|
||||
<p>Used for <strong>read or delete</strong> endpoints to represent a <strong>single model instance</strong>.</p>
|
||||
<p>Provides <code>get</code> and <code>delete</code> method handlers.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#retrievemodelmixin">RetrieveModelMixin</a>, <a href="#destroymodelmixin">DestroyModelMixin</a></p>
|
||||
<h2 id="retrieveupdatedestroyapiview"><a class="toclink" href="#retrieveupdatedestroyapiview">RetrieveUpdateDestroyAPIView</a></h2>
|
||||
<p>Used for <strong>read-write-delete</strong> endpoints to represent a <strong>single model instance</strong>.</p>
|
||||
<p>Provides <code>get</code>, <code>put</code>, <code>patch</code> and <code>delete</code> method handlers.</p>
|
||||
<p>Extends: <a href="#genericapiview">GenericAPIView</a>, <a href="#retrievemodelmixin">RetrieveModelMixin</a>, <a href="#updatemodelmixin">UpdateModelMixin</a>, <a href="#destroymodelmixin">DestroyModelMixin</a></p>
|
||||
<hr />
|
||||
<h1 id="customizing-the-generic-views"><a class="toclink" href="#customizing-the-generic-views">Customizing the generic views</a></h1>
|
||||
<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"><a class="toclink" href="#creating-custom-mixins">Creating custom mixins</a></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><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.
|
||||
"""
|
||||
def get_object(self):
|
||||
queryset = self.get_queryset() # Get the base queryset
|
||||
queryset = self.filter_queryset(queryset) # Apply any filter backends
|
||||
filter = {}
|
||||
for field in self.lookup_fields:
|
||||
if self.kwargs[field]: # Ignore empty fields.
|
||||
filter[field] = self.kwargs[field]
|
||||
obj = get_object_or_404(queryset, **filter) # Lookup the object
|
||||
self.check_object_permissions(self.request, obj)
|
||||
return obj
|
||||
</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><code>class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
lookup_fields = ['account', 'username']
|
||||
</code></pre>
|
||||
<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"><a class="toclink" href="#creating-custom-base-classes">Creating custom base classes</a></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><code>class BaseRetrieveView(MultipleFieldLookupMixin,
|
||||
generics.RetrieveAPIView):
|
||||
pass
|
||||
|
||||
class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
|
||||
generics.RetrieveUpdateDestroyAPIView):
|
||||
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"><a class="toclink" href="#put-as-create">PUT as create</a></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"><a class="toclink" href="#third-party-packages">Third party packages</a></h1>
|
||||
<p>The following third party packages provide additional generic view implementations.</p>
|
||||
<h2 id="django-rest-multiple-models"><a class="toclink" href="#django-rest-multiple-models">Django Rest Multiple Models</a></h2>
|
||||
<p><a href="https://github.com/MattBroach/DjangoRestMultipleModels">Django Rest Multiple Models</a> provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.</p>
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
</div> <!--/row-->
|
||||
</div> <!--/.fluid-container-->
|
||||
</div> <!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div> <!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
603
api-guide/metadata/index.html
Normal file
603
api-guide/metadata/index.html
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
<!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="../../img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="https://www.django-rest-framework.org/api-guide/metadata/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Django, API, REST, Metadata">
|
||||
<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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../schemas/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../content-negotiation/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li class="active" >
|
||||
<a href="./">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<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>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#third-party-packages">Third party packages</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#drf-schema-adapter">DRF-schema-adapter</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<a class="github" href="https://github.com/encode/django-rest-framework/tree/master/rest_framework/metadata.py">
|
||||
<span class="label label-info">metadata.py</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<h1 id="metadata"><a class="toclink" href="#metadata">Metadata</a></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>— <a href="https://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><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"><a class="toclink" href="#setting-the-metadata-scheme">Setting the metadata scheme</a></h2>
|
||||
<p>You can set the metadata class globally using the <code>'DEFAULT_METADATA_CLASS'</code> settings key:</p>
|
||||
<pre><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><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"><a class="toclink" href="#creating-schema-endpoints">Creating schema endpoints</a></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><code>@action(methods=['GET'], detail=False)
|
||||
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"><a class="toclink" href="#custom-metadata-classes">Custom metadata classes</a></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="https://json-schema.org/">JSON schema</a>, or returning debug information to admin users.</p>
|
||||
<h2 id="example"><a class="toclink" href="#example">Example</a></h2>
|
||||
<p>The following class could be used to limit the information that is returned to <code>OPTIONS</code> requests.</p>
|
||||
<pre><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>
|
||||
<p>Then configure your settings to use this custom class:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_METADATA_CLASS': 'myproject.apps.core.MinimalMetadata'
|
||||
}
|
||||
</code></pre>
|
||||
<h1 id="third-party-packages"><a class="toclink" href="#third-party-packages">Third party packages</a></h1>
|
||||
<p>The following third party packages provide additional metadata implementations.</p>
|
||||
<h2 id="drf-schema-adapter"><a class="toclink" href="#drf-schema-adapter">DRF-schema-adapter</a></h2>
|
||||
<p><a href="https://github.com/drf-forms/drf-schema-adapter">drf-schema-adapter</a> is a set of tools that makes it easier to provide schema information to frontend frameworks and libraries. It provides a metadata mixin as well as 2 metadata classes and several adapters suitable to generate <a href="https://json-schema.org/">json-schema</a> as well as schema information readable by various libraries.</p>
|
||||
<p>You can also write your own adapter to work with your specific frontend.
|
||||
If you wish to do so, it also provides an exporter that can export those schema information to json files.</p>
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
</div> <!--/row-->
|
||||
</div> <!--/.fluid-container-->
|
||||
</div> <!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div> <!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
784
api-guide/pagination/index.html
Normal file
784
api-guide/pagination/index.html
Normal file
|
|
@ -0,0 +1,784 @@
|
|||
<!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="https://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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../versioning/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../filtering/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/funding/">Funding</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/jobs/">Jobs</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
<!-- Search Modal -->
|
||||
<div id="mkdocs_search_modal" 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">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<form role="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
|
||||
</div>
|
||||
</form>
|
||||
<div id="mkdocs-search-results"></div>
|
||||
</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">
|
||||
<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="#setting-the-pagination-style">Setting the pagination style</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#modifying-the-pagination-style">Modifying the pagination style</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#api-reference">API Reference</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#pagenumberpagination">PageNumberPagination</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#limitoffsetpagination">LimitOffsetPagination</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#cursorpagination">CursorPagination</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#custom-pagination-styles">Custom pagination styles</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#example">Example</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#using-your-custom-pagination-class">Using your custom pagination class</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#pagination-schemas">Pagination & schemas</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#html-pagination-controls">HTML pagination controls</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#customizing-the-controls">Customizing the controls</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="main">
|
||||
<a href="#third-party-packages">Third party packages</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
<a href="#drf-extensions">DRF-extensions</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#drf-proxy-pagination">drf-proxy-pagination</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#link-header-pagination">link-header-pagination</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<div id="sidebarInclude">
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
|
||||
|
||||
|
||||
<a class="github" href="https://github.com/encode/django-rest-framework/tree/master/rest_framework/pagination.py">
|
||||
<span class="label label-info">pagination.py</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<h1 id="pagination"><a class="toclink" href="#pagination">Pagination</a></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>— <a href="https://docs.djangoproject.com/en/stable/topics/pagination/">Django documentation</a></p>
|
||||
</blockquote>
|
||||
<p>REST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.</p>
|
||||
<p>The pagination API can support either:</p>
|
||||
<ul>
|
||||
<li>Pagination links that are provided as part of the content of the response.</li>
|
||||
<li>Pagination links that are included in response headers, such as <code>Content-Range</code> or <code>Link</code>.</li>
|
||||
</ul>
|
||||
<p>The built-in styles currently all use links included as part of the content of the response. This style is more accessible when using the browsable API.</p>
|
||||
<p>Pagination is only performed automatically if you're using the generic views or viewsets. If you're using a regular <code>APIView</code>, you'll need to call into the pagination API yourself to ensure you return a paginated response. See the source code for the <code>mixins.ListModelMixin</code> and <code>generics.GenericAPIView</code> classes for an example.</p>
|
||||
<p>Pagination can be turned off by setting the pagination class to <code>None</code>.</p>
|
||||
<h2 id="setting-the-pagination-style"><a class="toclink" href="#setting-the-pagination-style">Setting the pagination style</a></h2>
|
||||
<p>The pagination style may be set globally, using the <code>DEFAULT_PAGINATION_CLASS</code> and <code>PAGE_SIZE</code> setting keys. For example, to use the built-in limit/offset pagination, you would do something like this:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
|
||||
'PAGE_SIZE': 100
|
||||
}
|
||||
</code></pre>
|
||||
<p>Note that you need to set both the pagination class, and the page size that should be used. Both <code>DEFAULT_PAGINATION_CLASS</code> and <code>PAGE_SIZE</code> are <code>None</code> by default.</p>
|
||||
<p>You can also set the pagination class on an individual view by using the <code>pagination_class</code> attribute. Typically you'll want to use the same pagination style throughout your API, although you might want to vary individual aspects of the pagination, such as default or maximum page size, on a per-view basis.</p>
|
||||
<h2 id="modifying-the-pagination-style"><a class="toclink" href="#modifying-the-pagination-style">Modifying the pagination style</a></h2>
|
||||
<p>If you want to modify particular aspects of the pagination style, you'll want to override one of the pagination classes, and set the attributes that you want to change.</p>
|
||||
<pre><code>class LargeResultsSetPagination(PageNumberPagination):
|
||||
page_size = 1000
|
||||
page_size_query_param = 'page_size'
|
||||
max_page_size = 10000
|
||||
|
||||
class StandardResultsSetPagination(PageNumberPagination):
|
||||
page_size = 100
|
||||
page_size_query_param = 'page_size'
|
||||
max_page_size = 1000
|
||||
</code></pre>
|
||||
<p>You can then apply your new style to a view using the <code>pagination_class</code> attribute:</p>
|
||||
<pre><code>class BillingRecordsView(generics.ListAPIView):
|
||||
queryset = Billing.objects.all()
|
||||
serializer_class = BillingRecordsSerializer
|
||||
pagination_class = LargeResultsSetPagination
|
||||
</code></pre>
|
||||
<p>Or apply the style globally, using the <code>DEFAULT_PAGINATION_CLASS</code> settings key. For example:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
|
||||
}
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h1 id="api-reference"><a class="toclink" href="#api-reference">API Reference</a></h1>
|
||||
<h2 id="pagenumberpagination"><a class="toclink" href="#pagenumberpagination">PageNumberPagination</a></h2>
|
||||
<p>This pagination style accepts a single number page number in the request query parameters.</p>
|
||||
<p><strong>Request</strong>:</p>
|
||||
<pre><code>GET https://api.example.org/accounts/?page=4
|
||||
</code></pre>
|
||||
<p><strong>Response</strong>:</p>
|
||||
<pre><code>HTTP 200 OK
|
||||
{
|
||||
"count": 1023
|
||||
"next": "https://api.example.org/accounts/?page=5",
|
||||
"previous": "https://api.example.org/accounts/?page=3",
|
||||
"results": [
|
||||
…
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<h4 id="setup"><a class="toclink" href="#setup">Setup</a></h4>
|
||||
<p>To enable the <code>PageNumberPagination</code> style globally, use the following configuration, and set the <code>PAGE_SIZE</code> as desired:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
||||
'PAGE_SIZE': 100
|
||||
}
|
||||
</code></pre>
|
||||
<p>On <code>GenericAPIView</code> subclasses you may also set the <code>pagination_class</code> attribute to select <code>PageNumberPagination</code> on a per-view basis.</p>
|
||||
<h4 id="configuration"><a class="toclink" href="#configuration">Configuration</a></h4>
|
||||
<p>The <code>PageNumberPagination</code> class includes a number of attributes that may be overridden to modify the pagination style.</p>
|
||||
<p>To set these attributes you should override the <code>PageNumberPagination</code> class, and then enable your custom pagination class as above.</p>
|
||||
<ul>
|
||||
<li><code>django_paginator_class</code> - The Django Paginator class to use. Default is <code>django.core.paginator.Paginator</code>, which should be fine for most use cases.</li>
|
||||
<li><code>page_size</code> - A numeric value indicating the page size. If set, this overrides the <code>PAGE_SIZE</code> setting. Defaults to the same value as the <code>PAGE_SIZE</code> settings key.</li>
|
||||
<li><code>page_query_param</code> - A string value indicating the name of the query parameter to use for the pagination control.</li>
|
||||
<li><code>page_size_query_param</code> - If set, this is a string value indicating the name of a query parameter that allows the client to set the page size on a per-request basis. Defaults to <code>None</code>, indicating that the client may not control the requested page size.</li>
|
||||
<li><code>max_page_size</code> - If set, this is a numeric value indicating the maximum allowable requested page size. This attribute is only valid if <code>page_size_query_param</code> is also set.</li>
|
||||
<li><code>last_page_strings</code> - A list or tuple of string values indicating values that may be used with the <code>page_query_param</code> to request the final page in the set. Defaults to <code>('last',)</code></li>
|
||||
<li><code>template</code> - The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to <code>None</code> to disable HTML pagination controls completely. Defaults to <code>"rest_framework/pagination/numbers.html"</code>.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="limitoffsetpagination"><a class="toclink" href="#limitoffsetpagination">LimitOffsetPagination</a></h2>
|
||||
<p>This pagination style mirrors the syntax used when looking up multiple database records. The client includes both a "limit" and an
|
||||
"offset" query parameter. The limit indicates the maximum number of items to return, and is equivalent to the <code>page_size</code> in other styles. The offset indicates the starting position of the query in relation to the complete set of unpaginated items.</p>
|
||||
<p><strong>Request</strong>:</p>
|
||||
<pre><code>GET https://api.example.org/accounts/?limit=100&offset=400
|
||||
</code></pre>
|
||||
<p><strong>Response</strong>:</p>
|
||||
<pre><code>HTTP 200 OK
|
||||
{
|
||||
"count": 1023
|
||||
"next": "https://api.example.org/accounts/?limit=100&offset=500",
|
||||
"previous": "https://api.example.org/accounts/?limit=100&offset=300",
|
||||
"results": [
|
||||
…
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<h4 id="setup_1"><a class="toclink" href="#setup_1">Setup</a></h4>
|
||||
<p>To enable the <code>LimitOffsetPagination</code> style globally, use the following configuration:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
|
||||
}
|
||||
</code></pre>
|
||||
<p>Optionally, you may also set a <code>PAGE_SIZE</code> key. If the <code>PAGE_SIZE</code> parameter is also used then the <code>limit</code> query parameter will be optional, and may be omitted by the client.</p>
|
||||
<p>On <code>GenericAPIView</code> subclasses you may also set the <code>pagination_class</code> attribute to select <code>LimitOffsetPagination</code> on a per-view basis.</p>
|
||||
<h4 id="configuration_1"><a class="toclink" href="#configuration_1">Configuration</a></h4>
|
||||
<p>The <code>LimitOffsetPagination</code> class includes a number of attributes that may be overridden to modify the pagination style.</p>
|
||||
<p>To set these attributes you should override the <code>LimitOffsetPagination</code> class, and then enable your custom pagination class as above.</p>
|
||||
<ul>
|
||||
<li><code>default_limit</code> - A numeric value indicating the limit to use if one is not provided by the client in a query parameter. Defaults to the same value as the <code>PAGE_SIZE</code> settings key.</li>
|
||||
<li><code>limit_query_param</code> - A string value indicating the name of the "limit" query parameter. Defaults to <code>'limit'</code>.</li>
|
||||
<li><code>offset_query_param</code> - A string value indicating the name of the "offset" query parameter. Defaults to <code>'offset'</code>.</li>
|
||||
<li><code>max_limit</code> - If set this is a numeric value indicating the maximum allowable limit that may be requested by the client. Defaults to <code>None</code>.</li>
|
||||
<li><code>template</code> - The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to <code>None</code> to disable HTML pagination controls completely. Defaults to <code>"rest_framework/pagination/numbers.html"</code>.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h2 id="cursorpagination"><a class="toclink" href="#cursorpagination">CursorPagination</a></h2>
|
||||
<p>The cursor-based pagination presents an opaque "cursor" indicator that the client may use to page through the result set. This pagination style only presents forward and reverse controls, and does not allow the client to navigate to arbitrary positions.</p>
|
||||
<p>Cursor based pagination requires that there is a unique, unchanging ordering of items in the result set. This ordering might typically be a creation timestamp on the records, as this presents a consistent ordering to paginate against.</p>
|
||||
<p>Cursor based pagination is more complex than other schemes. It also requires that the result set presents a fixed ordering, and does not allow the client to arbitrarily index into the result set. However it does provide the following benefits:</p>
|
||||
<ul>
|
||||
<li>Provides a consistent pagination view. When used properly <code>CursorPagination</code> ensures that the client will never see the same item twice when paging through records, even when new items are being inserted by other clients during the pagination process.</li>
|
||||
<li>Supports usage with very large datasets. With extremely large datasets pagination using offset-based pagination styles may become inefficient or unusable. Cursor based pagination schemes instead have fixed-time properties, and do not slow down as the dataset size increases.</li>
|
||||
</ul>
|
||||
<h4 id="details-and-limitations"><a class="toclink" href="#details-and-limitations">Details and limitations</a></h4>
|
||||
<p>Proper use of cursor based pagination requires a little attention to detail. You'll need to think about what ordering you want the scheme to be applied against. The default is to order by <code>"-created"</code>. This assumes that <strong>there must be a 'created' timestamp field</strong> on the model instances, and will present a "timeline" style paginated view, with the most recently added items first.</p>
|
||||
<p>You can modify the ordering by overriding the <code>'ordering'</code> attribute on the pagination class, or by using the <code>OrderingFilter</code> filter class together with <code>CursorPagination</code>. When used with <code>OrderingFilter</code> you should strongly consider restricting the fields that the user may order by.</p>
|
||||
<p>Proper usage of cursor pagination should have an ordering field that satisfies the following:</p>
|
||||
<ul>
|
||||
<li>Should be an unchanging value, such as a timestamp, slug, or other field that is only set once, on creation.</li>
|
||||
<li>Should be unique, or nearly unique. Millisecond precision timestamps are a good example. This implementation of cursor pagination uses a smart "position plus offset" style that allows it to properly support not-strictly-unique values as the ordering.</li>
|
||||
<li>Should be a non-nullable value that can be coerced to a string.</li>
|
||||
<li>Should not be a float. Precision errors easily lead to incorrect results.
|
||||
Hint: use decimals instead.
|
||||
(If you already have a float field and must paginate on that, an
|
||||
<a href="https://gist.github.com/keturn/8bc88525a183fd41c73ffb729b8865be#file-fpcursorpagination-py">example <code>CursorPagination</code> subclass that uses decimals to limit precision is available here</a>.)</li>
|
||||
<li>The field should have a database index.</li>
|
||||
</ul>
|
||||
<p>Using an ordering field that does not satisfy these constraints will generally still work, but you'll be losing some of the benefits of cursor pagination.</p>
|
||||
<p>For more technical details on the implementation we use for cursor pagination, the <a href="https://cra.mr/2011/03/08/building-cursors-for-the-disqus-api">"Building cursors for the Disqus API"</a> blog post gives a good overview of the basic approach.</p>
|
||||
<h4 id="setup_2"><a class="toclink" href="#setup_2">Setup</a></h4>
|
||||
<p>To enable the <code>CursorPagination</code> style globally, use the following configuration, modifying the <code>PAGE_SIZE</code> as desired:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
|
||||
'PAGE_SIZE': 100
|
||||
}
|
||||
</code></pre>
|
||||
<p>On <code>GenericAPIView</code> subclasses you may also set the <code>pagination_class</code> attribute to select <code>CursorPagination</code> on a per-view basis.</p>
|
||||
<h4 id="configuration_2"><a class="toclink" href="#configuration_2">Configuration</a></h4>
|
||||
<p>The <code>CursorPagination</code> class includes a number of attributes that may be overridden to modify the pagination style.</p>
|
||||
<p>To set these attributes you should override the <code>CursorPagination</code> class, and then enable your custom pagination class as above.</p>
|
||||
<ul>
|
||||
<li><code>page_size</code> = A numeric value indicating the page size. If set, this overrides the <code>PAGE_SIZE</code> setting. Defaults to the same value as the <code>PAGE_SIZE</code> settings key.</li>
|
||||
<li><code>cursor_query_param</code> = A string value indicating the name of the "cursor" query parameter. Defaults to <code>'cursor'</code>.</li>
|
||||
<li><code>ordering</code> = This should be a string, or list of strings, indicating the field against which the cursor based pagination will be applied. For example: <code>ordering = 'slug'</code>. Defaults to <code>-created</code>. This value may also be overridden by using <code>OrderingFilter</code> on the view.</li>
|
||||
<li><code>template</code> = The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to <code>None</code> to disable HTML pagination controls completely. Defaults to <code>"rest_framework/pagination/previous_and_next.html"</code>.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h1 id="custom-pagination-styles"><a class="toclink" href="#custom-pagination-styles">Custom pagination styles</a></h1>
|
||||
<p>To create a custom pagination serializer class you should subclass <code>pagination.BasePagination</code> and override the <code>paginate_queryset(self, queryset, request, view=None)</code> and <code>get_paginated_response(self, data)</code> methods:</p>
|
||||
<ul>
|
||||
<li>The <code>paginate_queryset</code> method is passed the initial queryset and should return an iterable object that contains only the data in the requested page.</li>
|
||||
<li>The <code>get_paginated_response</code> method is passed the serialized page data and should return a <code>Response</code> instance.</li>
|
||||
</ul>
|
||||
<p>Note that the <code>paginate_queryset</code> method may set state on the pagination instance, that may later be used by the <code>get_paginated_response</code> method.</p>
|
||||
<h2 id="example"><a class="toclink" href="#example">Example</a></h2>
|
||||
<p>Suppose we want to replace the default pagination output style with a modified format that includes the next and previous links under in a nested 'links' key. We could specify a custom pagination class like so:</p>
|
||||
<pre><code>class CustomPagination(pagination.PageNumberPagination):
|
||||
def get_paginated_response(self, data):
|
||||
return Response({
|
||||
'links': {
|
||||
'next': self.get_next_link(),
|
||||
'previous': self.get_previous_link()
|
||||
},
|
||||
'count': self.page.paginator.count,
|
||||
'results': data
|
||||
})
|
||||
</code></pre>
|
||||
<p>We'd then need to setup the custom class in our configuration:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
|
||||
'PAGE_SIZE': 100
|
||||
}
|
||||
</code></pre>
|
||||
<p>Note that if you care about how the ordering of keys is displayed in responses in the browsable API you might choose to use an <code>OrderedDict</code> when constructing the body of paginated responses, but this is optional.</p>
|
||||
<h2 id="using-your-custom-pagination-class"><a class="toclink" href="#using-your-custom-pagination-class">Using your custom pagination class</a></h2>
|
||||
<p>To have your custom pagination class be used by default, use the <code>DEFAULT_PAGINATION_CLASS</code> setting:</p>
|
||||
<pre><code>REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.LinkHeaderPagination',
|
||||
'PAGE_SIZE': 100
|
||||
}
|
||||
</code></pre>
|
||||
<p>API responses for list endpoints will now include a <code>Link</code> header, instead of including the pagination links as part of the body of the response, for example:</p>
|
||||
<p><img alt="Link Header" src="../../img/link-header-pagination.png" /></p>
|
||||
<p><em>A custom pagination style, using the 'Link' header'</em></p>
|
||||
<h2 id="pagination-schemas"><a class="toclink" href="#pagination-schemas">Pagination & schemas</a></h2>
|
||||
<p>You can also make the pagination controls available to the schema autogeneration
|
||||
that REST framework provides, by implementing a <code>get_schema_fields()</code> method. This method should have the following signature:</p>
|
||||
<p><code>get_schema_fields(self, view)</code></p>
|
||||
<p>The method should return a list of <code>coreapi.Field</code> instances.</p>
|
||||
<hr />
|
||||
<h1 id="html-pagination-controls"><a class="toclink" href="#html-pagination-controls">HTML pagination controls</a></h1>
|
||||
<p>By default using the pagination classes will cause HTML pagination controls to be displayed in the browsable API. There are two built-in display styles. The <code>PageNumberPagination</code> and <code>LimitOffsetPagination</code> classes display a list of page numbers with previous and next controls. The <code>CursorPagination</code> class displays a simpler style that only displays a previous and next control.</p>
|
||||
<h2 id="customizing-the-controls"><a class="toclink" href="#customizing-the-controls">Customizing the controls</a></h2>
|
||||
<p>You can override the templates that render the HTML pagination controls. The two built-in styles are:</p>
|
||||
<ul>
|
||||
<li><code>rest_framework/pagination/numbers.html</code></li>
|
||||
<li><code>rest_framework/pagination/previous_and_next.html</code></li>
|
||||
</ul>
|
||||
<p>Providing a template with either of these paths in a global template directory will override the default rendering for the relevant pagination classes.</p>
|
||||
<p>Alternatively you can disable HTML pagination controls completely by subclassing on of the existing classes, setting <code>template = None</code> as an attribute on the class. You'll then need to configure your <code>DEFAULT_PAGINATION_CLASS</code> settings key to use your custom class as the default pagination style.</p>
|
||||
<h4 id="low-level-api"><a class="toclink" href="#low-level-api">Low-level API</a></h4>
|
||||
<p>The low-level API for determining if a pagination class should display the controls or not is exposed as a <code>display_page_controls</code> attribute on the pagination instance. Custom pagination classes should be set to <code>True</code> in the <code>paginate_queryset</code> method if they require the HTML pagination controls to be displayed.</p>
|
||||
<p>The <code>.to_html()</code> and <code>.get_html_context()</code> methods may also be overridden in a custom pagination class in order to further customize how the controls are rendered.</p>
|
||||
<hr />
|
||||
<h1 id="third-party-packages"><a class="toclink" href="#third-party-packages">Third party packages</a></h1>
|
||||
<p>The following third party packages are also available.</p>
|
||||
<h2 id="drf-extensions"><a class="toclink" href="#drf-extensions">DRF-extensions</a></h2>
|
||||
<p>The <a href="https://chibisov.github.io/drf-extensions/docs/"><code>DRF-extensions</code> package</a> includes a <a href="https://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>
|
||||
<h2 id="drf-proxy-pagination"><a class="toclink" href="#drf-proxy-pagination">drf-proxy-pagination</a></h2>
|
||||
<p>The <a href="https://github.com/tuffnatty/drf-proxy-pagination"><code>drf-proxy-pagination</code> package</a> includes a <code>ProxyPagination</code> class which allows to choose pagination class with a query parameter.</p>
|
||||
<h2 id="link-header-pagination"><a class="toclink" href="#link-header-pagination">link-header-pagination</a></h2>
|
||||
<p>The <a href="https://github.com/tbeadle/django-rest-framework-link-header-pagination"><code>django-rest-framework-link-header-pagination</code> package</a> includes a <code>LinkHeaderPagination</code> class which provides pagination via an HTTP <code>Link</code> header as described in <a href="github-link-pagination">Github's developer documentation</a>.</p>
|
||||
|
||||
|
||||
</div> <!--/span-->
|
||||
</div> <!--/row-->
|
||||
</div> <!--/.fluid-container-->
|
||||
</div> <!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div> <!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
|
||||
<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 src="../../js/theme.js"></script>
|
||||
|
||||
<script>var base_url = '../..';</script>
|
||||
|
||||
<script src="../../search/main.js" defer></script>
|
||||
|
||||
|
||||
<script>
|
||||
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/dropdown to no higher than browser window
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
717
api-guide/parsers/index.html
Normal file
717
api-guide/parsers/index.html
Normal file
|
|
@ -0,0 +1,717 @@
|
|||
<!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="https://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>
|
||||
#sidebarInclude img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#sidebarInclude a.promo {
|
||||
color: black;
|
||||
}
|
||||
@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/encode/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="next" href="../renderers/">
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small " rel="prev" href="../routers/">
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_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="https://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="../caching/">Caching</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="../versioning/">Versioning</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../content-negotiation/">Content negotiation</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../metadata/">Metadata</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../schemas/">Schemas</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/api-clients/">API Clients</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/internationalization/">Internationalization</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/ajax-csrf-cors/">AJAX, CSRF & CORS</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../topics/html-and-forms/">HTML & Forms</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>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Community <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li >
|
||||
<a href="../../community/tutorials-and-resources/">Tutorials and Resources</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/third-party-packages/">Third Party Packages</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/contributing/">Contributing to REST framework</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/project-management/">Project management</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/release-notes/">Release Notes</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.11-announcement/">3.11 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.10-announcement/">3.10 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.9-announcement/">3.9 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.8-announcement/">3.8 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.7-announcement/">3.7 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.6-announcement/">3.6 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.5-announcement/">3.5 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.4-announcement/">3.4 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.3-announcement/">3.3 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.2-announcement/">3.2 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.1-announcement/">3.1 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/3.0-announcement/">3.0 Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/kickstarter-announcement/">Kickstarter Announcement</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||
<a href="../../community/mozilla-grant/">Mozilla Grant</a>
|
||||
</li>
|
||||
|
||||
<li >
|
||||