mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-12-04 23:44:07 +03:00
First docs build
This commit is contained in:
parent
fa5a87982e
commit
46f1afa9f8
152
api-guide/contentnegotiation.html
Normal file
152
api-guide/contentnegotiation.html
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<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. -- RFC 2616, Fielding et al.</p>
|
||||||
|
</blockquote>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
151
api-guide/exceptions.html
Normal file
151
api-guide/exceptions.html
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#exceptions">Exceptions</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="exceptions">Exceptions</h1>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
153
api-guide/parsers.html
Normal file
153
api-guide/parsers.html
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#parsers">Parsers</a></li>
|
||||||
|
<li><a href="#parse(request)">.parse(request)</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="parsers">Parsers</h1>
|
||||||
|
<h2 id="parserequest">.parse(request)</h2>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
153
api-guide/renderers.html
Normal file
153
api-guide/renderers.html
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#renderers">Renderers</a></li>
|
||||||
|
<li><a href="#render(response)">.render(response)</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="renderers">Renderers</h1>
|
||||||
|
<h2 id="renderresponse">.render(response)</h2>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
194
api-guide/requests.html
Normal file
194
api-guide/requests.html
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#requests">Requests</a></li>
|
||||||
|
<li><a href="#method">.method</a></li>
|
||||||
|
<li><a href="#content_type">.content_type</a></li>
|
||||||
|
<li><a href="#data">.DATA</a></li>
|
||||||
|
<li><a href="#files">.FILES</a></li>
|
||||||
|
<li><a href="#user">.user</a></li>
|
||||||
|
<li><a href="#auth">.auth</a></li>
|
||||||
|
<li><a href="#parsers">.parsers</a></li>
|
||||||
|
<li><a href="#stream">.stream</a></li>
|
||||||
|
<li><a href="#authentication">.authentication</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="requests">Requests</h1>
|
||||||
|
<blockquote>
|
||||||
|
<p>If you're doing REST-based web service stuff ... you should ignore request.POST.</p>
|
||||||
|
<p>— Malcom Tredinnick, <a href="https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion">Django developers group</a></p>
|
||||||
|
</blockquote>
|
||||||
|
<p>REST framework's <code>Request</code> class extends the standard <code>HttpRequest</code>, adding support for parsing multiple content types, allowing browser-based <code>PUT</code>, <code>DELETE</code> and other methods, and adding flexible per-request authentication.</p>
|
||||||
|
<h2 id="method">.method</h2>
|
||||||
|
<p><code>request.method</code> returns the uppercased string representation of the request's HTTP method.</p>
|
||||||
|
<p>Browser-based <code>PUT</code>, <code>DELETE</code> and other requests are supported, and can be made by using a hidden form field named <code>_method</code> in a regular <code>POST</code> form.</p>
|
||||||
|
<h2 id="content_type">.content_type</h2>
|
||||||
|
<p><code>request.content</code>, returns a string object representing the mimetype of the HTTP request's body, if one exists.</p>
|
||||||
|
<h2 id="data">.DATA</h2>
|
||||||
|
<p><code>request.DATA</code> returns the parsed content of the request body. This is similar to the standard <code>HttpRequest.POST</code> attribute except that:</p>
|
||||||
|
<ol>
|
||||||
|
<li>It supports parsing the content of HTTP methods other than <code>POST</code>, meaning that you can access the content of <code>PUT</code> and <code>PATCH</code> requests.</li>
|
||||||
|
<li>It supports parsing multiple content types, rather than just form data. For example you can handle incoming json data in the same way that you handle incoming form data.</li>
|
||||||
|
</ol>
|
||||||
|
<h2 id="files">.FILES</h2>
|
||||||
|
<p><code>request.FILES</code> returns any uploaded files that may be present in the content of the request body. This is the same as the standard <code>HttpRequest</code> behavior, except that the same flexible request parsing that is used for <code>request.DATA</code>.</p>
|
||||||
|
<p>This allows you to support file uploads from multiple content-types. For example you can write a parser that supports <code>POST</code>ing the raw content of a file, instead of using form-encoded file uploads.</p>
|
||||||
|
<h2 id="user">.user</h2>
|
||||||
|
<p><code>request.user</code> returns a <code>django.contrib.auth.models.User</code> instance. </p>
|
||||||
|
<h2 id="auth">.auth</h2>
|
||||||
|
<p><code>request.auth</code> returns any additional authentication context that may not be contained in <code>request.user</code>. The exact behavior of <code>request.auth</code> depends on what authentication has been set in <code>request.authentication</code>. For many types of authentication this will simply be <code>None</code>, but it may also be an object representing a permission scope, an expiry time, or any other information that might be contained in a token-based authentication scheme.</p>
|
||||||
|
<h2 id="parsers">.parsers</h2>
|
||||||
|
<p><code>request.parsers</code> should be set to a list of <code>Parser</code> instances that can be used to parse the content of the request body.</p>
|
||||||
|
<p><code>request.parsers</code> may no longer be altered once <code>request.DATA</code>, <code>request.FILES</code> or <code>request.POST</code> have been accessed.</p>
|
||||||
|
<p>If you're using the <code>djangorestframework.views.View</code> class... <strong>[TODO]</strong></p>
|
||||||
|
<h2 id="stream">.stream</h2>
|
||||||
|
<p><code>request.stream</code> returns a stream representing the content of the request body.</p>
|
||||||
|
<p>You will not typically need to access <code>request.stream</code>, unless you're writing a <code>Parser</code> class.</p>
|
||||||
|
<h2 id="authentication">.authentication</h2>
|
||||||
|
<p><code>request.authentication</code> should be set to a list of <code>Authentication</code> instances that can be used to authenticate the request.</p>
|
||||||
|
<p><code>request.authentication</code> may no longer be altered once <code>request.user</code> or <code>request.auth</code> have been accessed.</p>
|
||||||
|
<p>If you're using the <code>djangorestframework.views.View</code> class... <strong>[TODO]</strong></p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
166
api-guide/responses.html
Normal file
166
api-guide/responses.html
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#responses">Responses</a></li>
|
||||||
|
<li><a href="#response(content,-headers=none,--renderers=none,-view=none,-format=none,-status=none)">Response(content, headers=None, renderers=None, view=None, format=None, status=None)</a></li>
|
||||||
|
<li><a href="#renderers">.renderers</a></li>
|
||||||
|
<li><a href="#view">.view</a></li>
|
||||||
|
<li><a href="#format">.format</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="responses">Responses</h1>
|
||||||
|
<blockquote>
|
||||||
|
<p>Unlike basic HttpResponse objects, TemplateResponse objects retain the details of the context that was provided by the view to compute the response. The final output of the response is not computed until it is needed, later in the response process.</p>
|
||||||
|
<p>— <a href="https://docs.djangoproject.com/en/dev/ref/template-response/">Django documentation</a></p>
|
||||||
|
</blockquote>
|
||||||
|
<p>REST framework supports HTTP content negotiation by providing a <code>Response</code> class which allows you to return content that can be rendered into multiple content types, depending on the client request.</p>
|
||||||
|
<p>The <code>Response</code> class subclasses Django's <code>TemplateResponse</code>. <code>Response</code> objects are initialised with content, which should consist of native python primatives. REST framework then uses standard HTTP content negotiation to determine how it should render the final response content.</p>
|
||||||
|
<p>There's no requirement for you to use the <code>Response</code> class, you can also return regular <code>HttpResponse</code> objects from your views if you want, but it does provide a better interface for returning Web API responses.</p>
|
||||||
|
<h2 id="responsecontent-headersnone-renderersnone-viewnone-formatnone-statusnone">Response(content, headers=None, renderers=None, view=None, format=None, status=None)</h2>
|
||||||
|
<h2 id="renderers">.renderers</h2>
|
||||||
|
<h2 id="view">.view</h2>
|
||||||
|
<h2 id="format">.format</h2>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
348
api-guide/serializers.html
Normal file
348
api-guide/serializers.html
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#serializers">Serializers</a></li>
|
||||||
|
<li><a href="#declaring-serializers">Declaring Serializers</a></li>
|
||||||
|
<li><a href="#serializing-objects">Serializing objects</a></li>
|
||||||
|
<li><a href="#deserializing-objects">Deserializing objects</a></li>
|
||||||
|
<li><a href="#validation">Validation</a></li>
|
||||||
|
<li><a href="#dealing-with-nested-objects">Dealing with nested objects</a></li>
|
||||||
|
<li><a href="#creating-custom-fields">Creating custom fields</a></li>
|
||||||
|
<li class="main"><a href="#modelserializers">ModelSerializers</a></li>
|
||||||
|
<li><a href="#specifying-fields-explicitly">Specifying fields explicitly</a></li>
|
||||||
|
<li><a href="#relational-fields">Relational fields</a></li>
|
||||||
|
<li><a href="#specifying-which-fields-should-be-included">Specifying which fields should be included</a></li>
|
||||||
|
<li><a href="#specifiying-nested-serialization">Specifiying nested serialization</a></li>
|
||||||
|
<li><a href="#customising-the-default-fields-used-by-a-modelserializer">Customising the default fields used by a ModelSerializer</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="serializers">Serializers</h1>
|
||||||
|
<blockquote>
|
||||||
|
<p>Expanding the usefulness of the serializers is something that we would
|
||||||
|
like to address. However, it's not a trivial problem, and it
|
||||||
|
will take some serious design work. Any offers to help out in this
|
||||||
|
area would be gratefully accepted.</p>
|
||||||
|
<p>— Russell Keith-Magee, <a href="https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion">Django users group</a></p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Serializers allow complex data such as querysets and model instances to be converted to native python datatypes that can then be easily rendered into <code>JSON</code>, <code>XML</code> or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.</p>
|
||||||
|
<p>REST framework's serializers work very similarly to Django's <code>Form</code> and <code>ModelForm</code> classes. It provides a <code>Serializer</code> class which gives you a powerful, generic way to control the output of your responses, as well as a <code>ModelSerializer</code> class which provides a useful shortcut for creating serializers that deal with model instances and querysets.</p>
|
||||||
|
<h2 id="declaring-serializers">Declaring Serializers</h2>
|
||||||
|
<p>Let's start by creating a simple object we can use for example purposes:</p>
|
||||||
|
<pre><code>class Comment(object):
|
||||||
|
def __init__(self, email, content, created=None):
|
||||||
|
self.email = email
|
||||||
|
self.content = content
|
||||||
|
self.created = created or datetime.datetime.now()
|
||||||
|
|
||||||
|
comment = Comment(email='leila@example.com', content='foo bar')
|
||||||
|
</code></pre>
|
||||||
|
<p>We'll declare a serializer that we can use to serialize and deserialize <code>Comment</code> objects.
|
||||||
|
Declaring a serializer looks very similar to declaring a form:</p>
|
||||||
|
<pre><code>class CommentSerializer(serializers.Serializer):
|
||||||
|
email = serializers.EmailField()
|
||||||
|
content = serializers.CharField(max_length=200)
|
||||||
|
created = serializers.DateTimeField()
|
||||||
|
|
||||||
|
def restore_object(self, attrs, instance=None):
|
||||||
|
if instance:
|
||||||
|
instance.title = attrs['title']
|
||||||
|
instance.content = attrs['content']
|
||||||
|
instance.created = attrs['created']
|
||||||
|
return instance
|
||||||
|
return Comment(**attrs)
|
||||||
|
</code></pre>
|
||||||
|
<p>The first part of serializer class defines the fields that get serialized/deserialized. The <code>restore_object</code> method defines how fully fledged instances get created when deserializing data. The <code>restore_object</code> method is optional, and is only required if we want our serializer to support deserialization.</p>
|
||||||
|
<h2 id="serializing-objects">Serializing objects</h2>
|
||||||
|
<p>We can now use <code>CommentSerializer</code> to serialize a comment, or list of comments. Again, using the <code>Serializer</code> class looks a lot like using a <code>Form</code> class.</p>
|
||||||
|
<pre><code>serializer = CommentSerializer(instance=comment)
|
||||||
|
serializer.data
|
||||||
|
# {'email': u'leila@example.com', 'content': u'foo bar', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774)}
|
||||||
|
</code></pre>
|
||||||
|
<p>At this point we've translated the model instance into python native datatypes. To finalise the serialization process we render the data into <code>json</code>.</p>
|
||||||
|
<pre><code>stream = JSONRenderer().render(data)
|
||||||
|
stream
|
||||||
|
# '{"email": "leila@example.com", "content": "foo bar", "created": "2012-08-22T16:20:09.822"}'
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="deserializing-objects">Deserializing objects</h2>
|
||||||
|
<p>Deserialization is similar. First we parse a stream into python native datatypes... </p>
|
||||||
|
<pre><code>data = JSONParser().parse(stream)
|
||||||
|
</code></pre>
|
||||||
|
<p>...then we restore those native datatypes into a fully populated object instance.</p>
|
||||||
|
<pre><code>serializer = CommentSerializer(data)
|
||||||
|
serializer.is_valid()
|
||||||
|
# True
|
||||||
|
serializer.object
|
||||||
|
# <Comment object at 0x10633b2d0>
|
||||||
|
>>> serializer.deserialize('json', stream)
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="validation">Validation</h2>
|
||||||
|
<p>When deserializing data, you always need to call <code>is_valid()</code> before attempting to access the deserialized object. If any validation errors occur, the <code>.errors</code> and <code>.non_field_errors</code> properties will contain the resulting error messages.</p>
|
||||||
|
<p><strong>TODO: Describe validation in more depth</strong></p>
|
||||||
|
<h2 id="dealing-with-nested-objects">Dealing with nested objects</h2>
|
||||||
|
<p>The previous example is fine for dealing with objects that only have simple datatypes, but sometimes we also need to be able to represent more complex objects,
|
||||||
|
where some of the attributes of an object might not be simple datatypes such as strings, dates or integers.</p>
|
||||||
|
<p>The <code>Serializer</code> class is itself a type of <code>Field</code>, and can be used to represent relationships where one object type is nested inside another.</p>
|
||||||
|
<pre><code>class UserSerializer(serializers.Serializer):
|
||||||
|
email = serializers.EmailField()
|
||||||
|
username = serializers.CharField()
|
||||||
|
|
||||||
|
def restore_object(self, attrs, instance=None):
|
||||||
|
return User(**attrs)
|
||||||
|
|
||||||
|
class CommentSerializer(serializers.Serializer):
|
||||||
|
user = serializers.UserSerializer()
|
||||||
|
title = serializers.CharField()
|
||||||
|
content = serializers.CharField(max_length=200)
|
||||||
|
created = serializers.DateTimeField()
|
||||||
|
|
||||||
|
def restore_object(self, attrs, instance=None):
|
||||||
|
return Comment(**attrs)
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="creating-custom-fields">Creating custom fields</h2>
|
||||||
|
<p>If you want to create a custom field, you'll probably want to override either one or both of the <code>.to_native()</code> and <code>.from_native()</code> methods. These two methods are used to convert between the intial datatype, and a primative, serializable datatype. Primative datatypes may be any of a number, string, date/time/datetime or None. They may also be any list or dictionary like object that only contains other primative objects.</p>
|
||||||
|
<p>The <code>.to_native()</code> method is called to convert the initial datatype into a primative, serializable datatype. The <code>from_native()</code> method is called to restore a primative datatype into it's initial representation.</p>
|
||||||
|
<p>Let's look at an example of serializing a class that represents an RGB color value:</p>
|
||||||
|
<pre><code>class Color(object):
|
||||||
|
"""
|
||||||
|
A color represented in the RGB colorspace.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, red, green, blue):
|
||||||
|
assert(red >= 0 and green >= 0 and blue >= 0)
|
||||||
|
assert(red < 256 and green < 256 and blue < 256)
|
||||||
|
self.red, self.green, self.blue = red, green, blue
|
||||||
|
|
||||||
|
class ColourField(Field):
|
||||||
|
"""
|
||||||
|
Color objects are serialized into "rgb(#, #, #)" notation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def to_native(self, obj):
|
||||||
|
return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.blue)
|
||||||
|
|
||||||
|
def from_native(self, data):
|
||||||
|
data = data.strip('rgb(').rstrip(')')
|
||||||
|
red, green, blue = [int(col) for col in data.split(',')]
|
||||||
|
return Color(red, green, blue)
|
||||||
|
</code></pre>
|
||||||
|
<p>By default field values are treated as mapping to an attribute on the object. If you need to customize how the field value is accessed and set you need to override <code>.field_to_native()</code> and/or <code>.field_from_native()</code>.</p>
|
||||||
|
<p>As an example, let's create a field that can be used represent the class name of the object being serialized:</p>
|
||||||
|
<pre><code>class ClassNameField(Field):
|
||||||
|
def field_to_native(self, obj, field_name):
|
||||||
|
"""
|
||||||
|
Serialize the object's class name, not an attribute of the object.
|
||||||
|
"""
|
||||||
|
return obj.__class__.__name__
|
||||||
|
|
||||||
|
def field_from_native(self, data, field_name, into):
|
||||||
|
"""
|
||||||
|
We don't want to set anything when we revert this field.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
</code></pre>
|
||||||
|
<hr />
|
||||||
|
<h1 id="modelserializers">ModelSerializers</h1>
|
||||||
|
<p>Often you'll want serializer classes that map closely to model definitions.
|
||||||
|
The <code>ModelSerializer</code> class lets you automatically create a Serializer class with fields that corrospond to the Model fields.</p>
|
||||||
|
<pre><code>class AccountSerializer(ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Account
|
||||||
|
</code></pre>
|
||||||
|
<p><strong>[TODO: Explain model field to serializer field mapping in more detail]</strong></p>
|
||||||
|
<h2 id="specifying-fields-explicitly">Specifying fields explicitly</h2>
|
||||||
|
<p>You can add extra fields to a <code>ModelSerializer</code> or override the default fields by declaring fields on the class, just as you would for a <code>Serializer</code> class.</p>
|
||||||
|
<pre><code>class AccountSerializer(ModelSerializer):
|
||||||
|
url = CharField(source='get_absolute_url', readonly=True)
|
||||||
|
group = NaturalKeyField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Account
|
||||||
|
</code></pre>
|
||||||
|
<p>Extra fields can corrospond to any property or callable on the model.</p>
|
||||||
|
<h2 id="relational-fields">Relational fields</h2>
|
||||||
|
<p>When serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation is to use the primary keys of the related instances.</p>
|
||||||
|
<p>Alternative representations include serializing using natural keys, serializing complete nested representations, or serializing using a custom representation, such as a URL that uniquely identifies the model instances.</p>
|
||||||
|
<p>The <code>PrimaryKeyField</code> and <code>NaturalKeyField</code> fields provide alternative flat representations.</p>
|
||||||
|
<p>The <code>ModelSerializer</code> class can itself be used as a field, in order to serialize relationships using nested representations.</p>
|
||||||
|
<p>The <code>RelatedField</code> class may be subclassed to create a custom represenation of a relationship. The subclass should override <code>.to_native()</code>, and optionally <code>.from_native()</code> if deserialization is supported.</p>
|
||||||
|
<p>All the relational fields may be used for any relationship or reverse relationship on a model.</p>
|
||||||
|
<h2 id="specifying-which-fields-should-be-included">Specifying which fields should be included</h2>
|
||||||
|
<p>If you only want a subset of the default fields to be used in a model serializer, you can do so using <code>fields</code> or <code>exclude</code> options, just as you would with a <code>ModelForm</code>.</p>
|
||||||
|
<p>For example:</p>
|
||||||
|
<pre><code>class AccountSerializer(ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Account
|
||||||
|
exclude = ('id',)
|
||||||
|
</code></pre>
|
||||||
|
<p>The <code>fields</code> and <code>exclude</code> options may also be set by passing them to the <code>serialize()</code> method.</p>
|
||||||
|
<p><strong>[TODO: Possibly only allow .serialize(fields=…) in FixtureSerializer for backwards compatability, but remove for ModelSerializer]</strong></p>
|
||||||
|
<h2 id="specifiying-nested-serialization">Specifiying nested serialization</h2>
|
||||||
|
<p>The default <code>ModelSerializer</code> uses primary keys for relationships, but you can also easily generate nested representations using the <code>nested</code> option:</p>
|
||||||
|
<pre><code>class AccountSerializer(ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Account
|
||||||
|
exclude = ('id',)
|
||||||
|
nested = True
|
||||||
|
</code></pre>
|
||||||
|
<p>The <code>nested</code> option may be set to either <code>True</code>, <code>False</code>, or an integer value. If given an integer value it indicates the depth of relationships that should be traversed before reverting to a flat representation.</p>
|
||||||
|
<p>When serializing objects using a nested representation any occurances of recursion will be recognised, and will fall back to using a flat representation.</p>
|
||||||
|
<p>The <code>nested</code> option may also be set by passing it to the <code>serialize()</code> method.</p>
|
||||||
|
<p><strong>[TODO: Possibly only allow .serialize(nested=…) in FixtureSerializer]</strong></p>
|
||||||
|
<h2 id="customising-the-default-fields-used-by-a-modelserializer">Customising the default fields used by a ModelSerializer</h2>
|
||||||
|
<pre><code>class AccountSerializer(ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Account
|
||||||
|
|
||||||
|
def get_nested_field(self, model_field):
|
||||||
|
return ModelSerializer()
|
||||||
|
|
||||||
|
def get_related_field(self, model_field):
|
||||||
|
return NaturalKeyField()
|
||||||
|
|
||||||
|
def get_field(self, model_field):
|
||||||
|
return Field()
|
||||||
|
</code></pre>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
230
api-guide/status-codes.html
Normal file
230
api-guide/status-codes.html
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#status-codes">Status Codes</a></li>
|
||||||
|
<li><a href="#informational---1xx">Informational - 1xx</a></li>
|
||||||
|
<li><a href="#successful---2xx">Successful - 2xx</a></li>
|
||||||
|
<li><a href="#redirection---3xx">Redirection - 3xx</a></li>
|
||||||
|
<li><a href="#client-error---4xx">Client Error - 4xx</a></li>
|
||||||
|
<li><a href="#server-error---5xx">Server Error - 5xx</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="status-codes">Status Codes</h1>
|
||||||
|
<blockquote>
|
||||||
|
<p>418 I'm a teapot - Any attempt to brew coffee with a teapot should result in the error code "418 I'm a teapot". The resulting entity body MAY be short and stout.</p>
|
||||||
|
<p>— <a href="http://www.ietf.org/rfc/rfc2324.txt">RFC 2324</a>, Hyper Text Coffee Pot Control Protocol</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Using bare status codes in your responses isn't recommended. REST framework includes a set of named constants that you can use to make more code more obvious and readable.</p>
|
||||||
|
<pre><code>from djangorestframework import status
|
||||||
|
|
||||||
|
def empty_view(self):
|
||||||
|
content = {'please move along': 'nothing to see here'}
|
||||||
|
return Response(content, status=status.HTTP_404_NOT_FOUND)
|
||||||
|
</code></pre>
|
||||||
|
<p>The full set of HTTP status codes included in the <code>status</code> module is listed below.</p>
|
||||||
|
<p>For more information on proper usage of HTTP status codes see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">RFC 2616</a>
|
||||||
|
and <a href="http://tools.ietf.org/html/rfc6585">RFC 6585</a>.</p>
|
||||||
|
<h2 id="informational-1xx">Informational - 1xx</h2>
|
||||||
|
<p>This class of status code indicates a provisional response. There are no 1xx status codes used in REST framework by default.</p>
|
||||||
|
<pre><code>HTTP_100_CONTINUE
|
||||||
|
HTTP_101_SWITCHING_PROTOCOLS
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="successful-2xx">Successful - 2xx</h2>
|
||||||
|
<p>This class of status code indicates that the client's request was successfully received, understood, and accepted.</p>
|
||||||
|
<pre><code>HTTP_200_OK
|
||||||
|
HTTP_201_CREATED
|
||||||
|
HTTP_202_ACCEPTED
|
||||||
|
HTTP_203_NON_AUTHORITATIVE_INFORMATION
|
||||||
|
HTTP_204_NO_CONTENT
|
||||||
|
HTTP_205_RESET_CONTENT
|
||||||
|
HTTP_206_PARTIAL_CONTENT
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="redirection-3xx">Redirection - 3xx</h2>
|
||||||
|
<p>This class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request.</p>
|
||||||
|
<pre><code>HTTP_300_MULTIPLE_CHOICES
|
||||||
|
HTTP_301_MOVED_PERMANENTLY
|
||||||
|
HTTP_302_FOUND
|
||||||
|
HTTP_303_SEE_OTHER
|
||||||
|
HTTP_304_NOT_MODIFIED
|
||||||
|
HTTP_305_USE_PROXY
|
||||||
|
HTTP_306_RESERVED
|
||||||
|
HTTP_307_TEMPORARY_REDIRECT
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="client-error-4xx">Client Error - 4xx</h2>
|
||||||
|
<p>The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition.</p>
|
||||||
|
<pre><code>HTTP_400_BAD_REQUEST
|
||||||
|
HTTP_401_UNAUTHORIZED
|
||||||
|
HTTP_402_PAYMENT_REQUIRED
|
||||||
|
HTTP_403_FORBIDDEN
|
||||||
|
HTTP_404_NOT_FOUND
|
||||||
|
HTTP_405_METHOD_NOT_ALLOWED
|
||||||
|
HTTP_406_NOT_ACCEPTABLE
|
||||||
|
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
|
||||||
|
HTTP_408_REQUEST_TIMEOUT
|
||||||
|
HTTP_409_CONFLICT
|
||||||
|
HTTP_410_GONE
|
||||||
|
HTTP_411_LENGTH_REQUIRED
|
||||||
|
HTTP_412_PRECONDITION_FAILED
|
||||||
|
HTTP_413_REQUEST_ENTITY_TOO_LARGE
|
||||||
|
HTTP_414_REQUEST_URI_TOO_LONG
|
||||||
|
HTTP_415_UNSUPPORTED_MEDIA_TYPE
|
||||||
|
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
|
||||||
|
HTTP_417_EXPECTATION_FAILED
|
||||||
|
HTTP_428_PRECONDITION_REQUIRED
|
||||||
|
HTTP_429_TOO_MANY_REQUESTS
|
||||||
|
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="server-error-5xx">Server Error - 5xx</h2>
|
||||||
|
<p>Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has erred or is incapable of performing the request. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition.</p>
|
||||||
|
<pre><code>HTTP_500_INTERNAL_SERVER_ERROR
|
||||||
|
HTTP_501_NOT_IMPLEMENTED
|
||||||
|
HTTP_502_BAD_GATEWAY
|
||||||
|
HTTP_503_SERVICE_UNAVAILABLE
|
||||||
|
HTTP_504_GATEWAY_TIMEOUT
|
||||||
|
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
|
||||||
|
HTTP_511_NETWORD_AUTHENTICATION_REQUIRED
|
||||||
|
</code></pre>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
182
api-guide/urls.html
Normal file
182
api-guide/urls.html
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#returning-uris-from-your-web-apis">Returning URIs from your Web APIs</a></li>
|
||||||
|
<li><a href="#reverse(viewname,-request,-*args,-**kwargs)">reverse(viewname, request, *args, **kwargs)</a></li>
|
||||||
|
<li><a href="#reverse_lazy(viewname,-request,-*args,-**kwargs)">reverse_lazy(viewname, request, *args, **kwargs)</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="returning-uris-from-your-web-apis">Returning URIs from your Web APIs</h1>
|
||||||
|
<blockquote>
|
||||||
|
<p>The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components.</p>
|
||||||
|
<p>— Roy Fielding, <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5">Architectural Styles and the Design of Network-based Software Architectures</a></p>
|
||||||
|
</blockquote>
|
||||||
|
<p>As a rule, it's probably better practice to return absolute URIs from you web APIs, such as <code>http://example.com/foobar</code>, rather than returning relative URIs, such as <code>/foobar</code>.</p>
|
||||||
|
<p>The advantages of doing so are:</p>
|
||||||
|
<ul>
|
||||||
|
<li>It's more explicit.</li>
|
||||||
|
<li>It leaves less work for your API clients.</li>
|
||||||
|
<li>There's no ambiguity about the meaning of the string when it's found in representations such as JSON that do not have a native URI type.</li>
|
||||||
|
<li>It allows use to easily do things like markup HTML representations with hyperlinks.</li>
|
||||||
|
</ul>
|
||||||
|
<p>REST framework provides two utility functions to make it more simple to return absolute URIs from your Web API.</p>
|
||||||
|
<p>There's no requirement for you to use them, but if you do then the self-describing API will be able to automatically hyperlink it's output for you, which makes browsing the API much easier.</p>
|
||||||
|
<h2 id="reverseviewname-request-args-kwargs">reverse(viewname, request, <em>args, </em>*kwargs)</h2>
|
||||||
|
<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse"><code>django.core.urlresolvers.reverse</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
|
||||||
|
<pre><code>from djangorestframework.utils import reverse
|
||||||
|
from djangorestframework.views import APIView
|
||||||
|
|
||||||
|
class MyView(APIView):
|
||||||
|
def get(self, request):
|
||||||
|
content = {
|
||||||
|
...
|
||||||
|
'url': reverse('year-summary', request, args=[1945])
|
||||||
|
}
|
||||||
|
return Response(content)
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="reverse_lazyviewname-request-args-kwargs">reverse_lazy(viewname, request, <em>args, </em>*kwargs)</h2>
|
||||||
|
<p>Has the same behavior as <a href="https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy"><code>django.core.urlresolvers.reverse_lazy</code></a>, except that it returns a fully qualified URL, using the request to determine the host and port.</p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
185
api-guide/views.html
Normal file
185
api-guide/views.html
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#views">Views</a></li>
|
||||||
|
<li><a href="#apiview">APIView</a></li>
|
||||||
|
<li><a href="#method-handlers">Method handlers</a></li>
|
||||||
|
<li><a href="#initial(request,-*args,-**kwargs)">.initial(request, *args, **kwargs)</a></li>
|
||||||
|
<li><a href="#final(request,-response,-*args,-**kwargs)">.final(request, response, *args, **kwargs)</a></li>
|
||||||
|
<li><a href="#parsers">.parsers</a></li>
|
||||||
|
<li><a href="#renderers">.renderers</a></li>
|
||||||
|
<li><a href="#serializer">.serializer</a></li>
|
||||||
|
<li><a href="#authentication">.authentication</a></li>
|
||||||
|
<li><a href="#permissions">.permissions</a></li>
|
||||||
|
<li><a href="#headers">.headers</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<blockquote>
|
||||||
|
<p>Django's class based views are a welcome departure from the old-style views.</p>
|
||||||
|
<p>— <a href="http://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html">Reinout van Rees</a></p>
|
||||||
|
</blockquote>
|
||||||
|
<h1 id="views">Views</h1>
|
||||||
|
<p>REST framework provides a simple <code>APIView</code> class, built on Django's <code>django.generics.views.View</code>. The <code>APIView</code> class ensures five main things:</p>
|
||||||
|
<ol>
|
||||||
|
<li>Any requests inside the view will become <code>Request</code> instances.</li>
|
||||||
|
<li><code>Request</code> instances will have their <code>renderers</code> and <code>authentication</code> attributes automatically set. </li>
|
||||||
|
<li><code>Response</code> instances will have their <code>parsers</code> and <code>serializer</code> attributes automatically set.</li>
|
||||||
|
<li><code>APIException</code> exceptions will be caught and return appropriate responses.</li>
|
||||||
|
<li>Any permissions provided will be checked prior to passing the request to a handler method.</li>
|
||||||
|
</ol>
|
||||||
|
<p>Additionally there are a some minor extras, such as providing a default <code>options</code> handler, setting some common headers on the response prior to return, and providing the useful <code>initial()</code> and <code>final()</code> hooks.</p>
|
||||||
|
<h2 id="apiview">APIView</h2>
|
||||||
|
<h2 id="method-handlers">Method handlers</h2>
|
||||||
|
<p>Describe that APIView handles regular .get(), .post(), .put(), .delete() etc...</p>
|
||||||
|
<h2 id="initialrequest-args-kwargs">.initial(request, <em>args, </em>*kwargs)</h2>
|
||||||
|
<h2 id="finalrequest-response-args-kwargs">.final(request, response, <em>args, </em>*kwargs)</h2>
|
||||||
|
<h2 id="parsers">.parsers</h2>
|
||||||
|
<h2 id="renderers">.renderers</h2>
|
||||||
|
<h2 id="serializer">.serializer</h2>
|
||||||
|
<h2 id="authentication">.authentication</h2>
|
||||||
|
<h2 id="permissions">.permissions</h2>
|
||||||
|
<h2 id="headers">.headers</h2>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
1040
css/bootstrap-responsive.css
vendored
Normal file
1040
css/bootstrap-responsive.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5624
css/bootstrap.css
vendored
Normal file
5624
css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
251
index.html
251
index.html
|
@ -1 +1,250 @@
|
||||||
My GitHub Page
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#django-rest-framework">Django REST framework</a></li>
|
||||||
|
<li><a href="#requirements">Requirements</a></li>
|
||||||
|
<li><a href="#installation">Installation</a></li>
|
||||||
|
<li><a href="#quickstart">Quickstart</a></li>
|
||||||
|
<li><a href="#tutorial">Tutorial</a></li>
|
||||||
|
<li><a href="#api-guide">API Guide</a></li>
|
||||||
|
<li><a href="#topics">Topics</a></li>
|
||||||
|
<li><a href="#license">License</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="django-rest-framework">Django REST framework</h1>
|
||||||
|
<p><strong>A toolkit for building well-connected, self-describing Web APIs.</strong></p>
|
||||||
|
<p><strong>WARNING: This documentation is for the 2.0 redesign of REST framework. It is a work in progress.</strong></p>
|
||||||
|
<p>Django REST framework is a lightweight library that makes it easy to build Web APIs. It is designed as a modular and easy to customize architecture, based on Django's class based views.</p>
|
||||||
|
<p>Web APIs built using REST framework are fully self-describing and web browseable - a huge useability win for your developers. It also supports a wide range of media types, authentication and permission policies out of the box.</p>
|
||||||
|
<h2 id="requirements">Requirements</h2>
|
||||||
|
<p>REST framework requires the following:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Python (2.6, 2.7)</li>
|
||||||
|
<li>Django (1.3, 1.4, 1.5)</li>
|
||||||
|
<li><a href="https://github.com/zacharyvoase/urlobject">URLObject</a> (2.0.0+)</li>
|
||||||
|
</ul>
|
||||||
|
<p>The following packages are optional:</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://pypi.python.org/pypi/Markdown/">Markdown</a> (2.1.0+) - Markdown support for the self describing API.</li>
|
||||||
|
<li><a href="http://pypi.python.org/pypi/PyYAML">PyYAML</a> (3.10+) - YAML content type support.</li>
|
||||||
|
</ul>
|
||||||
|
<p>If you're installing using <code>pip</code>, all requirements and optional packages will be installed by default.</p>
|
||||||
|
<h2 id="installation">Installation</h2>
|
||||||
|
<p><strong>WARNING: These instructions will only become valid once this becomes the master version</strong></p>
|
||||||
|
<p>Install using <code>pip</code>...</p>
|
||||||
|
<pre><code>pip install djangorestframework
|
||||||
|
</code></pre>
|
||||||
|
<p>...or clone the project from github.</p>
|
||||||
|
<pre><code>git clone git@github.com:tomchristie/django-rest-framework.git
|
||||||
|
pip install -r requirements.txt
|
||||||
|
</code></pre>
|
||||||
|
<p>Add <code>djangorestframework</code> to your <code>INSTALLED_APPS</code>.</p>
|
||||||
|
<pre><code>INSTALLED_APPS = (
|
||||||
|
...
|
||||||
|
'djangorestframework',
|
||||||
|
)
|
||||||
|
</code></pre>
|
||||||
|
<p>If you're intending to use the browserable API you'll want to add REST framework's login and logout views. Add the following to your root <code>urls.py</code> file.</p>
|
||||||
|
<pre><code>urlpatterns = patterns('',
|
||||||
|
...
|
||||||
|
url(r'^auth', include('djangorestframework.urls', namespace='djangorestframework'))
|
||||||
|
)
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="quickstart">Quickstart</h2>
|
||||||
|
<p><strong>TODO</strong></p>
|
||||||
|
<h2 id="tutorial">Tutorial</h2>
|
||||||
|
<p>The tutorial will walk you through the building blocks that make up REST framework. It'll take a little while to get through, but it'll give you a comprehensive understanding of how everything fits together, and is highly recommended reading.</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="tutorial/1-serialization.html">1 - Serialization</a></li>
|
||||||
|
<li><a href="tutorial/2-requests-and-responses.html">2 - Requests & Responses</a></li>
|
||||||
|
<li><a href="tutorial/3-class-based-views.html">3 - Class based views</a></li>
|
||||||
|
<li><a href="tutorial/4-authentication-permissions-and-throttling.html">4 - Authentication, permissions & throttling</a></li>
|
||||||
|
<li><a href="tutorial/5-relationships-and-hyperlinked-apis.html">5 - Relationships & hyperlinked APIs</a></li>
|
||||||
|
<li><a href="tutorial/6-resource-orientated-projects.html">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
<h2 id="api-guide">API Guide</h2>
|
||||||
|
<p>The API guide is your complete reference manual to all the functionality provided by REST framework.</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="api-guide/requests.html">Requests</a></li>
|
||||||
|
<li><a href="api-guide/responses.html">Responses</a></li>
|
||||||
|
<li><a href="api-guide/views.html">Views</a></li>
|
||||||
|
<li><a href="api-guide/parsers.html">Parsers</a></li>
|
||||||
|
<li><a href="api-guide/renderers.html">Renderers</a></li>
|
||||||
|
<li><a href="api-guide/serializers.html">Serializers</a></li>
|
||||||
|
<li><a href="api-guide/authentication.html">Authentication</a></li>
|
||||||
|
<li><a href="api-guide/permissions.html">Permissions</a></li>
|
||||||
|
<li><a href="api-guide/exceptions.html">Exceptions</a></li>
|
||||||
|
<li><a href="api-guide/status.html">Status codes</a></li>
|
||||||
|
<li><a href="api-guide/urls.html">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
<h2 id="topics">Topics</h2>
|
||||||
|
<p>General guides to using REST framework.</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="topics/csrf.html">CSRF</a></li>
|
||||||
|
<li><a href="topics/formoverloading.html">Form overloading</a></li>
|
||||||
|
<li><a href="topics/credits.html">Credits</a></li>
|
||||||
|
</ul>
|
||||||
|
<h2 id="license">License</h2>
|
||||||
|
<p>Copyright (c) 2011-2012, Tom Christie
|
||||||
|
All rights reserved.</p>
|
||||||
|
<p>Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:</p>
|
||||||
|
<p>Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.</p>
|
||||||
|
<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
90
js/bootstrap-alert.js
vendored
Normal file
90
js/bootstrap-alert.js
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/* ==========================================================
|
||||||
|
* bootstrap-alert.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#alerts
|
||||||
|
* ==========================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ========================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* ALERT CLASS DEFINITION
|
||||||
|
* ====================== */
|
||||||
|
|
||||||
|
var dismiss = '[data-dismiss="alert"]'
|
||||||
|
, Alert = function (el) {
|
||||||
|
$(el).on('click', dismiss, this.close)
|
||||||
|
}
|
||||||
|
|
||||||
|
Alert.prototype.close = function (e) {
|
||||||
|
var $this = $(this)
|
||||||
|
, selector = $this.attr('data-target')
|
||||||
|
, $parent
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
selector = $this.attr('href')
|
||||||
|
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
||||||
|
}
|
||||||
|
|
||||||
|
$parent = $(selector)
|
||||||
|
|
||||||
|
e && e.preventDefault()
|
||||||
|
|
||||||
|
$parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
|
||||||
|
|
||||||
|
$parent.trigger(e = $.Event('close'))
|
||||||
|
|
||||||
|
if (e.isDefaultPrevented()) return
|
||||||
|
|
||||||
|
$parent.removeClass('in')
|
||||||
|
|
||||||
|
function removeElement() {
|
||||||
|
$parent
|
||||||
|
.trigger('closed')
|
||||||
|
.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
$.support.transition && $parent.hasClass('fade') ?
|
||||||
|
$parent.on($.support.transition.end, removeElement) :
|
||||||
|
removeElement()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ALERT PLUGIN DEFINITION
|
||||||
|
* ======================= */
|
||||||
|
|
||||||
|
$.fn.alert = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('alert')
|
||||||
|
if (!data) $this.data('alert', (data = new Alert(this)))
|
||||||
|
if (typeof option == 'string') data[option].call($this)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.alert.Constructor = Alert
|
||||||
|
|
||||||
|
|
||||||
|
/* ALERT DATA-API
|
||||||
|
* ============== */
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
96
js/bootstrap-button.js
vendored
Normal file
96
js/bootstrap-button.js
vendored
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* ============================================================
|
||||||
|
* bootstrap-button.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#buttons
|
||||||
|
* ============================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ============================================================ */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* BUTTON PUBLIC CLASS DEFINITION
|
||||||
|
* ============================== */
|
||||||
|
|
||||||
|
var Button = function (element, options) {
|
||||||
|
this.$element = $(element)
|
||||||
|
this.options = $.extend({}, $.fn.button.defaults, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button.prototype.setState = function (state) {
|
||||||
|
var d = 'disabled'
|
||||||
|
, $el = this.$element
|
||||||
|
, data = $el.data()
|
||||||
|
, val = $el.is('input') ? 'val' : 'html'
|
||||||
|
|
||||||
|
state = state + 'Text'
|
||||||
|
data.resetText || $el.data('resetText', $el[val]())
|
||||||
|
|
||||||
|
$el[val](data[state] || this.options[state])
|
||||||
|
|
||||||
|
// push to event loop to allow forms to submit
|
||||||
|
setTimeout(function () {
|
||||||
|
state == 'loadingText' ?
|
||||||
|
$el.addClass(d).attr(d, d) :
|
||||||
|
$el.removeClass(d).removeAttr(d)
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button.prototype.toggle = function () {
|
||||||
|
var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
|
||||||
|
|
||||||
|
$parent && $parent
|
||||||
|
.find('.active')
|
||||||
|
.removeClass('active')
|
||||||
|
|
||||||
|
this.$element.toggleClass('active')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* BUTTON PLUGIN DEFINITION
|
||||||
|
* ======================== */
|
||||||
|
|
||||||
|
$.fn.button = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('button')
|
||||||
|
, options = typeof option == 'object' && option
|
||||||
|
if (!data) $this.data('button', (data = new Button(this, options)))
|
||||||
|
if (option == 'toggle') data.toggle()
|
||||||
|
else if (option) data.setState(option)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.button.defaults = {
|
||||||
|
loadingText: 'loading...'
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.button.Constructor = Button
|
||||||
|
|
||||||
|
|
||||||
|
/* BUTTON DATA-API
|
||||||
|
* =============== */
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) {
|
||||||
|
var $btn = $(e.target)
|
||||||
|
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
|
||||||
|
$btn.button('toggle')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
176
js/bootstrap-carousel.js
vendored
Normal file
176
js/bootstrap-carousel.js
vendored
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
/* ==========================================================
|
||||||
|
* bootstrap-carousel.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#carousel
|
||||||
|
* ==========================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ========================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* CAROUSEL CLASS DEFINITION
|
||||||
|
* ========================= */
|
||||||
|
|
||||||
|
var Carousel = function (element, options) {
|
||||||
|
this.$element = $(element)
|
||||||
|
this.options = options
|
||||||
|
this.options.slide && this.slide(this.options.slide)
|
||||||
|
this.options.pause == 'hover' && this.$element
|
||||||
|
.on('mouseenter', $.proxy(this.pause, this))
|
||||||
|
.on('mouseleave', $.proxy(this.cycle, this))
|
||||||
|
}
|
||||||
|
|
||||||
|
Carousel.prototype = {
|
||||||
|
|
||||||
|
cycle: function (e) {
|
||||||
|
if (!e) this.paused = false
|
||||||
|
this.options.interval
|
||||||
|
&& !this.paused
|
||||||
|
&& (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
, to: function (pos) {
|
||||||
|
var $active = this.$element.find('.item.active')
|
||||||
|
, children = $active.parent().children()
|
||||||
|
, activePos = children.index($active)
|
||||||
|
, that = this
|
||||||
|
|
||||||
|
if (pos > (children.length - 1) || pos < 0) return
|
||||||
|
|
||||||
|
if (this.sliding) {
|
||||||
|
return this.$element.one('slid', function () {
|
||||||
|
that.to(pos)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activePos == pos) {
|
||||||
|
return this.pause().cycle()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
|
||||||
|
}
|
||||||
|
|
||||||
|
, pause: function (e) {
|
||||||
|
if (!e) this.paused = true
|
||||||
|
if (this.$element.find('.next, .prev').length && $.support.transition.end) {
|
||||||
|
this.$element.trigger($.support.transition.end)
|
||||||
|
this.cycle()
|
||||||
|
}
|
||||||
|
clearInterval(this.interval)
|
||||||
|
this.interval = null
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
, next: function () {
|
||||||
|
if (this.sliding) return
|
||||||
|
return this.slide('next')
|
||||||
|
}
|
||||||
|
|
||||||
|
, prev: function () {
|
||||||
|
if (this.sliding) return
|
||||||
|
return this.slide('prev')
|
||||||
|
}
|
||||||
|
|
||||||
|
, slide: function (type, next) {
|
||||||
|
var $active = this.$element.find('.item.active')
|
||||||
|
, $next = next || $active[type]()
|
||||||
|
, isCycling = this.interval
|
||||||
|
, direction = type == 'next' ? 'left' : 'right'
|
||||||
|
, fallback = type == 'next' ? 'first' : 'last'
|
||||||
|
, that = this
|
||||||
|
, e = $.Event('slide', {
|
||||||
|
relatedTarget: $next[0]
|
||||||
|
})
|
||||||
|
|
||||||
|
this.sliding = true
|
||||||
|
|
||||||
|
isCycling && this.pause()
|
||||||
|
|
||||||
|
$next = $next.length ? $next : this.$element.find('.item')[fallback]()
|
||||||
|
|
||||||
|
if ($next.hasClass('active')) return
|
||||||
|
|
||||||
|
if ($.support.transition && this.$element.hasClass('slide')) {
|
||||||
|
this.$element.trigger(e)
|
||||||
|
if (e.isDefaultPrevented()) return
|
||||||
|
$next.addClass(type)
|
||||||
|
$next[0].offsetWidth // force reflow
|
||||||
|
$active.addClass(direction)
|
||||||
|
$next.addClass(direction)
|
||||||
|
this.$element.one($.support.transition.end, function () {
|
||||||
|
$next.removeClass([type, direction].join(' ')).addClass('active')
|
||||||
|
$active.removeClass(['active', direction].join(' '))
|
||||||
|
that.sliding = false
|
||||||
|
setTimeout(function () { that.$element.trigger('slid') }, 0)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$element.trigger(e)
|
||||||
|
if (e.isDefaultPrevented()) return
|
||||||
|
$active.removeClass('active')
|
||||||
|
$next.addClass('active')
|
||||||
|
this.sliding = false
|
||||||
|
this.$element.trigger('slid')
|
||||||
|
}
|
||||||
|
|
||||||
|
isCycling && this.cycle()
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* CAROUSEL PLUGIN DEFINITION
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
$.fn.carousel = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('carousel')
|
||||||
|
, options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
|
||||||
|
, action = typeof option == 'string' ? option : options.slide
|
||||||
|
if (!data) $this.data('carousel', (data = new Carousel(this, options)))
|
||||||
|
if (typeof option == 'number') data.to(option)
|
||||||
|
else if (action) data[action]()
|
||||||
|
else if (options.interval) data.cycle()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.carousel.defaults = {
|
||||||
|
interval: 5000
|
||||||
|
, pause: 'hover'
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.carousel.Constructor = Carousel
|
||||||
|
|
||||||
|
|
||||||
|
/* CAROUSEL DATA-API
|
||||||
|
* ================= */
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('body').on('click.carousel.data-api', '[data-slide]', function ( e ) {
|
||||||
|
var $this = $(this), href
|
||||||
|
, $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
|
||||||
|
, options = !$target.data('modal') && $.extend({}, $target.data(), $this.data())
|
||||||
|
$target.carousel(options)
|
||||||
|
e.preventDefault()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
158
js/bootstrap-collapse.js
vendored
Normal file
158
js/bootstrap-collapse.js
vendored
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/* =============================================================
|
||||||
|
* bootstrap-collapse.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#collapse
|
||||||
|
* =============================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ============================================================ */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* COLLAPSE PUBLIC CLASS DEFINITION
|
||||||
|
* ================================ */
|
||||||
|
|
||||||
|
var Collapse = function (element, options) {
|
||||||
|
this.$element = $(element)
|
||||||
|
this.options = $.extend({}, $.fn.collapse.defaults, options)
|
||||||
|
|
||||||
|
if (this.options.parent) {
|
||||||
|
this.$parent = $(this.options.parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.options.toggle && this.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
Collapse.prototype = {
|
||||||
|
|
||||||
|
constructor: Collapse
|
||||||
|
|
||||||
|
, dimension: function () {
|
||||||
|
var hasWidth = this.$element.hasClass('width')
|
||||||
|
return hasWidth ? 'width' : 'height'
|
||||||
|
}
|
||||||
|
|
||||||
|
, show: function () {
|
||||||
|
var dimension
|
||||||
|
, scroll
|
||||||
|
, actives
|
||||||
|
, hasData
|
||||||
|
|
||||||
|
if (this.transitioning) return
|
||||||
|
|
||||||
|
dimension = this.dimension()
|
||||||
|
scroll = $.camelCase(['scroll', dimension].join('-'))
|
||||||
|
actives = this.$parent && this.$parent.find('> .accordion-group > .in')
|
||||||
|
|
||||||
|
if (actives && actives.length) {
|
||||||
|
hasData = actives.data('collapse')
|
||||||
|
if (hasData && hasData.transitioning) return
|
||||||
|
actives.collapse('hide')
|
||||||
|
hasData || actives.data('collapse', null)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$element[dimension](0)
|
||||||
|
this.transition('addClass', $.Event('show'), 'shown')
|
||||||
|
$.support.transition && this.$element[dimension](this.$element[0][scroll])
|
||||||
|
}
|
||||||
|
|
||||||
|
, hide: function () {
|
||||||
|
var dimension
|
||||||
|
if (this.transitioning) return
|
||||||
|
dimension = this.dimension()
|
||||||
|
this.reset(this.$element[dimension]())
|
||||||
|
this.transition('removeClass', $.Event('hide'), 'hidden')
|
||||||
|
this.$element[dimension](0)
|
||||||
|
}
|
||||||
|
|
||||||
|
, reset: function (size) {
|
||||||
|
var dimension = this.dimension()
|
||||||
|
|
||||||
|
this.$element
|
||||||
|
.removeClass('collapse')
|
||||||
|
[dimension](size || 'auto')
|
||||||
|
[0].offsetWidth
|
||||||
|
|
||||||
|
this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
, transition: function (method, startEvent, completeEvent) {
|
||||||
|
var that = this
|
||||||
|
, complete = function () {
|
||||||
|
if (startEvent.type == 'show') that.reset()
|
||||||
|
that.transitioning = 0
|
||||||
|
that.$element.trigger(completeEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$element.trigger(startEvent)
|
||||||
|
|
||||||
|
if (startEvent.isDefaultPrevented()) return
|
||||||
|
|
||||||
|
this.transitioning = 1
|
||||||
|
|
||||||
|
this.$element[method]('in')
|
||||||
|
|
||||||
|
$.support.transition && this.$element.hasClass('collapse') ?
|
||||||
|
this.$element.one($.support.transition.end, complete) :
|
||||||
|
complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
, toggle: function () {
|
||||||
|
this[this.$element.hasClass('in') ? 'hide' : 'show']()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* COLLAPSIBLE PLUGIN DEFINITION
|
||||||
|
* ============================== */
|
||||||
|
|
||||||
|
$.fn.collapse = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('collapse')
|
||||||
|
, options = typeof option == 'object' && option
|
||||||
|
if (!data) $this.data('collapse', (data = new Collapse(this, options)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.collapse.defaults = {
|
||||||
|
toggle: true
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.collapse.Constructor = Collapse
|
||||||
|
|
||||||
|
|
||||||
|
/* COLLAPSIBLE DATA-API
|
||||||
|
* ==================== */
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('body').on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
|
||||||
|
var $this = $(this), href
|
||||||
|
, target = $this.attr('data-target')
|
||||||
|
|| e.preventDefault()
|
||||||
|
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
|
||||||
|
, option = $(target).data('collapse') ? 'toggle' : $this.data()
|
||||||
|
$this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
|
||||||
|
$(target).collapse(option)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
150
js/bootstrap-dropdown.js
vendored
Normal file
150
js/bootstrap-dropdown.js
vendored
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/* ============================================================
|
||||||
|
* bootstrap-dropdown.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#dropdowns
|
||||||
|
* ============================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ============================================================ */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* DROPDOWN CLASS DEFINITION
|
||||||
|
* ========================= */
|
||||||
|
|
||||||
|
var toggle = '[data-toggle=dropdown]'
|
||||||
|
, Dropdown = function (element) {
|
||||||
|
var $el = $(element).on('click.dropdown.data-api', this.toggle)
|
||||||
|
$('html').on('click.dropdown.data-api', function () {
|
||||||
|
$el.parent().removeClass('open')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Dropdown.prototype = {
|
||||||
|
|
||||||
|
constructor: Dropdown
|
||||||
|
|
||||||
|
, toggle: function (e) {
|
||||||
|
var $this = $(this)
|
||||||
|
, $parent
|
||||||
|
, isActive
|
||||||
|
|
||||||
|
if ($this.is('.disabled, :disabled')) return
|
||||||
|
|
||||||
|
$parent = getParent($this)
|
||||||
|
|
||||||
|
isActive = $parent.hasClass('open')
|
||||||
|
|
||||||
|
clearMenus()
|
||||||
|
|
||||||
|
if (!isActive) {
|
||||||
|
$parent.toggleClass('open')
|
||||||
|
$this.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
, keydown: function (e) {
|
||||||
|
var $this
|
||||||
|
, $items
|
||||||
|
, $active
|
||||||
|
, $parent
|
||||||
|
, isActive
|
||||||
|
, index
|
||||||
|
|
||||||
|
if (!/(38|40|27)/.test(e.keyCode)) return
|
||||||
|
|
||||||
|
$this = $(this)
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
if ($this.is('.disabled, :disabled')) return
|
||||||
|
|
||||||
|
$parent = getParent($this)
|
||||||
|
|
||||||
|
isActive = $parent.hasClass('open')
|
||||||
|
|
||||||
|
if (!isActive || (isActive && e.keyCode == 27)) return $this.click()
|
||||||
|
|
||||||
|
$items = $('[role=menu] li:not(.divider) a', $parent)
|
||||||
|
|
||||||
|
if (!$items.length) return
|
||||||
|
|
||||||
|
index = $items.index($items.filter(':focus'))
|
||||||
|
|
||||||
|
if (e.keyCode == 38 && index > 0) index-- // up
|
||||||
|
if (e.keyCode == 40 && index < $items.length - 1) index++ // down
|
||||||
|
if (!~index) index = 0
|
||||||
|
|
||||||
|
$items
|
||||||
|
.eq(index)
|
||||||
|
.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearMenus() {
|
||||||
|
getParent($(toggle))
|
||||||
|
.removeClass('open')
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParent($this) {
|
||||||
|
var selector = $this.attr('data-target')
|
||||||
|
, $parent
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
selector = $this.attr('href')
|
||||||
|
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
||||||
|
}
|
||||||
|
|
||||||
|
$parent = $(selector)
|
||||||
|
$parent.length || ($parent = $this.parent())
|
||||||
|
|
||||||
|
return $parent
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* DROPDOWN PLUGIN DEFINITION
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
$.fn.dropdown = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('dropdown')
|
||||||
|
if (!data) $this.data('dropdown', (data = new Dropdown(this)))
|
||||||
|
if (typeof option == 'string') data[option].call($this)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.dropdown.Constructor = Dropdown
|
||||||
|
|
||||||
|
|
||||||
|
/* APPLY TO STANDARD DROPDOWN ELEMENTS
|
||||||
|
* =================================== */
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('html')
|
||||||
|
.on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus)
|
||||||
|
$('body')
|
||||||
|
.on('click.dropdown touchstart.dropdown.data-api', '.dropdown', function (e) { e.stopPropagation() })
|
||||||
|
.on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
|
||||||
|
.on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
239
js/bootstrap-modal.js
vendored
Normal file
239
js/bootstrap-modal.js
vendored
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
/* =========================================================
|
||||||
|
* bootstrap-modal.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#modals
|
||||||
|
* =========================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ========================================================= */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* MODAL CLASS DEFINITION
|
||||||
|
* ====================== */
|
||||||
|
|
||||||
|
var Modal = function (element, options) {
|
||||||
|
this.options = options
|
||||||
|
this.$element = $(element)
|
||||||
|
.delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
|
||||||
|
this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
|
||||||
|
}
|
||||||
|
|
||||||
|
Modal.prototype = {
|
||||||
|
|
||||||
|
constructor: Modal
|
||||||
|
|
||||||
|
, toggle: function () {
|
||||||
|
return this[!this.isShown ? 'show' : 'hide']()
|
||||||
|
}
|
||||||
|
|
||||||
|
, show: function () {
|
||||||
|
var that = this
|
||||||
|
, e = $.Event('show')
|
||||||
|
|
||||||
|
this.$element.trigger(e)
|
||||||
|
|
||||||
|
if (this.isShown || e.isDefaultPrevented()) return
|
||||||
|
|
||||||
|
$('body').addClass('modal-open')
|
||||||
|
|
||||||
|
this.isShown = true
|
||||||
|
|
||||||
|
this.escape()
|
||||||
|
|
||||||
|
this.backdrop(function () {
|
||||||
|
var transition = $.support.transition && that.$element.hasClass('fade')
|
||||||
|
|
||||||
|
if (!that.$element.parent().length) {
|
||||||
|
that.$element.appendTo(document.body) //don't move modals dom position
|
||||||
|
}
|
||||||
|
|
||||||
|
that.$element
|
||||||
|
.show()
|
||||||
|
|
||||||
|
if (transition) {
|
||||||
|
that.$element[0].offsetWidth // force reflow
|
||||||
|
}
|
||||||
|
|
||||||
|
that.$element
|
||||||
|
.addClass('in')
|
||||||
|
.attr('aria-hidden', false)
|
||||||
|
.focus()
|
||||||
|
|
||||||
|
that.enforceFocus()
|
||||||
|
|
||||||
|
transition ?
|
||||||
|
that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
|
||||||
|
that.$element.trigger('shown')
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
, hide: function (e) {
|
||||||
|
e && e.preventDefault()
|
||||||
|
|
||||||
|
var that = this
|
||||||
|
|
||||||
|
e = $.Event('hide')
|
||||||
|
|
||||||
|
this.$element.trigger(e)
|
||||||
|
|
||||||
|
if (!this.isShown || e.isDefaultPrevented()) return
|
||||||
|
|
||||||
|
this.isShown = false
|
||||||
|
|
||||||
|
$('body').removeClass('modal-open')
|
||||||
|
|
||||||
|
this.escape()
|
||||||
|
|
||||||
|
$(document).off('focusin.modal')
|
||||||
|
|
||||||
|
this.$element
|
||||||
|
.removeClass('in')
|
||||||
|
.attr('aria-hidden', true)
|
||||||
|
|
||||||
|
$.support.transition && this.$element.hasClass('fade') ?
|
||||||
|
this.hideWithTransition() :
|
||||||
|
this.hideModal()
|
||||||
|
}
|
||||||
|
|
||||||
|
, enforceFocus: function () {
|
||||||
|
var that = this
|
||||||
|
$(document).on('focusin.modal', function (e) {
|
||||||
|
if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
|
||||||
|
that.$element.focus()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
, escape: function () {
|
||||||
|
var that = this
|
||||||
|
if (this.isShown && this.options.keyboard) {
|
||||||
|
this.$element.on('keyup.dismiss.modal', function ( e ) {
|
||||||
|
e.which == 27 && that.hide()
|
||||||
|
})
|
||||||
|
} else if (!this.isShown) {
|
||||||
|
this.$element.off('keyup.dismiss.modal')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
, hideWithTransition: function () {
|
||||||
|
var that = this
|
||||||
|
, timeout = setTimeout(function () {
|
||||||
|
that.$element.off($.support.transition.end)
|
||||||
|
that.hideModal()
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
this.$element.one($.support.transition.end, function () {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
that.hideModal()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
, hideModal: function (that) {
|
||||||
|
this.$element
|
||||||
|
.hide()
|
||||||
|
.trigger('hidden')
|
||||||
|
|
||||||
|
this.backdrop()
|
||||||
|
}
|
||||||
|
|
||||||
|
, removeBackdrop: function () {
|
||||||
|
this.$backdrop.remove()
|
||||||
|
this.$backdrop = null
|
||||||
|
}
|
||||||
|
|
||||||
|
, backdrop: function (callback) {
|
||||||
|
var that = this
|
||||||
|
, animate = this.$element.hasClass('fade') ? 'fade' : ''
|
||||||
|
|
||||||
|
if (this.isShown && this.options.backdrop) {
|
||||||
|
var doAnimate = $.support.transition && animate
|
||||||
|
|
||||||
|
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
|
||||||
|
.appendTo(document.body)
|
||||||
|
|
||||||
|
if (this.options.backdrop != 'static') {
|
||||||
|
this.$backdrop.click($.proxy(this.hide, this))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
|
||||||
|
|
||||||
|
this.$backdrop.addClass('in')
|
||||||
|
|
||||||
|
doAnimate ?
|
||||||
|
this.$backdrop.one($.support.transition.end, callback) :
|
||||||
|
callback()
|
||||||
|
|
||||||
|
} else if (!this.isShown && this.$backdrop) {
|
||||||
|
this.$backdrop.removeClass('in')
|
||||||
|
|
||||||
|
$.support.transition && this.$element.hasClass('fade')?
|
||||||
|
this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
|
||||||
|
this.removeBackdrop()
|
||||||
|
|
||||||
|
} else if (callback) {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MODAL PLUGIN DEFINITION
|
||||||
|
* ======================= */
|
||||||
|
|
||||||
|
$.fn.modal = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('modal')
|
||||||
|
, options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
|
||||||
|
if (!data) $this.data('modal', (data = new Modal(this, options)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
else if (options.show) data.show()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.modal.defaults = {
|
||||||
|
backdrop: true
|
||||||
|
, keyboard: true
|
||||||
|
, show: true
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.modal.Constructor = Modal
|
||||||
|
|
||||||
|
|
||||||
|
/* MODAL DATA-API
|
||||||
|
* ============== */
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
|
||||||
|
var $this = $(this)
|
||||||
|
, href = $this.attr('href')
|
||||||
|
, $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
|
||||||
|
, option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
$target
|
||||||
|
.modal(option)
|
||||||
|
.one('hide', function () {
|
||||||
|
$this.focus()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
103
js/bootstrap-popover.js
vendored
Normal file
103
js/bootstrap-popover.js
vendored
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/* ===========================================================
|
||||||
|
* bootstrap-popover.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#popovers
|
||||||
|
* ===========================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* =========================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* POPOVER PUBLIC CLASS DEFINITION
|
||||||
|
* =============================== */
|
||||||
|
|
||||||
|
var Popover = function (element, options) {
|
||||||
|
this.init('popover', element, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
|
||||||
|
========================================== */
|
||||||
|
|
||||||
|
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
|
||||||
|
|
||||||
|
constructor: Popover
|
||||||
|
|
||||||
|
, setContent: function () {
|
||||||
|
var $tip = this.tip()
|
||||||
|
, title = this.getTitle()
|
||||||
|
, content = this.getContent()
|
||||||
|
|
||||||
|
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
|
||||||
|
$tip.find('.popover-content > *')[this.options.html ? 'html' : 'text'](content)
|
||||||
|
|
||||||
|
$tip.removeClass('fade top bottom left right in')
|
||||||
|
}
|
||||||
|
|
||||||
|
, hasContent: function () {
|
||||||
|
return this.getTitle() || this.getContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
, getContent: function () {
|
||||||
|
var content
|
||||||
|
, $e = this.$element
|
||||||
|
, o = this.options
|
||||||
|
|
||||||
|
content = $e.attr('data-content')
|
||||||
|
|| (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
|
||||||
|
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
, tip: function () {
|
||||||
|
if (!this.$tip) {
|
||||||
|
this.$tip = $(this.options.template)
|
||||||
|
}
|
||||||
|
return this.$tip
|
||||||
|
}
|
||||||
|
|
||||||
|
, destroy: function () {
|
||||||
|
this.hide().$element.off('.' + this.type).removeData(this.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
/* POPOVER PLUGIN DEFINITION
|
||||||
|
* ======================= */
|
||||||
|
|
||||||
|
$.fn.popover = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('popover')
|
||||||
|
, options = typeof option == 'object' && option
|
||||||
|
if (!data) $this.data('popover', (data = new Popover(this, options)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.popover.Constructor = Popover
|
||||||
|
|
||||||
|
$.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
|
||||||
|
placement: 'right'
|
||||||
|
, trigger: 'click'
|
||||||
|
, content: ''
|
||||||
|
, template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
151
js/bootstrap-scrollspy.js
vendored
Normal file
151
js/bootstrap-scrollspy.js
vendored
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/* =============================================================
|
||||||
|
* bootstrap-scrollspy.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#scrollspy
|
||||||
|
* =============================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ============================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* SCROLLSPY CLASS DEFINITION
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
function ScrollSpy(element, options) {
|
||||||
|
var process = $.proxy(this.process, this)
|
||||||
|
, $element = $(element).is('body') ? $(window) : $(element)
|
||||||
|
, href
|
||||||
|
this.options = $.extend({}, $.fn.scrollspy.defaults, options)
|
||||||
|
this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
|
||||||
|
this.selector = (this.options.target
|
||||||
|
|| ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
|
||||||
|
|| '') + ' .nav li > a'
|
||||||
|
this.$body = $('body')
|
||||||
|
this.refresh()
|
||||||
|
this.process()
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollSpy.prototype = {
|
||||||
|
|
||||||
|
constructor: ScrollSpy
|
||||||
|
|
||||||
|
, refresh: function () {
|
||||||
|
var self = this
|
||||||
|
, $targets
|
||||||
|
|
||||||
|
this.offsets = $([])
|
||||||
|
this.targets = $([])
|
||||||
|
|
||||||
|
$targets = this.$body
|
||||||
|
.find(this.selector)
|
||||||
|
.map(function () {
|
||||||
|
var $el = $(this)
|
||||||
|
, href = $el.data('target') || $el.attr('href')
|
||||||
|
, $href = /^#\w/.test(href) && $(href)
|
||||||
|
return ( $href
|
||||||
|
&& $href.length
|
||||||
|
&& [[ $href.position().top, href ]] ) || null
|
||||||
|
})
|
||||||
|
.sort(function (a, b) { return a[0] - b[0] })
|
||||||
|
.each(function () {
|
||||||
|
self.offsets.push(this[0])
|
||||||
|
self.targets.push(this[1])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
, process: function () {
|
||||||
|
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
|
||||||
|
, scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
|
||||||
|
, maxScroll = scrollHeight - this.$scrollElement.height()
|
||||||
|
, offsets = this.offsets
|
||||||
|
, targets = this.targets
|
||||||
|
, activeTarget = this.activeTarget
|
||||||
|
, i
|
||||||
|
|
||||||
|
if (scrollTop >= maxScroll) {
|
||||||
|
return activeTarget != (i = targets.last()[0])
|
||||||
|
&& this.activate ( i )
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = offsets.length; i--;) {
|
||||||
|
activeTarget != targets[i]
|
||||||
|
&& scrollTop >= offsets[i]
|
||||||
|
&& (!offsets[i + 1] || scrollTop <= offsets[i + 1])
|
||||||
|
&& this.activate( targets[i] )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
, activate: function (target) {
|
||||||
|
var active
|
||||||
|
, selector
|
||||||
|
|
||||||
|
this.activeTarget = target
|
||||||
|
|
||||||
|
$(this.selector)
|
||||||
|
.parent('.active')
|
||||||
|
.removeClass('active')
|
||||||
|
|
||||||
|
selector = this.selector
|
||||||
|
+ '[data-target="' + target + '"],'
|
||||||
|
+ this.selector + '[href="' + target + '"]'
|
||||||
|
|
||||||
|
active = $(selector)
|
||||||
|
.parent('li')
|
||||||
|
.addClass('active')
|
||||||
|
|
||||||
|
if (active.parent('.dropdown-menu').length) {
|
||||||
|
active = active.closest('li.dropdown').addClass('active')
|
||||||
|
}
|
||||||
|
|
||||||
|
active.trigger('activate')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SCROLLSPY PLUGIN DEFINITION
|
||||||
|
* =========================== */
|
||||||
|
|
||||||
|
$.fn.scrollspy = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('scrollspy')
|
||||||
|
, options = typeof option == 'object' && option
|
||||||
|
if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.scrollspy.Constructor = ScrollSpy
|
||||||
|
|
||||||
|
$.fn.scrollspy.defaults = {
|
||||||
|
offset: 10
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SCROLLSPY DATA-API
|
||||||
|
* ================== */
|
||||||
|
|
||||||
|
$(window).on('load', function () {
|
||||||
|
$('[data-spy="scroll"]').each(function () {
|
||||||
|
var $spy = $(this)
|
||||||
|
$spy.scrollspy($spy.data())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
135
js/bootstrap-tab.js
vendored
Normal file
135
js/bootstrap-tab.js
vendored
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/* ========================================================
|
||||||
|
* bootstrap-tab.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#tabs
|
||||||
|
* ========================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ======================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* TAB CLASS DEFINITION
|
||||||
|
* ==================== */
|
||||||
|
|
||||||
|
var Tab = function (element) {
|
||||||
|
this.element = $(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
Tab.prototype = {
|
||||||
|
|
||||||
|
constructor: Tab
|
||||||
|
|
||||||
|
, show: function () {
|
||||||
|
var $this = this.element
|
||||||
|
, $ul = $this.closest('ul:not(.dropdown-menu)')
|
||||||
|
, selector = $this.attr('data-target')
|
||||||
|
, previous
|
||||||
|
, $target
|
||||||
|
, e
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
selector = $this.attr('href')
|
||||||
|
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $this.parent('li').hasClass('active') ) return
|
||||||
|
|
||||||
|
previous = $ul.find('.active a').last()[0]
|
||||||
|
|
||||||
|
e = $.Event('show', {
|
||||||
|
relatedTarget: previous
|
||||||
|
})
|
||||||
|
|
||||||
|
$this.trigger(e)
|
||||||
|
|
||||||
|
if (e.isDefaultPrevented()) return
|
||||||
|
|
||||||
|
$target = $(selector)
|
||||||
|
|
||||||
|
this.activate($this.parent('li'), $ul)
|
||||||
|
this.activate($target, $target.parent(), function () {
|
||||||
|
$this.trigger({
|
||||||
|
type: 'shown'
|
||||||
|
, relatedTarget: previous
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
, activate: function ( element, container, callback) {
|
||||||
|
var $active = container.find('> .active')
|
||||||
|
, transition = callback
|
||||||
|
&& $.support.transition
|
||||||
|
&& $active.hasClass('fade')
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
$active
|
||||||
|
.removeClass('active')
|
||||||
|
.find('> .dropdown-menu > .active')
|
||||||
|
.removeClass('active')
|
||||||
|
|
||||||
|
element.addClass('active')
|
||||||
|
|
||||||
|
if (transition) {
|
||||||
|
element[0].offsetWidth // reflow for transition
|
||||||
|
element.addClass('in')
|
||||||
|
} else {
|
||||||
|
element.removeClass('fade')
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( element.parent('.dropdown-menu') ) {
|
||||||
|
element.closest('li.dropdown').addClass('active')
|
||||||
|
}
|
||||||
|
|
||||||
|
callback && callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
transition ?
|
||||||
|
$active.one($.support.transition.end, next) :
|
||||||
|
next()
|
||||||
|
|
||||||
|
$active.removeClass('in')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TAB PLUGIN DEFINITION
|
||||||
|
* ===================== */
|
||||||
|
|
||||||
|
$.fn.tab = function ( option ) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('tab')
|
||||||
|
if (!data) $this.data('tab', (data = new Tab(this)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.tab.Constructor = Tab
|
||||||
|
|
||||||
|
|
||||||
|
/* TAB DATA-API
|
||||||
|
* ============ */
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
|
||||||
|
e.preventDefault()
|
||||||
|
$(this).tab('show')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
275
js/bootstrap-tooltip.js
vendored
Normal file
275
js/bootstrap-tooltip.js
vendored
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
/* ===========================================================
|
||||||
|
* bootstrap-tooltip.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#tooltips
|
||||||
|
* Inspired by the original jQuery.tipsy by Jason Frame
|
||||||
|
* ===========================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ========================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* TOOLTIP PUBLIC CLASS DEFINITION
|
||||||
|
* =============================== */
|
||||||
|
|
||||||
|
var Tooltip = function (element, options) {
|
||||||
|
this.init('tooltip', element, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
Tooltip.prototype = {
|
||||||
|
|
||||||
|
constructor: Tooltip
|
||||||
|
|
||||||
|
, init: function (type, element, options) {
|
||||||
|
var eventIn
|
||||||
|
, eventOut
|
||||||
|
|
||||||
|
this.type = type
|
||||||
|
this.$element = $(element)
|
||||||
|
this.options = this.getOptions(options)
|
||||||
|
this.enabled = true
|
||||||
|
|
||||||
|
if (this.options.trigger == 'click') {
|
||||||
|
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
|
||||||
|
} else if (this.options.trigger != 'manual') {
|
||||||
|
eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
|
||||||
|
eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
|
||||||
|
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
|
||||||
|
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.options.selector ?
|
||||||
|
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
||||||
|
this.fixTitle()
|
||||||
|
}
|
||||||
|
|
||||||
|
, getOptions: function (options) {
|
||||||
|
options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
|
||||||
|
|
||||||
|
if (options.delay && typeof options.delay == 'number') {
|
||||||
|
options.delay = {
|
||||||
|
show: options.delay
|
||||||
|
, hide: options.delay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
, enter: function (e) {
|
||||||
|
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
||||||
|
|
||||||
|
if (!self.options.delay || !self.options.delay.show) return self.show()
|
||||||
|
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
self.hoverState = 'in'
|
||||||
|
this.timeout = setTimeout(function() {
|
||||||
|
if (self.hoverState == 'in') self.show()
|
||||||
|
}, self.options.delay.show)
|
||||||
|
}
|
||||||
|
|
||||||
|
, leave: function (e) {
|
||||||
|
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
||||||
|
|
||||||
|
if (this.timeout) clearTimeout(this.timeout)
|
||||||
|
if (!self.options.delay || !self.options.delay.hide) return self.hide()
|
||||||
|
|
||||||
|
self.hoverState = 'out'
|
||||||
|
this.timeout = setTimeout(function() {
|
||||||
|
if (self.hoverState == 'out') self.hide()
|
||||||
|
}, self.options.delay.hide)
|
||||||
|
}
|
||||||
|
|
||||||
|
, show: function () {
|
||||||
|
var $tip
|
||||||
|
, inside
|
||||||
|
, pos
|
||||||
|
, actualWidth
|
||||||
|
, actualHeight
|
||||||
|
, placement
|
||||||
|
, tp
|
||||||
|
|
||||||
|
if (this.hasContent() && this.enabled) {
|
||||||
|
$tip = this.tip()
|
||||||
|
this.setContent()
|
||||||
|
|
||||||
|
if (this.options.animation) {
|
||||||
|
$tip.addClass('fade')
|
||||||
|
}
|
||||||
|
|
||||||
|
placement = typeof this.options.placement == 'function' ?
|
||||||
|
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
||||||
|
this.options.placement
|
||||||
|
|
||||||
|
inside = /in/.test(placement)
|
||||||
|
|
||||||
|
$tip
|
||||||
|
.remove()
|
||||||
|
.css({ top: 0, left: 0, display: 'block' })
|
||||||
|
.appendTo(inside ? this.$element : document.body)
|
||||||
|
|
||||||
|
pos = this.getPosition(inside)
|
||||||
|
|
||||||
|
actualWidth = $tip[0].offsetWidth
|
||||||
|
actualHeight = $tip[0].offsetHeight
|
||||||
|
|
||||||
|
switch (inside ? placement.split(' ')[1] : placement) {
|
||||||
|
case 'bottom':
|
||||||
|
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
|
||||||
|
break
|
||||||
|
case 'top':
|
||||||
|
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
|
||||||
|
break
|
||||||
|
case 'left':
|
||||||
|
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
|
||||||
|
break
|
||||||
|
case 'right':
|
||||||
|
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
$tip
|
||||||
|
.css(tp)
|
||||||
|
.addClass(placement)
|
||||||
|
.addClass('in')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
, setContent: function () {
|
||||||
|
var $tip = this.tip()
|
||||||
|
, title = this.getTitle()
|
||||||
|
|
||||||
|
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
|
||||||
|
$tip.removeClass('fade in top bottom left right')
|
||||||
|
}
|
||||||
|
|
||||||
|
, hide: function () {
|
||||||
|
var that = this
|
||||||
|
, $tip = this.tip()
|
||||||
|
|
||||||
|
$tip.removeClass('in')
|
||||||
|
|
||||||
|
function removeWithAnimation() {
|
||||||
|
var timeout = setTimeout(function () {
|
||||||
|
$tip.off($.support.transition.end).remove()
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
$tip.one($.support.transition.end, function () {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
$tip.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.support.transition && this.$tip.hasClass('fade') ?
|
||||||
|
removeWithAnimation() :
|
||||||
|
$tip.remove()
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
, fixTitle: function () {
|
||||||
|
var $e = this.$element
|
||||||
|
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
|
||||||
|
$e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
, hasContent: function () {
|
||||||
|
return this.getTitle()
|
||||||
|
}
|
||||||
|
|
||||||
|
, getPosition: function (inside) {
|
||||||
|
return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
|
||||||
|
width: this.$element[0].offsetWidth
|
||||||
|
, height: this.$element[0].offsetHeight
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
, getTitle: function () {
|
||||||
|
var title
|
||||||
|
, $e = this.$element
|
||||||
|
, o = this.options
|
||||||
|
|
||||||
|
title = $e.attr('data-original-title')
|
||||||
|
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
||||||
|
|
||||||
|
return title
|
||||||
|
}
|
||||||
|
|
||||||
|
, tip: function () {
|
||||||
|
return this.$tip = this.$tip || $(this.options.template)
|
||||||
|
}
|
||||||
|
|
||||||
|
, validate: function () {
|
||||||
|
if (!this.$element[0].parentNode) {
|
||||||
|
this.hide()
|
||||||
|
this.$element = null
|
||||||
|
this.options = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
, enable: function () {
|
||||||
|
this.enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
, disable: function () {
|
||||||
|
this.enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
, toggleEnabled: function () {
|
||||||
|
this.enabled = !this.enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
, toggle: function () {
|
||||||
|
this[this.tip().hasClass('in') ? 'hide' : 'show']()
|
||||||
|
}
|
||||||
|
|
||||||
|
, destroy: function () {
|
||||||
|
this.hide().$element.off('.' + this.type).removeData(this.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TOOLTIP PLUGIN DEFINITION
|
||||||
|
* ========================= */
|
||||||
|
|
||||||
|
$.fn.tooltip = function ( option ) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('tooltip')
|
||||||
|
, options = typeof option == 'object' && option
|
||||||
|
if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.tooltip.Constructor = Tooltip
|
||||||
|
|
||||||
|
$.fn.tooltip.defaults = {
|
||||||
|
animation: true
|
||||||
|
, placement: 'top'
|
||||||
|
, selector: false
|
||||||
|
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
|
||||||
|
, trigger: 'hover'
|
||||||
|
, title: ''
|
||||||
|
, delay: 0
|
||||||
|
, html: true
|
||||||
|
}
|
||||||
|
|
||||||
|
}(window.jQuery);
|
60
js/bootstrap-transition.js
vendored
Normal file
60
js/bootstrap-transition.js
vendored
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/* ===================================================
|
||||||
|
* bootstrap-transition.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#transitions
|
||||||
|
* ===================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ========================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
!function ($) {
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
|
||||||
|
* ======================================================= */
|
||||||
|
|
||||||
|
$.support.transition = (function () {
|
||||||
|
|
||||||
|
var transitionEnd = (function () {
|
||||||
|
|
||||||
|
var el = document.createElement('bootstrap')
|
||||||
|
, transEndEventNames = {
|
||||||
|
'WebkitTransition' : 'webkitTransitionEnd'
|
||||||
|
, 'MozTransition' : 'transitionend'
|
||||||
|
, 'OTransition' : 'oTransitionEnd otransitionend'
|
||||||
|
, 'transition' : 'transitionend'
|
||||||
|
}
|
||||||
|
, name
|
||||||
|
|
||||||
|
for (name in transEndEventNames){
|
||||||
|
if (el.style[name] !== undefined) {
|
||||||
|
return transEndEventNames[name]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}())
|
||||||
|
|
||||||
|
return transitionEnd && {
|
||||||
|
end: transitionEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
})()
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
300
js/bootstrap-typeahead.js
vendored
Normal file
300
js/bootstrap-typeahead.js
vendored
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
/* =============================================================
|
||||||
|
* bootstrap-typeahead.js v2.1.0
|
||||||
|
* http://twitter.github.com/bootstrap/javascript.html#typeahead
|
||||||
|
* =============================================================
|
||||||
|
* Copyright 2012 Twitter, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ============================================================ */
|
||||||
|
|
||||||
|
|
||||||
|
!function($){
|
||||||
|
|
||||||
|
"use strict"; // jshint ;_;
|
||||||
|
|
||||||
|
|
||||||
|
/* TYPEAHEAD PUBLIC CLASS DEFINITION
|
||||||
|
* ================================= */
|
||||||
|
|
||||||
|
var Typeahead = function (element, options) {
|
||||||
|
this.$element = $(element)
|
||||||
|
this.options = $.extend({}, $.fn.typeahead.defaults, options)
|
||||||
|
this.matcher = this.options.matcher || this.matcher
|
||||||
|
this.sorter = this.options.sorter || this.sorter
|
||||||
|
this.highlighter = this.options.highlighter || this.highlighter
|
||||||
|
this.updater = this.options.updater || this.updater
|
||||||
|
this.$menu = $(this.options.menu).appendTo('body')
|
||||||
|
this.source = this.options.source
|
||||||
|
this.shown = false
|
||||||
|
this.listen()
|
||||||
|
}
|
||||||
|
|
||||||
|
Typeahead.prototype = {
|
||||||
|
|
||||||
|
constructor: Typeahead
|
||||||
|
|
||||||
|
, select: function () {
|
||||||
|
var val = this.$menu.find('.active').attr('data-value')
|
||||||
|
this.$element
|
||||||
|
.val(this.updater(val))
|
||||||
|
.change()
|
||||||
|
return this.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
, updater: function (item) {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
, show: function () {
|
||||||
|
var pos = $.extend({}, this.$element.offset(), {
|
||||||
|
height: this.$element[0].offsetHeight
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$menu.css({
|
||||||
|
top: pos.top + pos.height
|
||||||
|
, left: pos.left
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$menu.show()
|
||||||
|
this.shown = true
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
, hide: function () {
|
||||||
|
this.$menu.hide()
|
||||||
|
this.shown = false
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
, lookup: function (event) {
|
||||||
|
var items
|
||||||
|
|
||||||
|
this.query = this.$element.val()
|
||||||
|
|
||||||
|
if (!this.query || this.query.length < this.options.minLength) {
|
||||||
|
return this.shown ? this.hide() : this
|
||||||
|
}
|
||||||
|
|
||||||
|
items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
|
||||||
|
|
||||||
|
return items ? this.process(items) : this
|
||||||
|
}
|
||||||
|
|
||||||
|
, process: function (items) {
|
||||||
|
var that = this
|
||||||
|
|
||||||
|
items = $.grep(items, function (item) {
|
||||||
|
return that.matcher(item)
|
||||||
|
})
|
||||||
|
|
||||||
|
items = this.sorter(items)
|
||||||
|
|
||||||
|
if (!items.length) {
|
||||||
|
return this.shown ? this.hide() : this
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.render(items.slice(0, this.options.items)).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
, matcher: function (item) {
|
||||||
|
return ~item.toLowerCase().indexOf(this.query.toLowerCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
, sorter: function (items) {
|
||||||
|
var beginswith = []
|
||||||
|
, caseSensitive = []
|
||||||
|
, caseInsensitive = []
|
||||||
|
, item
|
||||||
|
|
||||||
|
while (item = items.shift()) {
|
||||||
|
if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
|
||||||
|
else if (~item.indexOf(this.query)) caseSensitive.push(item)
|
||||||
|
else caseInsensitive.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return beginswith.concat(caseSensitive, caseInsensitive)
|
||||||
|
}
|
||||||
|
|
||||||
|
, highlighter: function (item) {
|
||||||
|
var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
|
||||||
|
return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
|
||||||
|
return '<strong>' + match + '</strong>'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
, render: function (items) {
|
||||||
|
var that = this
|
||||||
|
|
||||||
|
items = $(items).map(function (i, item) {
|
||||||
|
i = $(that.options.item).attr('data-value', item)
|
||||||
|
i.find('a').html(that.highlighter(item))
|
||||||
|
return i[0]
|
||||||
|
})
|
||||||
|
|
||||||
|
items.first().addClass('active')
|
||||||
|
this.$menu.html(items)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
, next: function (event) {
|
||||||
|
var active = this.$menu.find('.active').removeClass('active')
|
||||||
|
, next = active.next()
|
||||||
|
|
||||||
|
if (!next.length) {
|
||||||
|
next = $(this.$menu.find('li')[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
next.addClass('active')
|
||||||
|
}
|
||||||
|
|
||||||
|
, prev: function (event) {
|
||||||
|
var active = this.$menu.find('.active').removeClass('active')
|
||||||
|
, prev = active.prev()
|
||||||
|
|
||||||
|
if (!prev.length) {
|
||||||
|
prev = this.$menu.find('li').last()
|
||||||
|
}
|
||||||
|
|
||||||
|
prev.addClass('active')
|
||||||
|
}
|
||||||
|
|
||||||
|
, listen: function () {
|
||||||
|
this.$element
|
||||||
|
.on('blur', $.proxy(this.blur, this))
|
||||||
|
.on('keypress', $.proxy(this.keypress, this))
|
||||||
|
.on('keyup', $.proxy(this.keyup, this))
|
||||||
|
|
||||||
|
if ($.browser.webkit || $.browser.msie) {
|
||||||
|
this.$element.on('keydown', $.proxy(this.keydown, this))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$menu
|
||||||
|
.on('click', $.proxy(this.click, this))
|
||||||
|
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
|
||||||
|
}
|
||||||
|
|
||||||
|
, move: function (e) {
|
||||||
|
if (!this.shown) return
|
||||||
|
|
||||||
|
switch(e.keyCode) {
|
||||||
|
case 9: // tab
|
||||||
|
case 13: // enter
|
||||||
|
case 27: // escape
|
||||||
|
e.preventDefault()
|
||||||
|
break
|
||||||
|
|
||||||
|
case 38: // up arrow
|
||||||
|
e.preventDefault()
|
||||||
|
this.prev()
|
||||||
|
break
|
||||||
|
|
||||||
|
case 40: // down arrow
|
||||||
|
e.preventDefault()
|
||||||
|
this.next()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
, keydown: function (e) {
|
||||||
|
this.suppressKeyPressRepeat = !~$.inArray(e.keyCode, [40,38,9,13,27])
|
||||||
|
this.move(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
, keypress: function (e) {
|
||||||
|
if (this.suppressKeyPressRepeat) return
|
||||||
|
this.move(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
, keyup: function (e) {
|
||||||
|
switch(e.keyCode) {
|
||||||
|
case 40: // down arrow
|
||||||
|
case 38: // up arrow
|
||||||
|
break
|
||||||
|
|
||||||
|
case 9: // tab
|
||||||
|
case 13: // enter
|
||||||
|
if (!this.shown) return
|
||||||
|
this.select()
|
||||||
|
break
|
||||||
|
|
||||||
|
case 27: // escape
|
||||||
|
if (!this.shown) return
|
||||||
|
this.hide()
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.lookup()
|
||||||
|
}
|
||||||
|
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
, blur: function (e) {
|
||||||
|
var that = this
|
||||||
|
setTimeout(function () { that.hide() }, 150)
|
||||||
|
}
|
||||||
|
|
||||||
|
, click: function (e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
this.select()
|
||||||
|
}
|
||||||
|
|
||||||
|
, mouseenter: function (e) {
|
||||||
|
this.$menu.find('.active').removeClass('active')
|
||||||
|
$(e.currentTarget).addClass('active')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TYPEAHEAD PLUGIN DEFINITION
|
||||||
|
* =========================== */
|
||||||
|
|
||||||
|
$.fn.typeahead = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('typeahead')
|
||||||
|
, options = typeof option == 'object' && option
|
||||||
|
if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
|
||||||
|
if (typeof option == 'string') data[option]()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.typeahead.defaults = {
|
||||||
|
source: []
|
||||||
|
, items: 8
|
||||||
|
, menu: '<ul class="typeahead dropdown-menu"></ul>'
|
||||||
|
, item: '<li><a href="#"></a></li>'
|
||||||
|
, minLength: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.typeahead.Constructor = Typeahead
|
||||||
|
|
||||||
|
|
||||||
|
/* TYPEAHEAD DATA-API
|
||||||
|
* ================== */
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
|
||||||
|
var $this = $(this)
|
||||||
|
if ($this.data('typeahead')) return
|
||||||
|
e.preventDefault()
|
||||||
|
$this.typeahead($this.data())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
}(window.jQuery);
|
4
js/jquery.js
vendored
Normal file
4
js/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
199
topics/credits.html
Normal file
199
topics/credits.html
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#credits">Credits</a></li>
|
||||||
|
<li><a href="#contact">Contact</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="credits">Credits</h1>
|
||||||
|
<p>The following people have helped make REST framework great.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Tom Christie \<tomchristie> </li>
|
||||||
|
<li>Marko Tibold \<markotibold></li>
|
||||||
|
<li>Paul Bagwell \<pbgwl></li>
|
||||||
|
<li>Sébastien Piquemal \<sebpiq></li>
|
||||||
|
<li>Carmen Wick \<cwick></li>
|
||||||
|
<li>Alex Ehlke \<aehlke></li>
|
||||||
|
<li>Alen Mujezinovic \<flashingpumpkin></li>
|
||||||
|
<li>Carles Barrobés \<txels></li>
|
||||||
|
<li>Michael Fötsch \<mfoetsch></li>
|
||||||
|
<li>David Larlet \<david></li>
|
||||||
|
<li>Andrew Straw \<astraw></li>
|
||||||
|
<li>Zeth \<zeth></li>
|
||||||
|
<li>Fernando Zunino \<fzunino></li>
|
||||||
|
<li>Jens Alm \<ulmus></li>
|
||||||
|
<li>Craig Blaszczyk \<jakul></li>
|
||||||
|
<li>Garcia Solero \<garciasolero></li>
|
||||||
|
<li>Tom Drummond \<devioustree></li>
|
||||||
|
<li>Danilo Bargen \<gwrtheyrn></li>
|
||||||
|
<li>Andrew McCloud \<amccloud></li>
|
||||||
|
<li>Thomas Steinacher \<thomasst></li>
|
||||||
|
<li>Meurig Freeman \<meurig></li>
|
||||||
|
<li>Anthony Nemitz \<anemitz></li>
|
||||||
|
<li>Ewoud Kohl van Wijngaarden \<ekohl></li>
|
||||||
|
<li>Michael Ding \<yandy></li>
|
||||||
|
<li>Mjumbe Poe \<mjumbewu></li>
|
||||||
|
<li>Natim \<natim></li>
|
||||||
|
<li>Sebastian Żurek \<sebzur></li>
|
||||||
|
<li>Benoit C \<dzen></li>
|
||||||
|
<li>Chris Pickett \<bunchesofdonald></li>
|
||||||
|
<li>Ben Timby \<btimby></li>
|
||||||
|
<li>Michele Lazzeri \<michelelazzeri-nextage></li>
|
||||||
|
<li>Camille Harang \<mammique></li>
|
||||||
|
<li>Paul Oswald \<poswald></li>
|
||||||
|
<li>Sean C. Farley \<scfarley></li>
|
||||||
|
<li>Daniel Izquierdo \<izquierdo></li>
|
||||||
|
<li>Can Yavuz \<tschan></li>
|
||||||
|
<li>Shawn Lewis \<shawnlewis></li>
|
||||||
|
</ul>
|
||||||
|
<p>Many thanks to everyone who's contributed to the project.</p>
|
||||||
|
<h2 id="contact">Contact</h2>
|
||||||
|
<p>To contact the author directly:</p>
|
||||||
|
<ul>
|
||||||
|
<li>twitter: <a href="http://twitter.com/_tomchristie">@_tomchristie</a></li>
|
||||||
|
<li>mail: <a href="mailto:tom@tomchristie.com">tom@tomchristie.com</a></li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
160
topics/csrf.html
Normal file
160
topics/csrf.html
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#working-with-ajax-and-csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="working-with-ajax-and-csrf">Working with AJAX and CSRF</h1>
|
||||||
|
<blockquote>
|
||||||
|
<p>"Take a close look at possible CSRF / XSRF vulnerabilities on your own websites. They're the worst kind of vulnerability -- very easy to exploit by attackers, yet not so intuitively easy to understand for software developers, at least until you've been bitten by one."</p>
|
||||||
|
<p>— <a href="http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html">Jeff Atwood</a></p>
|
||||||
|
</blockquote>
|
||||||
|
<ul>
|
||||||
|
<li>Explain need to add CSRF token to AJAX requests.</li>
|
||||||
|
<li>Explain defered CSRF style used by REST framework</li>
|
||||||
|
<li>Why you should use Django's standard login/logout views, and not REST framework view</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
179
topics/formoverloading.html
Normal file
179
topics/formoverloading.html
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#browser-based-put-&-delete">Browser based PUT & DELETE</a></li>
|
||||||
|
<li><a href="#overloading-the-http-method">Overloading the HTTP method</a></li>
|
||||||
|
<li><a href="#overloading-the-http-content-type">Overloading the HTTP content type</a></li>
|
||||||
|
<li><a href="#doesnt-html5-support-put-and-delete-forms">Doesn't HTML5 support PUT and DELETE forms?</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="browser-based-put-delete">Browser based PUT & DELETE</h1>
|
||||||
|
<blockquote>
|
||||||
|
<p>"There are two noncontroversial uses for overloaded POST. The first is to <em>simulate</em> HTTP's uniform interface for clients like web browsers that don't support PUT or DELETE"</p>
|
||||||
|
<p>— <a href="1">RESTful Web Services</a>, Leonard Richardson & Sam Ruby.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h2 id="overloading-the-http-method">Overloading the HTTP method</h2>
|
||||||
|
<p><strong>TODO: Preamble.</strong> Note that this is the same strategy as is used in <a href="2">Ruby on Rails</a>.</p>
|
||||||
|
<p>For example, given the following form:</p>
|
||||||
|
<pre><code><form action="/news-items/5" method="POST">
|
||||||
|
<input type="hidden" name="_method" value="DELETE">
|
||||||
|
</form>
|
||||||
|
</code></pre>
|
||||||
|
<p><code>request.method</code> would return <code>"DELETE"</code>.</p>
|
||||||
|
<h2 id="overloading-the-http-content-type">Overloading the HTTP content type</h2>
|
||||||
|
<p>Browser-based submission of content types other than form are supported by using form fields named <code>_content</code> and <code>_content_type</code>:</p>
|
||||||
|
<p>For example, given the following form:</p>
|
||||||
|
<pre><code><form action="/news-items/5" method="PUT">
|
||||||
|
<input type="hidden" name="_content_type" value="application/json">
|
||||||
|
<input name="_content" value="{'count': 1}">
|
||||||
|
</form>
|
||||||
|
</code></pre>
|
||||||
|
<p><code>request.content_type</code> would return <code>"application/json"</code>, and <code>request.content</code> would return <code>"{'count': 1}"</code></p>
|
||||||
|
<h2 id="why-not-just-use-javascript">Why not just use Javascript?</h2>
|
||||||
|
<p><strong>[TODO]</strong></p>
|
||||||
|
<h2 id="doesnt-html5-support-put-and-delete-forms">Doesn't HTML5 support PUT and DELETE forms?</h2>
|
||||||
|
<p>Nope. It was at one point intended to support <code>PUT</code> and <code>DELETE</code> forms, but was later <a href="3">dropped from the spec</a>. There remains <a href="4">ongoing discussion</a> about adding support for <code>PUT</code> and <code>DELETE</code>, as well as how to support content-types other than form-encoded data.</p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
352
tutorial/1-serialization.html
Normal file
352
tutorial/1-serialization.html
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#tutorial-1-serialization">Tutorial 1: Serialization</a></li>
|
||||||
|
<li><a href="#introduction">Introduction</a></li>
|
||||||
|
<li><a href="#getting-started">Getting started</a></li>
|
||||||
|
<li><a href="#creating-a-model-to-work-with">Creating a model to work with</a></li>
|
||||||
|
<li><a href="#creating-a-serializer-class">Creating a Serializer class</a></li>
|
||||||
|
<li><a href="#working-with-serializers">Working with Serializers</a></li>
|
||||||
|
<li><a href="#writing-regular-django-views-using-our-serializers">Writing regular Django views using our Serializers</a></li>
|
||||||
|
<li><a href="#testing-our-first-attempt-at-a-web-api">Testing our first attempt at a Web API</a></li>
|
||||||
|
<li><a href="#where-are-we-now">Where are we now</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="tutorial-1-serialization">Tutorial 1: Serialization</h1>
|
||||||
|
<h2 id="introduction">Introduction</h2>
|
||||||
|
<p>This tutorial will walk you through the building blocks that make up REST framework. It'll take a little while to get through, but it'll give you a comprehensive understanding of how everything fits together.</p>
|
||||||
|
<h2 id="getting-started">Getting started</h2>
|
||||||
|
<p>To get started, let's create a new project to work with.</p>
|
||||||
|
<pre><code>django-admin.py startproject tutorial
|
||||||
|
cd tutorial
|
||||||
|
</code></pre>
|
||||||
|
<p>Once that's done we can create an app that we'll use to create a simple Web API.</p>
|
||||||
|
<pre><code>python manage.py startapp blog
|
||||||
|
</code></pre>
|
||||||
|
<p>The simplest way to get up and running will probably be to use an <code>sqlite3</code> database for the tutorial. Edit the <code>tutorial/settings.py</code> file, and set the default database <code>"ENGINE"</code> to <code>"sqlite3"</code>, and <code>"NAME"</code> to <code>"tmp.db"</code>.</p>
|
||||||
|
<pre><code>DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': 'tmp.db',
|
||||||
|
'USER': '',
|
||||||
|
'PASSWORD': '',
|
||||||
|
'HOST': '',
|
||||||
|
'PORT': '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>We'll also need to add our new <code>blog</code> app and the <code>djangorestframework</code> app to <code>INSTALLED_APPS</code>.</p>
|
||||||
|
<pre><code>INSTALLED_APPS = (
|
||||||
|
...
|
||||||
|
'djangorestframework',
|
||||||
|
'blog'
|
||||||
|
)
|
||||||
|
</code></pre>
|
||||||
|
<p>We also need to wire up the root urlconf, in the <code>tutorial/urls.py</code> file, to include our blog views.</p>
|
||||||
|
<pre><code>urlpatterns = patterns('',
|
||||||
|
url(r'^', include('blog.urls')),
|
||||||
|
)
|
||||||
|
</code></pre>
|
||||||
|
<p>Okay, we're ready to roll.</p>
|
||||||
|
<h2 id="creating-a-model-to-work-with">Creating a model to work with</h2>
|
||||||
|
<p>For the purposes of this tutorial we're going to start by creating a simple <code>Comment</code> model that is used to store comments against a blog post. Go ahead and edit the <code>blog</code> app's <code>models.py</code> file.</p>
|
||||||
|
<pre><code>from django.db import models
|
||||||
|
|
||||||
|
class Comment(models.Model):
|
||||||
|
email = models.EmailField()
|
||||||
|
content = models.CharField(max_length=200)
|
||||||
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
</code></pre>
|
||||||
|
<p>Don't forget to sync the database for the first time.</p>
|
||||||
|
<pre><code>python manage.py syncdb
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="creating-a-serializer-class">Creating a Serializer class</h2>
|
||||||
|
<p>We're going to create a simple Web API that we can use to edit these comment objects with. The first thing we need is a way of serializing and deserializing the objects into representations such as <code>json</code>. We do this by declaring serializers, that work very similarly to Django's forms. Create a file in the project named <code>serializers.py</code> and add the following.</p>
|
||||||
|
<pre><code>from blog import models
|
||||||
|
from djangorestframework import serializers
|
||||||
|
|
||||||
|
class CommentSerializer(serializers.Serializer):
|
||||||
|
email = serializers.EmailField()
|
||||||
|
content = serializers.CharField(max_length=200)
|
||||||
|
created = serializers.DateTimeField()
|
||||||
|
|
||||||
|
def restore_object(self, attrs, instance=None):
|
||||||
|
"""
|
||||||
|
Create or update a new comment instance.
|
||||||
|
"""
|
||||||
|
if instance:
|
||||||
|
instance.email = attrs['email']
|
||||||
|
instance.content = attrs['content']
|
||||||
|
instance.created = attrs['created']
|
||||||
|
return instance
|
||||||
|
return models.Comment(**attrs)
|
||||||
|
</code></pre>
|
||||||
|
<p>The first part of serializer class defines the fields that get serialized/deserialized. The <code>restore_object</code> method defines how fully fledged instances get created when deserializing data.</p>
|
||||||
|
<p>We can actually also save ourselves some time by using the <code>ModelSerializer</code> class, as we'll see later, but for now we'll keep our serializer definition explicit.<br />
|
||||||
|
</p>
|
||||||
|
<h2 id="working-with-serializers">Working with Serializers</h2>
|
||||||
|
<p>Before we go any further we'll familiarise ourselves with using our new Serializer class. Let's drop into the Django shell.</p>
|
||||||
|
<pre><code>python manage.py shell
|
||||||
|
</code></pre>
|
||||||
|
<p>Okay, once we've got a few imports out of the way, we'd better create a few comments to work with.</p>
|
||||||
|
<pre><code>from blog.models import Comment
|
||||||
|
from blog.serializers import CommentSerializer
|
||||||
|
from djangorestframework.renderers import JSONRenderer
|
||||||
|
from djangorestframework.parsers import JSONParser
|
||||||
|
|
||||||
|
c1 = Comment(email='leila@example.com', content='nothing to say')
|
||||||
|
c2 = Comment(email='tom@example.com', content='foo bar')
|
||||||
|
c3 = Comment(email='anna@example.com', content='LOLZ!')
|
||||||
|
c1.save()
|
||||||
|
c2.save()
|
||||||
|
c3.save()
|
||||||
|
</code></pre>
|
||||||
|
<p>We've now got a few comment instances to play with. Let's take a look at serializing one of those instances.</p>
|
||||||
|
<pre><code>serializer = CommentSerializer(instance=c1)
|
||||||
|
serializer.data
|
||||||
|
# {'email': u'leila@example.com', 'content': u'nothing to say', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774)}
|
||||||
|
</code></pre>
|
||||||
|
<p>At this point we've translated the model instance into python native datatypes. To finalise the serialization process we render the data into <code>json</code>.</p>
|
||||||
|
<pre><code>stream = JSONRenderer().render(serializer.data)
|
||||||
|
stream
|
||||||
|
# '{"email": "leila@example.com", "content": "nothing to say", "created": "2012-08-22T16:20:09.822"}'
|
||||||
|
</code></pre>
|
||||||
|
<p>Deserialization is similar. First we parse a stream into python native datatypes... </p>
|
||||||
|
<pre><code>data = JSONParser().parse(stream)
|
||||||
|
</code></pre>
|
||||||
|
<p>...then we restore those native datatypes into to a fully populated object instance.</p>
|
||||||
|
<pre><code>serializer = CommentSerializer(data)
|
||||||
|
serializer.is_valid()
|
||||||
|
# True
|
||||||
|
serializer.object
|
||||||
|
# <Comment object at 0x10633b2d0>
|
||||||
|
</code></pre>
|
||||||
|
<p>Notice how similar the API is to working with forms. The similarity should become even more apparent when we start writing views that use our serializer.</p>
|
||||||
|
<h2 id="writing-regular-django-views-using-our-serializers">Writing regular Django views using our Serializers</h2>
|
||||||
|
<p>Let's see how we can write some API views using our new Serializer class.
|
||||||
|
We'll start off by creating a subclass of HttpResponse that we can use to render any data we return into <code>json</code>.</p>
|
||||||
|
<p>Edit the <code>blog/views.py</code> file, and add the following.</p>
|
||||||
|
<pre><code>from blog.models import Comment
|
||||||
|
from blog.serializers import CommentSerializer
|
||||||
|
from djangorestframework.renderers import JSONRenderer
|
||||||
|
from djangorestframework.parsers import JSONParser
|
||||||
|
from django.http import HttpResponse
|
||||||
|
|
||||||
|
class JSONResponse(HttpResponse):
|
||||||
|
"""
|
||||||
|
An HttpResponse that renders it's content into JSON.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, data, **kwargs):
|
||||||
|
content = JSONRenderer().render(data)
|
||||||
|
kwargs['content_type'] = 'application/json'
|
||||||
|
super(JSONResponse, self).__init__(content, **kwargs)
|
||||||
|
</code></pre>
|
||||||
|
<p>The root of our API is going to be a view that supports listing all the existing comments, or creating a new comment.</p>
|
||||||
|
<pre><code>def comment_root(request):
|
||||||
|
"""
|
||||||
|
List all comments, or create a new comment.
|
||||||
|
"""
|
||||||
|
if request.method == 'GET':
|
||||||
|
comments = Comment.objects.all()
|
||||||
|
serializer = CommentSerializer(instance=comments)
|
||||||
|
return JSONResponse(serializer.data)
|
||||||
|
|
||||||
|
elif request.method == 'POST':
|
||||||
|
data = JSONParser().parse(request)
|
||||||
|
serializer = CommentSerializer(data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
comment = serializer.object
|
||||||
|
comment.save()
|
||||||
|
return JSONResponse(serializer.data, status=201)
|
||||||
|
else:
|
||||||
|
return JSONResponse(serializer.error_data, status=400)
|
||||||
|
</code></pre>
|
||||||
|
<p>We'll also need a view which corrosponds to an individual comment, and can be used to retrieve, update or delete the comment.</p>
|
||||||
|
<pre><code>def comment_instance(request, pk):
|
||||||
|
"""
|
||||||
|
Retrieve, update or delete a comment instance.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
comment = Comment.objects.get(pk=pk)
|
||||||
|
except Comment.DoesNotExist:
|
||||||
|
return HttpResponse(status=404)
|
||||||
|
|
||||||
|
if request.method == 'GET':
|
||||||
|
serializer = CommentSerializer(instance=comment)
|
||||||
|
return JSONResponse(serializer.data)
|
||||||
|
|
||||||
|
elif request.method == 'PUT':
|
||||||
|
data = JSONParser().parse(request)
|
||||||
|
serializer = CommentSerializer(data, instance=comment)
|
||||||
|
if serializer.is_valid():
|
||||||
|
comment = serializer.object
|
||||||
|
comment.save()
|
||||||
|
return JSONResponse(serializer.data)
|
||||||
|
else:
|
||||||
|
return JSONResponse(serializer.error_data, status=400)
|
||||||
|
|
||||||
|
elif request.method == 'DELETE':
|
||||||
|
comment.delete()
|
||||||
|
return HttpResponse(status=204)
|
||||||
|
</code></pre>
|
||||||
|
<p>Finally we need to wire these views up, in the <code>tutorial/urls.py</code> file.</p>
|
||||||
|
<pre><code>from django.conf.urls import patterns, url
|
||||||
|
|
||||||
|
urlpatterns = patterns('blog.views',
|
||||||
|
url(r'^$', 'comment_root'),
|
||||||
|
url(r'^(?P<pk>[0-9]+)$', 'comment_instance')
|
||||||
|
)
|
||||||
|
</code></pre>
|
||||||
|
<p>It's worth noting that there's a couple of edge cases we're not dealing with properly at the moment. If we send malformed <code>json</code>, or if a request is made with a method that the view doesn't handle, then we'll end up with a 500 "server error" response. Still, this'll do for now.</p>
|
||||||
|
<h2 id="testing-our-first-attempt-at-a-web-api">Testing our first attempt at a Web API</h2>
|
||||||
|
<p><strong>TODO: Describe using runserver and making example requests from console</strong></p>
|
||||||
|
<p><strong>TODO: Describe opening in a web browser and viewing json output</strong></p>
|
||||||
|
<h2 id="where-are-we-now">Where are we now</h2>
|
||||||
|
<p>We're doing okay so far, we've got a serialization API that feels pretty similar to Django's Forms API, and some regular Django views.</p>
|
||||||
|
<p>Our API views don't do anything particularly special at the moment, beyond serve <code>json</code> responses, and there's some error handling edge cases we'd still like to clean up, but it's a functioning Web API.</p>
|
||||||
|
<p>We'll see how we can start to improve things in <a href="2-requests-and-responses.html">part 2 of the tutorial</a>.</p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
260
tutorial/2-requests-and-responses.html
Normal file
260
tutorial/2-requests-and-responses.html
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#tutorial-2-request-and-response-objects">Tutorial 2: Request and Response objects</a></li>
|
||||||
|
<li><a href="#request-objects">Request objects</a></li>
|
||||||
|
<li><a href="#response-objects">Response objects</a></li>
|
||||||
|
<li><a href="#status-codes">Status codes</a></li>
|
||||||
|
<li><a href="#wrapping-api-views">Wrapping API views</a></li>
|
||||||
|
<li><a href="#pulling-it-all-together">Pulling it all together</a></li>
|
||||||
|
<li><a href="#adding-optional-format-suffixes-to-our-urls">Adding optional format suffixes to our URLs</a></li>
|
||||||
|
<li><a href="#hows-it-looking">How's it looking?</a></li>
|
||||||
|
<li><a href="#whats-next">What's next?</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="tutorial-2-request-and-response-objects">Tutorial 2: Request and Response objects</h1>
|
||||||
|
<p>From this point we're going to really start covering the core of REST framework.
|
||||||
|
Let's introduce a couple of essential building blocks.</p>
|
||||||
|
<h2 id="request-objects">Request objects</h2>
|
||||||
|
<p>REST framework intoduces a <code>Request</code> object that extends the regular <code>HttpRequest</code>, and provides more flexible request parsing. The core functionality of the <code>Request</code> object is the <code>request.DATA</code> attribute, which is similar to <code>request.POST</code>, but more useful for working with Web APIs.</p>
|
||||||
|
<pre><code>request.POST # Only handles form data. Only works for 'POST' method.
|
||||||
|
request.DATA # Handles arbitrary data. Works any HTTP request with content.
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="response-objects">Response objects</h2>
|
||||||
|
<p>REST framework also introduces a <code>Response</code> object, which is a type of <code>TemplateResponse</code> that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.</p>
|
||||||
|
<pre><code>return Response(data) # Renders to content type as requested by the client.
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="status-codes">Status codes</h2>
|
||||||
|
<p>Using numeric HTTP status codes in your views doesn't always make for obvious reading, and it's easy to not notice if you get an error code wrong. REST framework provides more explicit identifiers for each status code, such as <code>HTTP_400_BAD_REQUEST</code> in the <code>status</code> module. It's a good idea to use these throughout rather than using numeric identifiers.</p>
|
||||||
|
<h2 id="wrapping-api-views">Wrapping API views</h2>
|
||||||
|
<p>REST framework provides two wrappers you can use to write API views.</p>
|
||||||
|
<ol>
|
||||||
|
<li>The <code>@api_view</code> decorator for working with function based views.</li>
|
||||||
|
<li>The <code>APIView</code> class for working with class based views.</li>
|
||||||
|
</ol>
|
||||||
|
<p>These wrappers provide a few bits of functionality such as making sure you recieve <code>Request</code> instances in your view, and adding context to <code>Response</code> objects so that content negotiation can be performed.</p>
|
||||||
|
<p>The wrappers also provide behaviour such as returning <code>405 Method Not Allowed</code> responses when appropriate, and handling any <code>ParseError</code> exception that occurs when accessing <code>request.DATA</code> with malformed input.</p>
|
||||||
|
<h2 id="pulling-it-all-together">Pulling it all together</h2>
|
||||||
|
<p>Okay, let's go ahead and start using these new components to write a few views. </p>
|
||||||
|
<pre><code>from djangorestframework.decorators import api_view
|
||||||
|
from djangorestframework.status import *
|
||||||
|
|
||||||
|
@api_view(allow=['GET', 'POST'])
|
||||||
|
def comment_root(request):
|
||||||
|
"""
|
||||||
|
List all comments, or create a new comment.
|
||||||
|
"""
|
||||||
|
if request.method == 'GET':
|
||||||
|
comments = Comment.objects.all()
|
||||||
|
serializer = CommentSerializer(instance=comments)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
elif request.method == 'POST':
|
||||||
|
serializer = CommentSerializer(request.DATA)
|
||||||
|
if serializer.is_valid():
|
||||||
|
comment = serializer.object
|
||||||
|
comment.save()
|
||||||
|
return Response(serializer.data, status=HTTP_201_CREATED)
|
||||||
|
else:
|
||||||
|
return Response(serializer.error_data, status=HTTP_400_BAD_REQUEST)
|
||||||
|
</code></pre>
|
||||||
|
<p>Our instance view is an improvement over the previous example. It's slightly more concise, and the code now feels very similar to if we were working with the Forms API.</p>
|
||||||
|
<pre><code>@api_view(allow=['GET', 'PUT', 'DELETE'])
|
||||||
|
def comment_instance(request, pk):
|
||||||
|
"""
|
||||||
|
Retrieve, update or delete a comment instance.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
comment = Comment.objects.get(pk=pk)
|
||||||
|
except Comment.DoesNotExist:
|
||||||
|
return Response(status=HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
|
if request.method == 'GET':
|
||||||
|
serializer = CommentSerializer(instance=comment)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
elif request.method == 'PUT':
|
||||||
|
serializer = CommentSerializer(request.DATA, instance=comment)
|
||||||
|
if serializer.is_valid():
|
||||||
|
comment = serializer.object
|
||||||
|
comment.save()
|
||||||
|
return Response(serializer.data)
|
||||||
|
else:
|
||||||
|
return Response(serializer.error_data, status=HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
elif request.method == 'DELETE':
|
||||||
|
comment.delete()
|
||||||
|
return Response(status=HTTP_204_NO_CONTENT)
|
||||||
|
</code></pre>
|
||||||
|
<p>This should all feel very familiar - it looks a lot like working with forms in regular Django views.</p>
|
||||||
|
<p>Notice that we're no longer explicitly tying our requests or responses to a given content type. <code>request.DATA</code> can handle incoming <code>json</code> requests, but it can also handle <code>yaml</code> and other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us.</p>
|
||||||
|
<h2 id="adding-optional-format-suffixes-to-our-urls">Adding optional format suffixes to our URLs</h2>
|
||||||
|
<p>To take advantage of that, let's add support for format suffixes to our API endpoints, so that we can use URLs that explicitly refer to a given format. That means our API will be able to handle URLs such as <a href="http://example.com/api/items/4.json">http://example.com/api/items/4.json</a>.</p>
|
||||||
|
<p>Start by adding a <code>format</code> keyword argument to both of the views, like so.</p>
|
||||||
|
<pre><code>def comment_root(request, format=None):
|
||||||
|
</code></pre>
|
||||||
|
<p>and</p>
|
||||||
|
<pre><code>def comment_instance(request, pk, format=None):
|
||||||
|
</code></pre>
|
||||||
|
<p>Now update the <code>urls.py</code> file slightly, to append a set of <code>format_suffix_patterns</code> in addition to the existing URLs.</p>
|
||||||
|
<pre><code>from djangorestframework.urlpatterns import format_suffix_patterns
|
||||||
|
|
||||||
|
urlpatterns = patterns('blogpost.views',
|
||||||
|
url(r'^$', 'comment_root'),
|
||||||
|
url(r'^(?P<pk>[0-9]+)$', 'comment_instance')
|
||||||
|
)
|
||||||
|
|
||||||
|
urlpatterns = format_suffix_patterns(urlpatterns)
|
||||||
|
</code></pre>
|
||||||
|
<p>We don't necessarily need to add these extra url patterns in, but it gives us a simple, clean way of refering to a specific format.</p>
|
||||||
|
<h2 id="hows-it-looking">How's it looking?</h2>
|
||||||
|
<p>Go ahead and test the API from the command line, as we did in <a href="1-serialization.html">tutorial part 1</a>. Everything is working pretty similarly, although we've got some nicer error handling if we send invalid requests.</p>
|
||||||
|
<p><strong>TODO: Describe using accept headers, content-type headers, and format suffixed URLs</strong></p>
|
||||||
|
<p>Now go and open the API in a web browser, by visiting <a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>.</p>
|
||||||
|
<p><strong>TODO: Describe browseable API awesomeness</strong></p>
|
||||||
|
<h2 id="whats-next">What's next?</h2>
|
||||||
|
<p>In <a href="3-class-based-views.html">tutorial part 3</a>, we'll start using class based views, and see how generic views reduce the amount of code we need to write.</p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
272
tutorial/3-class-based-views.html
Normal file
272
tutorial/3-class-based-views.html
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li class="main"><a href="#tutorial-3-using-class-based-views">Tutorial 3: Using Class Based Views</a></li>
|
||||||
|
<li><a href="#rewriting-our-api-using-class-based-views">Rewriting our API using class based views</a></li>
|
||||||
|
<li><a href="#using-mixins">Using mixins</a></li>
|
||||||
|
<li><a href="#reusing-generic-class-based-views">Reusing generic class based views</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<h1 id="tutorial-3-using-class-based-views">Tutorial 3: Using Class Based Views</h1>
|
||||||
|
<p>We can also write our API views using class based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>.</p>
|
||||||
|
<h2 id="rewriting-our-api-using-class-based-views">Rewriting our API using class based views</h2>
|
||||||
|
<p>We'll start by rewriting the root view as a class based view. All this involves is a little bit of refactoring.</p>
|
||||||
|
<pre><code>from blog.models import Comment
|
||||||
|
from blog.serializers import ComentSerializer
|
||||||
|
from django.http import Http404
|
||||||
|
from djangorestframework.views import APIView
|
||||||
|
from djangorestframework.response import Response
|
||||||
|
from djangorestframework.status import *
|
||||||
|
|
||||||
|
class CommentRoot(views.APIView):
|
||||||
|
"""
|
||||||
|
List all comments, or create a new comment.
|
||||||
|
"""
|
||||||
|
def get(self, request, format=None):
|
||||||
|
comments = Comment.objects.all()
|
||||||
|
serializer = ComentSerializer(instance=comments)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
def post(self, request, format=None)
|
||||||
|
serializer = ComentSerializer(request.DATA)
|
||||||
|
if serializer.is_valid():
|
||||||
|
comment = serializer.object
|
||||||
|
comment.save()
|
||||||
|
return Response(serializer.serialized, status=HTTP_201_CREATED)
|
||||||
|
else:
|
||||||
|
return Response(serializer.serialized_errors, status=HTTP_400_BAD_REQUEST)
|
||||||
|
</code></pre>
|
||||||
|
<p>So far, so good. It looks pretty similar to the previous case, but we've got better seperation between the different HTTP methods. We'll also need to update the instance view. </p>
|
||||||
|
<pre><code>class CommentInstance(views.APIView):
|
||||||
|
"""
|
||||||
|
Retrieve, update or delete a comment instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_object(self, pk):
|
||||||
|
try:
|
||||||
|
return Poll.objects.get(pk=pk)
|
||||||
|
except Poll.DoesNotExist:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
def get(self, request, pk, format=None):
|
||||||
|
comment = self.get_object(pk)
|
||||||
|
serializer = CommentSerializer(instance=comment)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
def put(self, request, pk, format=None):
|
||||||
|
comment = self.get_object(pk)
|
||||||
|
serializer = CommentSerializer(request.DATA, instance=comment)
|
||||||
|
if serializer.is_valid():
|
||||||
|
comment = serializer.deserialized
|
||||||
|
comment.save()
|
||||||
|
return Response(serializer.data)
|
||||||
|
else:
|
||||||
|
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
def delete(self, request, pk, format=None):
|
||||||
|
comment = self.get_object(pk)
|
||||||
|
comment.delete()
|
||||||
|
return Response(status=HTTP_204_NO_CONTENT)
|
||||||
|
</code></pre>
|
||||||
|
<p>That's looking good. Again, it's still pretty similar to the function based view right now.</p>
|
||||||
|
<p>Since we're now working with class based views, rather than function based views, we'll also need to update our urlconf slightly.</p>
|
||||||
|
<pre><code>from blogpost import views
|
||||||
|
from djangorestframework.urlpatterns import format_suffix_patterns
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
url(r'^$', views.CommentRoot.as_view()),
|
||||||
|
url(r'^(?P<id>[0-9]+)$', views.CommentInstance.as_view())
|
||||||
|
)
|
||||||
|
|
||||||
|
urlpatterns = format_suffix_patterns(urlpatterns)
|
||||||
|
</code></pre>
|
||||||
|
<p>Okay, we're done. If you run the development server everything should be working just as before.</p>
|
||||||
|
<h2 id="using-mixins">Using mixins</h2>
|
||||||
|
<p>One of the big wins of using class based views is that it allows us to easily compose reusable bits of behaviour.</p>
|
||||||
|
<p>The create/retrieve/update/delete operations that we've been using so far is going to be pretty simliar for any model-backed API views we create. Those bits of common behaviour are implemented in REST framework's mixin classes.</p>
|
||||||
|
<p>We can compose those mixin classes, to recreate our existing API behaviour with less code.</p>
|
||||||
|
<pre><code>from blog.models import Comment
|
||||||
|
from blog.serializers import CommentSerializer
|
||||||
|
from djangorestframework import mixins, views
|
||||||
|
|
||||||
|
class CommentRoot(mixins.ListModelQuerysetMixin,
|
||||||
|
mixins.CreateModelInstanceMixin,
|
||||||
|
views.BaseRootAPIView):
|
||||||
|
model = Comment
|
||||||
|
serializer_class = CommentSerializer
|
||||||
|
|
||||||
|
get = list
|
||||||
|
post = create
|
||||||
|
|
||||||
|
class CommentInstance(mixins.RetrieveModelInstanceMixin,
|
||||||
|
mixins.UpdateModelInstanceMixin,
|
||||||
|
mixins.DestroyModelInstanceMixin,
|
||||||
|
views.BaseInstanceAPIView):
|
||||||
|
model = Comment
|
||||||
|
serializer_class = CommentSerializer
|
||||||
|
|
||||||
|
get = retrieve
|
||||||
|
put = update
|
||||||
|
delete = destroy
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="reusing-generic-class-based-views">Reusing generic class based views</h2>
|
||||||
|
<p>That's a lot less code than before, but we can go one step further still. REST framework also provides a set of already mixed-in views.</p>
|
||||||
|
<pre><code>from blog.models import Comment
|
||||||
|
from blog.serializers import CommentSerializer
|
||||||
|
from djangorestframework import views
|
||||||
|
|
||||||
|
class CommentRoot(views.RootAPIView):
|
||||||
|
model = Comment
|
||||||
|
serializer_class = CommentSerializer
|
||||||
|
|
||||||
|
class CommentInstance(views.InstanceAPIView):
|
||||||
|
model = Comment
|
||||||
|
serializer_class = CommentSerializer
|
||||||
|
</code></pre>
|
||||||
|
<p>Wow, that's pretty concise. We've got a huge amount for free, and our code looks like
|
||||||
|
good, clean, idomatic Django.</p>
|
||||||
|
<p>Next we'll move onto <a href="4-authentication-permissions-and-throttling.html">part 4 of the tutorial</a>, where we'll take a look at how we can customize the behavior of our views to support a range of authentication, permissions, throttling and other aspects.</p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
150
tutorial/4-authentication-permissions-and-throttling.html
Normal file
150
tutorial/4-authentication-permissions-and-throttling.html
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<p><a href="5-relationships-and-hyperlinked-apis.html">part 5</a></p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
156
tutorial/5-relationships-and-hyperlinked-apis.html
Normal file
156
tutorial/5-relationships-and-hyperlinked-apis.html
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<p><strong>TODO</strong></p>
|
||||||
|
<ul>
|
||||||
|
<li>Create BlogPost model</li>
|
||||||
|
<li>Demonstrate nested relationships</li>
|
||||||
|
<li>Demonstrate and describe hyperlinked relationships</li>
|
||||||
|
</ul>
|
||||||
|
<p><a href="6-resource-orientated-projects.html">part 6</a></p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
193
tutorial/6-resource-orientated-projects.html
Normal file
193
tutorial/6-resource-orientated-projects.html
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Django REST framework</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<!-- Le styles -->
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
.sidebar-nav {
|
||||||
|
padding: 9px 0;
|
||||||
|
}
|
||||||
|
.nav-list li.main {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.25em 0;
|
||||||
|
padding: 0.25em 40px;
|
||||||
|
line-height: 1.45;
|
||||||
|
position: relative;
|
||||||
|
color: #383838;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before {
|
||||||
|
display: block;
|
||||||
|
content: "\201C";
|
||||||
|
font-size: 80px;
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: -20px;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p:last-child {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link href="http://tomchristie.github.com/restframeworkdocs/css/bootstrap-responsive.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]-->
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
|
<div class="navbar-inner">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</a>
|
||||||
|
<a class="brand" href="http://tomchristie.github.com/restframeworkdocs">Django REST framework</a>
|
||||||
|
<div class="nav-collapse collapse">
|
||||||
|
<ul class="nav">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs">Home</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/1-serialization">1 - Serialization</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/3-class-based-views">3 - Class based views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/4-authentication-permissions-and-throttling">4 - Authentication, permissions and throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/tutorial/6-resource-orientated-projects">6 - Resource orientated projects</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/requests">Requests</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/responses">Responses</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/views">Views</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/parsers">Parsers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/renderers">Renderers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/serializers">Serializers</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/fields">Serializer fields</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/authentication">Authentication</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/permissions">Permissions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/throttling">Throttling</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/exceptions">Exceptions</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/status-codes">Status codes</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/api-guide/urls">Returning URLs</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/csrf">Working with AJAX and CSRF</a></li>
|
||||||
|
<li><a href="http://tomchristie.github.com/restframeworkdocs/topics/formoverloading">Browser based PUT, PATCH and DELETE</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Trunk</a></li>
|
||||||
|
<li><a href="#">2.0.0</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well affix span3">
|
||||||
|
<ul class="nav nav-list side-nav">
|
||||||
|
<li><a href="#trade-offs-between-views-vs-resources">Trade-offs between views vs resources.</a></li>
|
||||||
|
<li><a href="#onwards-and-upwards">Onwards and upwards.</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
<p>serializers.py</p>
|
||||||
|
<pre><code>class BlogPostSerializer(URLModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = BlogPost
|
||||||
|
|
||||||
|
class CommentSerializer(URLModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Comment
|
||||||
|
</code></pre>
|
||||||
|
<p>resources.py</p>
|
||||||
|
<pre><code>class BlogPostResource(ModelResource):
|
||||||
|
serializer_class = BlogPostSerializer
|
||||||
|
model = BlogPost
|
||||||
|
permissions = [AdminOrAnonReadonly()]
|
||||||
|
throttles = [AnonThrottle(rate='5/min')]
|
||||||
|
|
||||||
|
class CommentResource(ModelResource):
|
||||||
|
serializer_class = CommentSerializer
|
||||||
|
model = Comment
|
||||||
|
permissions = [AdminOrAnonReadonly()]
|
||||||
|
throttles = [AnonThrottle(rate='5/min')]
|
||||||
|
</code></pre>
|
||||||
|
<p>Now that we're using Resources rather than Views, we don't need to design the urlconf ourselves. The conventions for wiring up resources into views and urls are handled automatically. All we need to do is register the appropriate resources with a router, and let it do the rest. Here's our re-wired <code>urls.py</code> file.</p>
|
||||||
|
<pre><code>from blog import resources
|
||||||
|
from djangorestframework.routers import DefaultRouter
|
||||||
|
|
||||||
|
router = DefaultRouter()
|
||||||
|
router.register(resources.BlogPostResource)
|
||||||
|
router.register(resources.CommentResource)
|
||||||
|
urlpatterns = router.urlpatterns
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="trade-offs-between-views-vs-resources">Trade-offs between views vs resources.</h2>
|
||||||
|
<p>Writing resource-orientated code can be a good thing. It helps ensure that URL conventions will be consistent across your APIs, and minimises the amount of code you need to write.</p>
|
||||||
|
<p>The trade-off is that the behaviour is less explict. It can be more difficult to determine what code path is being followed, or where to override some behaviour.</p>
|
||||||
|
<h2 id="onwards-and-upwards">Onwards and upwards.</h2>
|
||||||
|
<p>We've reached the end of our tutorial. If you want to get more involved in the REST framework project, here's a few places you can start:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Contribute on GitHub by reviewing issues, and submitting issues or pull requests.</li>
|
||||||
|
<li>Join the REST framework group, and help build the community.</li>
|
||||||
|
<li>Follow me on Twitter and say hi.</li>
|
||||||
|
</ul>
|
||||||
|
<p>Now go build something great.</p>
|
||||||
|
</div><!--/span-->
|
||||||
|
</div><!--/row-->
|
||||||
|
</div><!--/.fluid-container-->
|
||||||
|
|
||||||
|
<!-- Le javascript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/jquery.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-dropdown.js"></script>
|
||||||
|
<script src="http://tomchristie.github.com/restframeworkdocs/js/bootstrap-scrollspy.js"></script>
|
||||||
|
<script>
|
||||||
|
//$('.side-nav').scrollspy()
|
||||||
|
var shiftWindow = function() { scrollBy(0, -50) };
|
||||||
|
if (location.hash) shiftWindow();
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
</script>
|
||||||
|
</body></html>
|
Loading…
Reference in New Issue
Block a user