mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-24 08:14:16 +03:00
Merge master
This commit is contained in:
commit
f13c0ebe69
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,7 +3,7 @@
|
|||
*~
|
||||
.*
|
||||
|
||||
html/
|
||||
site/
|
||||
htmlcov/
|
||||
coverage/
|
||||
build/
|
||||
|
|
|
@ -4,6 +4,7 @@ sudo: false
|
|||
|
||||
env:
|
||||
- TOX_ENV=py27-flake8
|
||||
- TOX_ENV=py27-docs
|
||||
- TOX_ENV=py34-django17
|
||||
- TOX_ENV=py33-django17
|
||||
- TOX_ENV=py32-django17
|
||||
|
|
|
@ -101,15 +101,15 @@ There are many great markdown editors that make working with the documentation r
|
|||
|
||||
## Building the documentation
|
||||
|
||||
To build the documentation, simply run the `mkdocs.py` script.
|
||||
To build the documentation, install MkDocs with `pip install mkdocs` and then run the following command.
|
||||
|
||||
./mkdocs.py
|
||||
mkdocs build
|
||||
|
||||
This will build the html output into the `html` directory.
|
||||
|
||||
You can build the documentation and open a preview in a browser window by using the `-p` flag.
|
||||
You can build the documentation and open a preview in a browser window by using the `serve` command.
|
||||
|
||||
./mkdocs.py -p
|
||||
mkdocs serve
|
||||
|
||||
## Language style
|
||||
|
||||
|
|
1
docs/CNAME
Normal file
1
docs/CNAME
Normal file
|
@ -0,0 +1 @@
|
|||
www.django-rest-framework.org
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="authentication.py"></a>
|
||||
source: authentication.py
|
||||
|
||||
# Authentication
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="negotiation.py"></a>
|
||||
source: negotiation.py
|
||||
|
||||
# Content negotiation
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="exceptions.py"></a>
|
||||
source: exceptions.py
|
||||
|
||||
# Exceptions
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="fields.py"></a>
|
||||
source: fields.py
|
||||
|
||||
# Serializer fields
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="filters.py"></a>
|
||||
source: filters.py
|
||||
|
||||
# Filtering
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="urlpatterns.py"></a>
|
||||
source: urlpatterns.py
|
||||
|
||||
# Format suffixes
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<a class="github" href="mixins.py"></a>
|
||||
<a class="github" href="generics.py"></a>
|
||||
source: mixins.py
|
||||
generics.py
|
||||
|
||||
# Generic views
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="pagination.py"></a>
|
||||
source: pagination.py
|
||||
|
||||
# Pagination
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="parsers.py"></a>
|
||||
source: parsers.py
|
||||
|
||||
# Parsers
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="permissions.py"></a>
|
||||
source: permissions.py
|
||||
|
||||
# Permissions
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="relations.py"></a>
|
||||
source: relations.py
|
||||
|
||||
# Serializer relations
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="renderers.py"></a>
|
||||
source: renderers.py
|
||||
|
||||
# Renderers
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="request.py"></a>
|
||||
source: request.py
|
||||
|
||||
# Requests
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="response.py"></a>
|
||||
source: response.py
|
||||
|
||||
# Responses
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="reverse.py"></a>
|
||||
source: reverse.py
|
||||
|
||||
# Returning URLs
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="routers.py"></a>
|
||||
source: routers.py
|
||||
|
||||
# Routers
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="serializers.py"></a>
|
||||
source: serializers.py
|
||||
|
||||
# Serializers
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="settings.py"></a>
|
||||
source: settings.py
|
||||
|
||||
# Settings
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="status.py"></a>
|
||||
source: status.py
|
||||
|
||||
# Status Codes
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="test.py"></a>
|
||||
source: test.py
|
||||
|
||||
# Testing
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="throttling.py"></a>
|
||||
source: throttling.py
|
||||
|
||||
# Throttling
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<a class="github" href="decorators.py"></a> <a class="github" href="views.py"></a>
|
||||
source: decorators.py
|
||||
views.py
|
||||
|
||||
# Class Based Views
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<a class="github" href="viewsets.py"></a>
|
||||
source: viewsets.py
|
||||
|
||||
# ViewSets
|
||||
|
||||
|
|
|
@ -192,6 +192,18 @@ body{
|
|||
.navbar .navbar-inner .dropdown-menu li a, .navbar .navbar-inner .dropdown-menu li{
|
||||
color: #A30000;
|
||||
}
|
||||
|
||||
.dropdown-menu .active > a,
|
||||
.dropdown-menu .active > a:hover {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.navbar-inverse .nav .dropdown .active > a,
|
||||
.navbar-inverse .nav .dropdown .active > a:hover,
|
||||
.navbar-inverse .nav .dropdown .active > a:focus {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.navbar .navbar-inner .dropdown-menu li a:hover{
|
||||
background: #eeeeee;
|
||||
color: #c20000;
|
||||
|
|
|
@ -26,9 +26,6 @@
|
|||
<img alt="Django REST Framework" title="Logo by Jake 'Sid' Smith" src="img/logo.png" width="600px" style="display: block; margin: 0 auto 0 auto">
|
||||
</p>
|
||||
|
||||
<!--
|
||||
# Django REST framework
|
||||
-->
|
||||
|
||||
Django REST framework is a powerful and flexible toolkit that makes it easy to build Web APIs.
|
||||
|
||||
|
@ -175,7 +172,7 @@ The API guide is your complete reference manual to all the functionality provide
|
|||
* [Serializers][serializers]
|
||||
* [Serializer fields][fields]
|
||||
* [Serializer relations][relations]
|
||||
* [Validators][validators]
|
||||
<!--* [Validators][validators]-->
|
||||
* [Authentication][authentication]
|
||||
* [Permissions][permissions]
|
||||
* [Throttling][throttling]
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
markdown>=2.1.0
|
|
@ -1,239 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<title>{{ title }}</title>
|
||||
<link href="{{ base_url }}/img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="{{ canonical_url }}"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="{{ description }}">
|
||||
<meta name="author" content="Tom Christie">
|
||||
|
||||
<!-- Le styles -->
|
||||
<link href="{{ base_url }}/css/prettify.css" rel="stylesheet">
|
||||
<link href="{{ base_url }}/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="{{ base_url }}/css/bootstrap-responsive.css" rel="stylesheet">
|
||||
<link href="{{ base_url }}/css/default.css" rel="stylesheet">
|
||||
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-18852272-2']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
<style>
|
||||
span.fusion-wrap a {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
color: black;
|
||||
}
|
||||
|
||||
a.fusion-poweredby {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
div.promo {display: none;}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="prettyPrint()" class="{{ page_id }}-page">
|
||||
|
||||
<div class="wrapper">
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container-fluid">
|
||||
<a class="repo-link btn btn-primary btn-small" href="https://github.com/tomchristie/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small {{ next_url_disabled }}" href="{{ next_url }}">Next <i class="icon-arrow-right icon-white"></i></a>
|
||||
<a class="repo-link btn btn-inverse btn-small {{ prev_url_disabled }}" href="{{ prev_url }}"><i class="icon-arrow-left icon-white"></i> Previous</a>
|
||||
<a class="repo-link btn btn-inverse btn-small" href="#searchModal" data-toggle="modal"><i class="icon-search icon-white"></i> Search</a>
|
||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</a>
|
||||
<a class="brand" href="{{ base_url }}{{ index }}">Django REST framework</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li><a href="{{ base_url }}{{ index }}">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="{{ base_url }}/tutorial/quickstart{{ suffix }}">Quickstart</a></li>
|
||||
<li><a href="{{ base_url }}/tutorial/1-serialization{{ suffix }}">1 - Serialization</a></li>
|
||||
<li><a href="{{ base_url }}/tutorial/2-requests-and-responses{{ suffix }}">2 - Requests and responses</a></li>
|
||||
<li><a href="{{ base_url }}/tutorial/3-class-based-views{{ suffix }}">3 - Class based views</a></li>
|
||||
<li><a href="{{ base_url }}/tutorial/4-authentication-and-permissions{{ suffix }}">4 - Authentication and permissions</a></li>
|
||||
<li><a href="{{ base_url }}/tutorial/5-relationships-and-hyperlinked-apis{{ suffix }}">5 - Relationships and hyperlinked APIs</a></li>
|
||||
<li><a href="{{ base_url }}/tutorial/6-viewsets-and-routers{{ suffix }}">6 - Viewsets and routers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{ base_url }}/api-guide/requests{{ suffix }}">Requests</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/responses{{ suffix }}">Responses</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/views{{ suffix }}">Views</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/generic-views{{ suffix }}">Generic views</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/viewsets{{ suffix }}">Viewsets</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/routers{{ suffix }}">Routers</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/parsers{{ suffix }}">Parsers</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/renderers{{ suffix }}">Renderers</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/serializers{{ suffix }}">Serializers</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/fields{{ suffix }}">Serializer fields</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/relations{{ suffix }}">Serializer relations</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/validators{{ suffix }}">Validators</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/authentication{{ suffix }}">Authentication</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/permissions{{ suffix }}">Permissions</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/throttling{{ suffix }}">Throttling</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/filtering{{ suffix }}">Filtering</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/pagination{{ suffix }}">Pagination</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/content-negotiation{{ suffix }}">Content negotiation</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/format-suffixes{{ suffix }}">Format suffixes</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/reverse{{ suffix }}">Returning URLs</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/exceptions{{ suffix }}">Exceptions</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/status-codes{{ suffix }}">Status codes</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/testing{{ suffix }}">Testing</a></li>
|
||||
<li><a href="{{ base_url }}/api-guide/settings{{ suffix }}">Settings</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{ base_url }}/topics/documenting-your-api{{ suffix }}">Documenting your API</a></li>
|
||||
<li><a href="{{ base_url }}/topics/ajax-csrf-cors{{ suffix }}">AJAX, CSRF & CORS</a></li>
|
||||
<li><a href="{{ base_url }}/topics/browser-enhancements{{ suffix }}">Browser enhancements</a></li>
|
||||
<li><a href="{{ base_url }}/topics/browsable-api{{ suffix }}">The Browsable API</a></li>
|
||||
<li><a href="{{ base_url }}/topics/rest-hypermedia-hateoas{{ suffix }}">REST, Hypermedia & HATEOAS</a></li>
|
||||
<li><a href="{{ base_url }}/topics/third-party-resources{{ suffix }}">Third Party Resources</a></li>
|
||||
<li><a href="{{ base_url }}/topics/contributing{{ suffix }}">Contributing to REST framework</a></li>
|
||||
<li><a href="{{ base_url }}/topics/rest-framework-2-announcement{{ suffix }}">2.0 Announcement</a></li>
|
||||
<li><a href="{{ base_url }}/topics/2.2-announcement{{ suffix }}">2.2 Announcement</a></li>
|
||||
<li><a href="{{ base_url }}/topics/2.3-announcement{{ suffix }}">2.3 Announcement</a></li>
|
||||
<li><a href="{{ base_url }}/topics/2.4-announcement{{ suffix }}">2.4 Announcement</a></li>
|
||||
<li><a href="{{ base_url }}/topics/kickstarter-announcement{{ suffix }}">Kickstarter Announcement</a></li>
|
||||
<li><a href="{{ base_url }}/topics/release-notes{{ suffix }}">Release Notes</a></li>
|
||||
<li><a href="{{ base_url }}/topics/credits{{ suffix }}">Credits</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav pull-right">
|
||||
<!-- TODO
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">Trunk</a></li>
|
||||
<li><a href="#">2.0.0</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- Search Modal -->
|
||||
<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- Custom google search -->
|
||||
<script>
|
||||
(function() {
|
||||
var cx = '015016005043623903336:rxraeohqk6w';
|
||||
var gcse = document.createElement('script');
|
||||
gcse.type = 'text/javascript';
|
||||
gcse.async = true;
|
||||
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
|
||||
'//www.google.com/cse/cse.js?cx=' + cx;
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(gcse, s);
|
||||
})();
|
||||
</script>
|
||||
<gcse:search></gcse:search>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
|
||||
<div class="span3">
|
||||
<!-- TODO
|
||||
<p style="margin-top: -12px">
|
||||
<a class="btn btn-mini btn-primary" style="width: 60px">« previous</a>
|
||||
<a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next »</a>
|
||||
</p>
|
||||
-->
|
||||
<div id="table-of-contents">
|
||||
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
|
||||
{{ toc }}
|
||||
<div class="promo">
|
||||
{{ ad_block }}
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
{{ content }}
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
</div><!--/.fluid-container-->
|
||||
</div><!--/.body content-->
|
||||
|
||||
<div id="push"></div>
|
||||
</div><!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="{{ base_url }}/js/jquery-1.8.1-min.js"></script>
|
||||
<script src="{{ base_url }}/js/prettify-1.0.js"></script>
|
||||
<script src="{{ base_url }}/js/bootstrap-2.1.1-min.js"></script>
|
||||
|
||||
<script>
|
||||
//$('.side-nav').scrollspy()
|
||||
var shiftWindow = function() { scrollBy(0, -50) };
|
||||
if (location.hash) shiftWindow();
|
||||
window.addEventListener("hashchange", shiftWindow);
|
||||
|
||||
$('.dropdown-menu').on('click touchstart', function(event) {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Dynamically force sidenav to no higher than browser window
|
||||
$('.side-nav').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function(){
|
||||
$(window).resize(function(){
|
||||
$('.side-nav').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body></html>
|
|
@ -170,7 +170,7 @@ We strongly recommend that you use the namespaced import style of `import serial
|
|||
The `validate_<field_name>` method hooks that can be attached to serializer classes change their signature slightly and return type. Previously these would take a dictionary of all incoming data, and a key representing the field name, and would return a dictionary including the validated data for that field:
|
||||
|
||||
def validate_score(self, attrs, source):
|
||||
if attrs[score] % 10 != 0:
|
||||
if attrs['score'] % 10 != 0:
|
||||
raise serializers.ValidationError('This field should be a multiple of ten.')
|
||||
return attrs
|
||||
|
||||
|
|
|
@ -135,15 +135,15 @@ There are many great Markdown editors that make working with the documentation r
|
|||
|
||||
## Building the documentation
|
||||
|
||||
To build the documentation, simply run the `mkdocs.py` script.
|
||||
To build the documentation, install MkDocs with `pip install mkdocs` and then run the following command.
|
||||
|
||||
./mkdocs.py
|
||||
mkdocs build
|
||||
|
||||
This will build the html output into the `html` directory.
|
||||
This will build the documentation into the `site` directory.
|
||||
|
||||
You can build the documentation and open a preview in a browser window by using the `-p` flag.
|
||||
You can build the documentation and open a preview in a browser window by using the `serve` command.
|
||||
|
||||
./mkdocs.py -p
|
||||
mkdocs serve
|
||||
|
||||
## Language style
|
||||
|
||||
|
|
|
@ -1,92 +1,322 @@
|
|||
# Third Party Resources
|
||||
|
||||
## About Third Party Packages
|
||||
|
||||
Third Party Packages allow developers to share code that extends the functionality of Django REST framework, in order to support additional use-cases.
|
||||
|
||||
We **support**, **encourage** and **strongly favour** the creation of Third Party Packages to encapsulate new behaviour rather than adding additional functionality directly to Django REST Framework.
|
||||
|
||||
We aim to make creating Third Party Packages as easy as possible, whilst keeping the **simplicity** of the core API and ensuring that **maintenance** of the main project remains under control. If a Third Party Package proves popular it is relatively easy to move it into the main project; removing features is much more problematic.
|
||||
|
||||
If you have an idea for a new feature please consider how it may be packaged as a Third Party Package. We're always happy to dicuss ideas on the [Mailing List][discussion-group].
|
||||
|
||||
## How to create a Third Party Package
|
||||
|
||||
### Creating your package
|
||||
|
||||
You can use [this cookiecutter template][cookiecutter] for creating reusable Django REST Framework packages quickly. Cookiecutter creates projects from project templates. While optional, this cookiecutter template includes best practices from Django REST framework and other packages, as well as a Travis CI configuration, Tox configuration, and a sane setup.py for easy PyPI registration/distribution.
|
||||
|
||||
Note: Let us know if you have an alternate cookiecuter package so we can also link to it.
|
||||
|
||||
#### Running the initial cookiecutter command
|
||||
|
||||
To run the initial cookiecutter command, you'll first need to install the Python `cookiecutter` package.
|
||||
|
||||
$ pip install cookiecutter
|
||||
|
||||
Once `cookiecutter` is installed just run the following to create a new project.
|
||||
|
||||
$ cookiecutter gh:jpadilla/cookiecutter-django-rest-framework
|
||||
|
||||
You'll be prompted for some questions, answer them, then it'll create your Python package in the current working directory based on those values.
|
||||
|
||||
full_name (default is "Your full name here")? Johnny Appleseed
|
||||
email (default is "you@example.com")? jappleseed@example.com
|
||||
github_username (default is "yourname")? jappleseed
|
||||
pypi_project_name (default is "dj-package")? djangorestframework-custom-auth
|
||||
repo_name (default is "dj-package")? django-rest-framework-custom-auth
|
||||
app_name (default is "djpackage")? custom_auth
|
||||
project_short_description (default is "Your project description goes here")?
|
||||
year (default is "2014")?
|
||||
version (default is "0.1.0")?
|
||||
|
||||
#### Getting it onto GitHub
|
||||
|
||||
To put your project up on GitHub, you'll need a repository for it to live in. You can create a new repository [here][new-repo]. If you need help, check out the [Create A Repo][create-a-repo] article on GitHub.
|
||||
|
||||
|
||||
#### Adding to Travis CI
|
||||
|
||||
We recommend using [Travis CI][travis-ci], a hosted continuous integration service which integrates well with GitHub and is free for public repositories.
|
||||
|
||||
To get started with Travis CI, [sign in][travis-ci] with your GitHub account. Once you're signed in, go to your [profile page][travis-profile] and enable the service hook for the repository you want.
|
||||
|
||||
If you use the cookiecutter template, your project will already contain a `.travis.yml` file which Travis CI will use to build your project and run tests. By default, builds are triggered everytime you push to your repository or create Pull Request.
|
||||
|
||||
#### Uploading to PyPI
|
||||
|
||||
Once you've got at least a prototype working and tests running, you should publish it on PyPI to allow others to install it via `pip`.
|
||||
|
||||
You must [register][pypi-register] an account before publishing to PyPI.
|
||||
|
||||
To register your package on PyPI run the following command.
|
||||
|
||||
$ python setup.py register
|
||||
|
||||
If this is the first time publishing to PyPI, you'll be prompted to login.
|
||||
|
||||
Note: Before publishing you'll need to make sure you have the latest pip that supports `wheel` as well as install the `wheel` package.
|
||||
|
||||
$ pip install --upgrade pip
|
||||
$ pip install wheel
|
||||
|
||||
After this, every time you want to release a new version on PyPI just run the following command.
|
||||
|
||||
$ python setup.py publish
|
||||
You probably want to also tag the version now:
|
||||
git tag -a {0} -m 'version 0.1.0'
|
||||
git push --tags
|
||||
|
||||
After releasing a new version to PyPI, it's always a good idea to tag the version and make available as a GitHub Release.
|
||||
|
||||
We recommend to follow [Semantic Versioning][semver] for your package's versions.
|
||||
|
||||
### Development
|
||||
|
||||
#### Version requirements
|
||||
|
||||
The cookiecutter template assumes a set of supported versions will be provided for Python and Django. Make sure you correctly update your requirements, docs, `tox.ini`, `.travis.yml`, and `setup.py` to match the set of versions you wish to support.
|
||||
|
||||
#### Tests
|
||||
|
||||
The cookiecutter template includes a `runtests.py` which uses the `pytest` package as a test runner.
|
||||
|
||||
Before running, you'll need to install a couple test requirements.
|
||||
|
||||
$ pip install -r requirements-test.txt
|
||||
|
||||
Once requirements installed, you can run `runtests.py`.
|
||||
|
||||
$ ./runtests.py
|
||||
|
||||
Run using a more concise output style.
|
||||
|
||||
$ ./runtests.py -q
|
||||
|
||||
Run the tests using a more concise output style, no coverage, no flake8.
|
||||
|
||||
$ ./runtests.py --fast
|
||||
|
||||
Don't run the flake8 code linting.
|
||||
|
||||
$ ./runtests.py --nolint
|
||||
|
||||
Only run the flake8 code linting, don't run the tests.
|
||||
|
||||
$ ./runtests.py --lintonly
|
||||
|
||||
Run the tests for a given test case.
|
||||
|
||||
$ ./runtests.py MyTestCase
|
||||
|
||||
Run the tests for a given test method.
|
||||
|
||||
$ ./runtests.py MyTestCase.test_this_method
|
||||
|
||||
Shorter form to run the tests for a given test method.
|
||||
|
||||
$ ./runtests.py test_this_method
|
||||
|
||||
To run your tests against multiple versions of Python as different versions of requirements such as Django we recommend using `tox`. [Tox][tox-docs] is a generic virtualenv management and test command line tool.
|
||||
|
||||
First, install `tox` globally.
|
||||
|
||||
$ pip install tox
|
||||
|
||||
To run `tox`, just simply run:
|
||||
|
||||
$ tox
|
||||
|
||||
To run a particular `tox` environment:
|
||||
|
||||
$ tox -e envlist
|
||||
|
||||
`envlist` is a comma-separated value to that specifies the environments to run tests against. To view a list of all possible test environments, run:
|
||||
|
||||
$ tox -l
|
||||
|
||||
#### Version compatibility
|
||||
|
||||
Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into a `compat.py` module, and should provide a single common interface that the rest of the codebase can use.
|
||||
|
||||
Check out Django REST framework's [compat.py][drf-compat] for an example.
|
||||
|
||||
### Once your package is available
|
||||
|
||||
Once your package is decently documented and available on PyPI, you might want share it with others that might find it useful.
|
||||
|
||||
#### Adding to the Django REST framework grid
|
||||
|
||||
We suggest adding your package to the [REST Framework][rest-framework-grid] grid on Django Packages.
|
||||
|
||||
#### Adding to the Django REST framework docs
|
||||
|
||||
Create a [Pull Request][drf-create-pr] or [Issue][drf-create-issue] on GitHub, and we'll add a link to it from the main REST framework documentation. You can add your package under **Third party packages** of the API Guide section that best applies, like [Authentication][authentication] or [Permissions][permissions]. You can also link your package under the [Third Party Resources][third-party-resources] section.
|
||||
|
||||
#### Announce on the discussion group.
|
||||
|
||||
You can also let others know about your package through the [discussion group][discussion-group].
|
||||
|
||||
## Existing Third Party Packages
|
||||
|
||||
Django REST Framework has a growing community of developers, packages, and resources.
|
||||
|
||||
Check out a grid detailing all the packages and ecosystem around Django REST Framework at [Django Packages](https://www.djangopackages.com/grids/g/django-rest-framework/).
|
||||
Check out a grid detailing all the packages and ecosystem around Django REST Framework at [Django Packages][rest-framework-grid].
|
||||
|
||||
To submit new content, [open an issue](https://github.com/tomchristie/django-rest-framework/issues/new) or [create a pull request](https://github.com/tomchristie/django-rest-framework/).
|
||||
|
||||
## Libraries and Extensions
|
||||
To submit new content, [open an issue][drf-create-issue] or [create a pull request][drf-create-pr].
|
||||
|
||||
### Authentication
|
||||
|
||||
* [djangorestframework-digestauth](https://github.com/juanriaza/django-rest-framework-digestauth) - Provides Digest Access Authentication support.
|
||||
* [django-oauth-toolkit](https://github.com/evonove/django-oauth-toolkit) - Provides OAuth 2.0 support.
|
||||
* [doac](https://github.com/Rediker-Software/doac) - Provides OAuth 2.0 support.
|
||||
* [djangorestframework-jwt](https://github.com/GetBlimp/django-rest-framework-jwt) - Provides JSON Web Token Authentication support.
|
||||
* [hawkrest](https://github.com/kumar303/hawkrest) - Provides Hawk HTTP Authorization.
|
||||
* [djangorestframework-httpsignature](https://github.com/etoccalino/django-rest-framework-httpsignature) - Provides an easy to use HTTP Signature Authentication mechanism.
|
||||
* [djoser](https://github.com/sunscrapers/djoser) - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.
|
||||
* [djangorestframework-digestauth][djangorestframework-digestauth] - Provides Digest Access Authentication support.
|
||||
* [django-oauth-toolkit][django-oauth-toolkit] - Provides OAuth 2.0 support.
|
||||
* [doac][doac] - Provides OAuth 2.0 support.
|
||||
* [djangorestframework-jwt][djangorestframework-jwt] - Provides JSON Web Token Authentication support.
|
||||
* [hawkrest][hawkrest] - Provides Hawk HTTP Authorization.
|
||||
* [djangorestframework-httpsignature][djangorestframework-httpsignature] - Provides an easy to use HTTP Signature Authentication mechanism.
|
||||
* [djoser][djoser] - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.
|
||||
|
||||
### Permissions
|
||||
|
||||
* [drf-any-permissions](https://github.com/kevin-brown/drf-any-permissions) - Provides alternative permission handling.
|
||||
* [djangorestframework-composed-permissions](https://github.com/niwibe/djangorestframework-composed-permissions) - Provides a simple way to define complex permissions.
|
||||
* [rest_condition](https://github.com/caxap/rest_condition) - Another extension for building complex permissions in a simple and convenient way.
|
||||
* [drf-any-permissions][drf-any-permissions] - Provides alternative permission handling.
|
||||
* [djangorestframework-composed-permissions][djangorestframework-composed-permissions] - Provides a simple way to define complex permissions.
|
||||
* [rest_condition][rest-condition] - Another extension for building complex permissions in a simple and convenient way.
|
||||
|
||||
### Serializers
|
||||
|
||||
* [django-rest-framework-mongoengine](https://github.com/umutbozkurt/django-rest-framework-mongoengine) - Serializer class that supports using MongoDB as the storage layer for Django REST framework.
|
||||
* [djangorestframework-gis](https://github.com/djangonauts/django-rest-framework-gis) - Geographic add-ons
|
||||
* [djangorestframework-hstore](https://github.com/djangonauts/django-rest-framework-hstore) - Serializer class to support django-hstore DictionaryField model field and its schema-mode feature.
|
||||
* [django-rest-framework-mongoengine][django-rest-framework-mongoengine] - Serializer class that supports using MongoDB as the storage layer for Django REST framework.
|
||||
* [djangorestframework-gis][djangorestframework-gis] - Geographic add-ons
|
||||
* [djangorestframework-hstore][djangorestframework-hstore] - Serializer class to support django-hstore DictionaryField model field and its schema-mode feature.
|
||||
|
||||
### Serializer fields
|
||||
|
||||
* [drf-compound-fields](https://github.com/estebistec/drf-compound-fields) - Provides "compound" serializer fields, such as lists of simple values.
|
||||
* [django-extra-fields](https://github.com/Hipo/drf-extra-fields) - Provides extra serializer fields.
|
||||
* [drf-compound-fields][drf-compound-fields] - Provides "compound" serializer fields, such as lists of simple values.
|
||||
* [django-extra-fields][django-extra-fields] - Provides extra serializer fields.
|
||||
|
||||
### Views
|
||||
|
||||
* [djangorestframework-bulk](https://github.com/miki725/django-rest-framework-bulk) - Implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.
|
||||
* [djangorestframework-bulk][djangorestframework-bulk] - Implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.
|
||||
|
||||
### Routers
|
||||
|
||||
* [drf-nested-routers](https://github.com/alanjds/drf-nested-routers) - Provides routers and relationship fields for working with nested resources.
|
||||
* [wq.db.rest](http://wq.io/docs/about-rest) - Provides an admin-style model registration API with reasonable default URLs and viewsets.
|
||||
* [drf-nested-routers][drf-nested-routers] - Provides routers and relationship fields for working with nested resources.
|
||||
* [wq.db.rest][wq.db.rest] - Provides an admin-style model registration API with reasonable default URLs and viewsets.
|
||||
|
||||
### Parsers
|
||||
|
||||
* [djangorestframework-msgpack](https://github.com/juanriaza/django-rest-framework-msgpack) - Provides MessagePack renderer and parser support.
|
||||
* [djangorestframework-camel-case](https://github.com/vbabiy/djangorestframework-camel-case) - Provides camel case JSON renderers and parsers.
|
||||
* [djangorestframework-msgpack][djangorestframework-msgpack] - Provides MessagePack renderer and parser support.
|
||||
* [djangorestframework-camel-case][djangorestframework-camel-case] - Provides camel case JSON renderers and parsers.
|
||||
|
||||
### Renderers
|
||||
|
||||
* [djangorestframework-csv](https://github.com/mjumbewu/django-rest-framework-csv) - Provides CSV renderer support.
|
||||
* [drf_ujson](https://github.com/gizmag/drf-ujson-renderer) - Implements JSON rendering using the UJSON package.
|
||||
* [Django REST Pandas](https://github.com/wq/django-rest-pandas) - Pandas DataFrame-powered renderers including Excel, CSV, and SVG formats.
|
||||
* [djangorestframework-csv][djangorestframework-csv] - Provides CSV renderer support.
|
||||
* [drf_ujson][drf_ujson] - Implements JSON rendering using the UJSON package.
|
||||
* [rest-pandas][rest-pandas] - Pandas DataFrame-powered renderers including Excel, CSV, and SVG formats.
|
||||
|
||||
### Filtering
|
||||
|
||||
* [djangorestframework-chain](https://github.com/philipn/django-rest-framework-chain) - Allows arbitrary chaining of both relations and lookup filters.
|
||||
* [djangorestframework-chain][djangorestframework-chain] - Allows arbitrary chaining of both relations and lookup filters.
|
||||
|
||||
### Misc
|
||||
|
||||
* [djangorestrelationalhyperlink](https://github.com/fredkingham/django_rest_model_hyperlink_serializers_project) - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer.
|
||||
* [django-rest-swagger](https://github.com/marcgibbons/django-rest-swagger) - An API documentation generator for Swagger UI.
|
||||
* [django-rest-framework-proxy ](https://github.com/eofs/django-rest-framework-proxy) - Proxy to redirect incoming request to another API server.
|
||||
* [gaiarestframework](https://github.com/AppsFuel/gaiarestframework) - Utils for django-rest-framewok
|
||||
* [drf-extensions](https://github.com/chibisov/drf-extensions) - A collection of custom extensions
|
||||
* [ember-data-django-rest-adapter](https://github.com/toranb/ember-data-django-rest-adapter) - An ember-data adapter
|
||||
* [djangorestrelationalhyperlink][djangorestrelationalhyperlink] - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer.
|
||||
* [django-rest-swagger][django-rest-swagger] - An API documentation generator for Swagger UI.
|
||||
* [django-rest-framework-proxy][django-rest-framework-proxy] - Proxy to redirect incoming request to another API server.
|
||||
* [gaiarestframework][gaiarestframework] - Utils for django-rest-framewok
|
||||
* [drf-extensions][drf-extensions] - A collection of custom extensions
|
||||
* [ember-data-django-rest-adapter][ember-data-django-rest-adapter] - An ember-data adapter
|
||||
|
||||
## Tutorials
|
||||
## Other Resources
|
||||
|
||||
* [Beginner's Guide to the Django Rest Framework](http://code.tutsplus.com/tutorials/beginners-guide-to-the-django-rest-framework--cms-19786)
|
||||
* [Getting Started with Django Rest Framework and AngularJS](http://blog.kevinastone.com/getting-started-with-django-rest-framework-and-angularjs.html)
|
||||
* [End to end web app with Django-Rest-Framework & AngularJS](http://blog.mourafiq.com/post/55034504632/end-to-end-web-app-with-django-rest-framework)
|
||||
* [Start Your API - django-rest-framework part 1](https://godjango.com/41-start-your-api-django-rest-framework-part-1/)
|
||||
* [Permissions & Authentication - django-rest-framework part 2](https://godjango.com/43-permissions-authentication-django-rest-framework-part-2/)
|
||||
* [ViewSets and Routers - django-rest-framework part 3](https://godjango.com/45-viewsets-and-routers-django-rest-framework-part-3/)
|
||||
* [Django Rest Framework User Endpoint](http://richardtier.com/2014/02/25/django-rest-framework-user-endpoint/)
|
||||
* [Check credentials using Django Rest Framework](http://richardtier.com/2014/03/06/110/)
|
||||
### Tutorials
|
||||
|
||||
## Videos
|
||||
* [Beginner's Guide to the Django Rest Framework][beginners-guide-to-the-django-rest-framework]
|
||||
* [Getting Started with Django Rest Framework and AngularJS][getting-started-with-django-rest-framework-and-angularjs]
|
||||
* [End to end web app with Django-Rest-Framework & AngularJS][end-to-end-web-app-with-django-rest-framework-angularjs]
|
||||
* [Start Your API - django-rest-framework part 1][start-your-api-django-rest-framework-part-1]
|
||||
* [Permissions & Authentication - django-rest-framework part 2][permissions-authentication-django-rest-framework-part-2]
|
||||
* [ViewSets and Routers - django-rest-framework part 3][viewsets-and-routers-django-rest-framework-part-3]
|
||||
* [Django Rest Framework User Endpoint][django-rest-framework-user-endpoint]
|
||||
* [Check credentials using Django Rest Framework][check-credentials-using-django-rest-framework]
|
||||
|
||||
* [Ember and Django Part 1 (Video)](http://www.neckbeardrepublic.com/screencasts/ember-and-django-part-1)
|
||||
* [Django Rest Framework Part 1 (Video)](http://www.neckbeardrepublic.com/screencasts/django-rest-framework-part-1)
|
||||
* [Pyowa July 2013 - Django Rest Framework (Video)](http://www.youtube.com/watch?v=E1ZrehVxpBo)
|
||||
* [django-rest-framework and angularjs (Video)](http://www.youtube.com/watch?v=Q8FRBGTJ020)
|
||||
### Videos
|
||||
|
||||
## Articles
|
||||
* [Ember and Django Part 1 (Video)][ember-and-django-part 1-video]
|
||||
* [Django Rest Framework Part 1 (Video)][django-rest-framework-part-1-video]
|
||||
* [Pyowa July 2013 - Django Rest Framework (Video)][pyowa-july-2013-django-rest-framework-video]
|
||||
* [django-rest-framework and angularjs (Video)][django-rest-framework-and-angularjs-video]
|
||||
|
||||
* [Web API performance: profiling Django REST framework](http://dabapps.com/blog/api-performance-profiling-django-rest-framework/)
|
||||
* [API Development with Django and Django REST Framework](https://bnotions.com/api-development-with-django-and-django-rest-framework/)
|
||||
### Articles
|
||||
|
||||
* [Web API performance: profiling Django REST framework][web-api-performance-profiling-django-rest-framework]
|
||||
* [API Development with Django and Django REST Framework][api-development-with-django-and-django-rest-framework]
|
||||
|
||||
|
||||
[cookiecutter]: https://github.com/jpadilla/cookiecutter-django-rest-framework
|
||||
[new-repo]: https://github.com/new
|
||||
[create-a-repo]: https://help.github.com/articles/create-a-repo/
|
||||
[travis-ci]: https://travis-ci.org
|
||||
[travis-profile]: https://travis-ci.org/profile
|
||||
[pypi-register]: https://pypi.python.org/pypi?%3Aaction=register_form
|
||||
[semver]: http://semver.org/
|
||||
[tox-docs]: https://tox.readthedocs.org/en/latest/
|
||||
[drf-compat]: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/compat.py
|
||||
[rest-framework-grid]: https://www.djangopackages.com/grids/g/django-rest-framework/
|
||||
[drf-create-pr]: https://github.com/tomchristie/django-rest-framework/compare
|
||||
[drf-create-issue]: https://github.com/tomchristie/django-rest-framework/issues/new
|
||||
[authentication]: ../api-guide/authentication.md
|
||||
[permissions]: ../api-guide/permissions.md
|
||||
[discussion-group]: https://groups.google.com/forum/#!forum/django-rest-framework
|
||||
[djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth
|
||||
[django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit
|
||||
[doac]: https://github.com/Rediker-Software/doac
|
||||
[djangorestframework-jwt]: https://github.com/GetBlimp/django-rest-framework-jwt
|
||||
[hawkrest]: https://github.com/kumar303/hawkrest
|
||||
[djangorestframework-httpsignature]: https://github.com/etoccalino/django-rest-framework-httpsignature
|
||||
[djoser]: https://github.com/sunscrapers/djoser
|
||||
[drf-any-permissions]: https://github.com/kevin-brown/drf-any-permissions
|
||||
[djangorestframework-composed-permissions]: https://github.com/niwibe/djangorestframework-composed-permissions
|
||||
[rest-condition]: https://github.com/caxap/rest_condition
|
||||
[django-rest-framework-mongoengine]: https://github.com/umutbozkurt/django-rest-framework-mongoengine
|
||||
[djangorestframework-gis]: https://github.com/djangonauts/django-rest-framework-gis
|
||||
[djangorestframework-hstore]: https://github.com/djangonauts/django-rest-framework-hstore
|
||||
[drf-compound-fields]: https://github.com/estebistec/drf-compound-fields
|
||||
[django-extra-fields]: https://github.com/Hipo/drf-extra-fields
|
||||
[djangorestframework-bulk]: https://github.com/miki725/django-rest-framework-bulk
|
||||
[drf-nested-routers]: https://github.com/alanjds/drf-nested-routers
|
||||
[wq.db.rest]: http://wq.io/docs/about-rest
|
||||
[djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack
|
||||
[djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case
|
||||
[djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv
|
||||
[drf_ujson]: https://github.com/gizmag/drf-ujson-renderer
|
||||
[rest-pandas]: https://github.com/wq/django-rest-pandas
|
||||
[djangorestframework-chain]: https://github.com/philipn/django-rest-framework-chain
|
||||
[djangorestrelationalhyperlink]: https://github.com/fredkingham/django_rest_model_hyperlink_serializers_project
|
||||
[django-rest-swagger]: https://github.com/marcgibbons/django-rest-swagger
|
||||
[django-rest-framework-proxy]: https://github.com/eofs/django-rest-framework-proxy
|
||||
[gaiarestframework]: https://github.com/AppsFuel/gaiarestframework
|
||||
[drf-extensions]: https://github.com/chibisov/drf-extensions
|
||||
[ember-data-django-rest-adapter]: https://github.com/toranb/ember-data-django-rest-adapter
|
||||
[beginners-guide-to-the-django-rest-framework]: http://code.tutsplus.com/tutorials/beginners-guide-to-the-django-rest-framework--cms-19786
|
||||
[getting-started-with-django-rest-framework-and-angularjs]: http://blog.kevinastone.com/getting-started-with-django-rest-framework-and-angularjs.html
|
||||
[end-to-end-web-app-with-django-rest-framework-angularjs]: http://blog.mourafiq.com/post/55034504632/end-to-end-web-app-with-django-rest-framework
|
||||
[start-your-api-django-rest-framework-part-1]: https://godjango.com/41-start-your-api-django-rest-framework-part-1/
|
||||
[permissions-authentication-django-rest-framework-part-2]: https://godjango.com/43-permissions-authentication-django-rest-framework-part-2/
|
||||
[viewsets-and-routers-django-rest-framework-part-3]: https://godjango.com/45-viewsets-and-routers-django-rest-framework-part-3/
|
||||
[django-rest-framework-user-endpoint]: http://richardtier.com/2014/02/25/django-rest-framework-user-endpoint/
|
||||
[check-credentials-using-django-rest-framework]: http://richardtier.com/2014/03/06/110/
|
||||
[ember-and-django-part 1-video]: http://www.neckbeardrepublic.com/screencasts/ember-and-django-part-1
|
||||
[django-rest-framework-part-1-video]: http://www.neckbeardrepublic.com/screencasts/django-rest-framework-part-1
|
||||
[pyowa-july-2013-django-rest-framework-video]: http://www.youtube.com/watch?v=e1zrehvxpbo
|
||||
[django-rest-framework-and-angularjs-video]: http://www.youtube.com/watch?v=q8frbgtj020
|
||||
[web-api-performance-profiling-django-rest-framework]: http://dabapps.com/blog/api-performance-profiling-django-rest-framework/
|
||||
[api-development-with-django-and-django-rest-framework]: https://bnotions.com/api-development-with-django-and-django-rest-framework/
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<title>Django REST framework - 404 - Page not found</title>
|
||||
<link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="http://www.django-rest-framework.org/404"/>
|
||||
<link rel="canonical" href="http://www.django-rest-framework.org/404" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Django, API, REST, 404 - Page not found">
|
||||
<meta name="author" content="Tom Christie">
|
||||
|
@ -21,20 +23,22 @@
|
|||
<![endif]-->
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-18852272-2']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
var ga = document.createElement('script');
|
||||
ga.type = 'text/javascript';
|
||||
ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="prettyPrint()" class="404-page">
|
||||
</head>
|
||||
|
||||
<body onload="prettyPrint()" class="404-page">
|
||||
|
||||
<div class="wrapper">
|
||||
|
||||
|
@ -121,16 +125,16 @@
|
|||
</li>
|
||||
-->
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- Search Modal -->
|
||||
<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<!-- Search Modal -->
|
||||
<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
|
@ -154,23 +158,30 @@
|
|||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
<div id="main-content" class="span12">
|
||||
<h1 id="404-page-not-found" style="text-align: center">404</h1>
|
||||
<p style="text-align: center"><strong>Page not found</strong></p>
|
||||
<p style="text-align: center"><strong>Page not found</strong>
|
||||
</p>
|
||||
<p style="text-align: center">Try the <a href="http://www.django-rest-framework.org/">homepage</a>, or <a href="#searchModal" data-toggle="modal">search the documentation</a>.</p>
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
</div><!--/.fluid-container-->
|
||||
</div><!--/.body content-->
|
||||
</div>
|
||||
<!--/span-->
|
||||
</div>
|
||||
<!--/row-->
|
||||
</div>
|
||||
<!--/.fluid-container-->
|
||||
</div>
|
||||
<!--/.body content-->
|
||||
|
||||
<div id="push"></div>
|
||||
</div><!--/.wrapper -->
|
||||
</div>
|
||||
<!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
|
||||
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
|
@ -181,7 +192,9 @@
|
|||
<script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>
|
||||
<script>
|
||||
//$('.side-nav').scrollspy()
|
||||
var shiftWindow = function() { scrollBy(0, -50) };
|
||||
var shiftWindow = function() {
|
||||
scrollBy(0, -50)
|
||||
};
|
||||
if (location.hash) shiftWindow();
|
||||
window.addEventListener("hashchange", shiftWindow);
|
||||
|
||||
|
@ -192,10 +205,12 @@
|
|||
// Dynamically force sidenav to no higher than browser window
|
||||
$('.side-nav').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function(){
|
||||
$(window).resize(function(){
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body></html>
|
||||
</body>
|
||||
|
||||
</html>
|
196
docs_theme/base.html
Normal file
196
docs_theme/base.html
Normal file
|
@ -0,0 +1,196 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<title>{{ page_title }}</title>
|
||||
<link href="{{ base_url }}/img/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<link rel="canonical" href="{{ canonical_url }}" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Django, API, REST, {{ current_page.title }}">
|
||||
<meta name="author" content="Tom Christie">
|
||||
|
||||
<!-- Le styles -->
|
||||
<link href="{{ base_url }}/css/prettify.css" rel="stylesheet">
|
||||
<link href="{{ base_url }}/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="{{ base_url }}/css/bootstrap-responsive.css" rel="stylesheet">
|
||||
<link href="{{ base_url }}/css/default.css" rel="stylesheet">
|
||||
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-18852272-2']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script');
|
||||
ga.type = 'text/javascript';
|
||||
ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
span.fusion-wrap a {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
color: black;
|
||||
}
|
||||
a.fusion-poweredby {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
div.promo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="prettyPrint()" class="{% if current_page.is_homepage %}index{% endif %}-page">
|
||||
|
||||
<div class="wrapper">
|
||||
|
||||
{% include "nav.html" %}
|
||||
|
||||
<div class="body-content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- Search Modal -->
|
||||
<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Documentation search</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<!-- Custom google search -->
|
||||
<script>
|
||||
(function() {
|
||||
var cx = '015016005043623903336:rxraeohqk6w';
|
||||
var gcse = document.createElement('script');
|
||||
gcse.type = 'text/javascript';
|
||||
gcse.async = true;
|
||||
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
|
||||
'//www.google.com/cse/cse.js?cx=' + cx;
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(gcse, s);
|
||||
})();
|
||||
</script>
|
||||
<gcse:search></gcse:search>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
|
||||
<div class="span3">
|
||||
<!-- TODO
|
||||
<p style="margin-top: -12px">
|
||||
<a class="btn btn-mini btn-primary" style="width: 60px">« previous</a>
|
||||
<a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next »</a>
|
||||
</p>
|
||||
-->
|
||||
<div id="table-of-contents">
|
||||
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
|
||||
|
||||
{% if current_page.is_homepage %}
|
||||
<li class="main">
|
||||
<a href="#">Django REST framework</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% for toc_item in toc %}
|
||||
|
||||
<li class="{% if not current_page.is_homepage %}main{% endif %}">
|
||||
<a href="{{ toc_item.url }}">{{ toc_item.title }}</a>
|
||||
</li>
|
||||
|
||||
{% for toc_item in toc_item.children %}
|
||||
<li>
|
||||
<a href="{{ toc_item.url }}">{{ toc_item.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if current_page.is_homepage %}
|
||||
<div class="promo">
|
||||
<hr/>
|
||||
<script type="text/javascript" src="//cdn.fusionads.net/fusion.js?zoneid=1332&serve=C6SDP2Y&placement=djangorestframework" id="_fusionads_js"></script>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-content" class="span9">
|
||||
{% if meta.source %}
|
||||
{% for filename in meta.source %}
|
||||
<a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/{{ filename }}">
|
||||
<span class="label label-info">{{ filename }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{{ content }}
|
||||
</div>
|
||||
<!--/span-->
|
||||
</div>
|
||||
<!--/row-->
|
||||
</div>
|
||||
<!--/.fluid-container-->
|
||||
</div>
|
||||
<!--/.body content-->
|
||||
<div id="push"></div>
|
||||
</div>
|
||||
<!--/.wrapper -->
|
||||
|
||||
<footer class="span12">
|
||||
<p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="{{ base_url }}/js/jquery-1.8.1-min.js"></script>
|
||||
<script src="{{ base_url }}/js/prettify-1.0.js"></script>
|
||||
<script src="{{ base_url }}/js/bootstrap-2.1.1-min.js"></script>
|
||||
|
||||
<script>
|
||||
//$('.side-nav').scrollspy()
|
||||
var shiftWindow = function() {
|
||||
scrollBy(0, -50)
|
||||
};
|
||||
if (location.hash) shiftWindow();
|
||||
window.addEventListener("hashchange", shiftWindow);
|
||||
|
||||
$('.dropdown-menu').on('click touchstart', function(event) {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Dynamically force sidenav to no higher than browser window
|
||||
$('.side-nav').css('max-height', window.innerHeight - 130);
|
||||
|
||||
$(function() {
|
||||
$(window).resize(function() {
|
||||
$('.side-nav').css('max-height', window.innerHeight - 130);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
47
docs_theme/nav.html
Normal file
47
docs_theme/nav.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container-fluid">
|
||||
<a class="repo-link btn btn-primary btn-small" href="https://github.com/tomchristie/django-rest-framework/tree/master">GitHub</a>
|
||||
<a class="repo-link btn btn-inverse btn-small {% if not next_page %}disabled{% endif %}" rel="prev" {% if next_page %}href="{{ next_page.url }}"{% endif %}>
|
||||
Next <i class="icon-arrow-right icon-white"></i>
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small {% if not previous_page %}disabled{% endif %}" rel="next" {% if previous_page %}href="{{ previous_page.url }}"{% endif %}>
|
||||
<i class="icon-arrow-left icon-white"></i> Previous
|
||||
</a>
|
||||
<a class="repo-link btn btn-inverse btn-small" href="#searchModal" data-toggle="modal"><i class="icon-search icon-white"></i> Search</a>
|
||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</a>
|
||||
<a class="brand" href="http://www.django-rest-framework.org">Django REST framework</a>
|
||||
<div class="nav-collapse collapse">
|
||||
{% if include_nav %}
|
||||
<!-- Main navigation -->
|
||||
<ul class="nav navbar-nav">
|
||||
<li {% if current_page.is_homepage %}class="active"{% endif %}><a href="/">Home</a></li>
|
||||
{% for nav_item in nav %} {% if nav_item.children %}
|
||||
<li class="dropdown{% if nav_item.active %} active{% endif %}">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ nav_item.title }} <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for nav_item in nav_item.children %}
|
||||
<li {% if nav_item.active %}class="active" {% endif %}>
|
||||
<a href="{{ nav_item.url }}">{{ nav_item.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li {% if nav_item.active %}class="active" {% endif %}>
|
||||
<a href="{{ nav_item.url }}">{{ nav_item.title }}</a>
|
||||
</li>
|
||||
{% endif %} {% endfor %}
|
||||
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
203
mkdocs.py
203
mkdocs.py
|
@ -1,203 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import markdown
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
root_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
docs_dir = os.path.join(root_dir, 'docs')
|
||||
html_dir = os.path.join(root_dir, 'html')
|
||||
|
||||
local = not '--deploy' in sys.argv
|
||||
preview = '-p' in sys.argv
|
||||
|
||||
if local:
|
||||
base_url = 'file://%s/' % os.path.normpath(os.path.join(os.getcwd(), html_dir))
|
||||
suffix = '.html'
|
||||
index = 'index.html'
|
||||
else:
|
||||
base_url = 'http://www.django-rest-framework.org'
|
||||
suffix = ''
|
||||
index = ''
|
||||
|
||||
|
||||
main_header = '<li class="main"><a href="#{{ anchor }}">{{ title }}</a></li>'
|
||||
sub_header = '<li><a href="#{{ anchor }}">{{ title }}</a></li>'
|
||||
code_label = r'<a class="github" href="https://github.com/tomchristie/django-rest-framework/tree/master/rest_framework/\1"><span class="label label-info">\1</span></a>'
|
||||
|
||||
page = open(os.path.join(docs_dir, 'template.html'), 'r').read()
|
||||
|
||||
# Copy static files
|
||||
# for static in ['css', 'js', 'img']:
|
||||
# source = os.path.join(docs_dir, 'static', static)
|
||||
# target = os.path.join(html_dir, static)
|
||||
# if os.path.exists(target):
|
||||
# shutil.rmtree(target)
|
||||
# shutil.copytree(source, target)
|
||||
|
||||
|
||||
# Hacky, but what the hell, it'll do the job
|
||||
path_list = [
|
||||
'index.md',
|
||||
'tutorial/quickstart.md',
|
||||
'tutorial/1-serialization.md',
|
||||
'tutorial/2-requests-and-responses.md',
|
||||
'tutorial/3-class-based-views.md',
|
||||
'tutorial/4-authentication-and-permissions.md',
|
||||
'tutorial/5-relationships-and-hyperlinked-apis.md',
|
||||
'tutorial/6-viewsets-and-routers.md',
|
||||
'api-guide/requests.md',
|
||||
'api-guide/responses.md',
|
||||
'api-guide/views.md',
|
||||
'api-guide/generic-views.md',
|
||||
'api-guide/viewsets.md',
|
||||
'api-guide/routers.md',
|
||||
'api-guide/parsers.md',
|
||||
'api-guide/renderers.md',
|
||||
'api-guide/serializers.md',
|
||||
'api-guide/fields.md',
|
||||
'api-guide/relations.md',
|
||||
'api-guide/validators.md',
|
||||
'api-guide/authentication.md',
|
||||
'api-guide/permissions.md',
|
||||
'api-guide/throttling.md',
|
||||
'api-guide/filtering.md',
|
||||
'api-guide/pagination.md',
|
||||
'api-guide/content-negotiation.md',
|
||||
'api-guide/format-suffixes.md',
|
||||
'api-guide/reverse.md',
|
||||
'api-guide/exceptions.md',
|
||||
'api-guide/status-codes.md',
|
||||
'api-guide/testing.md',
|
||||
'api-guide/settings.md',
|
||||
'topics/documenting-your-api.md',
|
||||
'topics/ajax-csrf-cors.md',
|
||||
'topics/browser-enhancements.md',
|
||||
'topics/browsable-api.md',
|
||||
'topics/rest-hypermedia-hateoas.md',
|
||||
'topics/third-party-resources.md',
|
||||
'topics/contributing.md',
|
||||
'topics/rest-framework-2-announcement.md',
|
||||
'topics/2.2-announcement.md',
|
||||
'topics/2.3-announcement.md',
|
||||
'topics/2.4-announcement.md',
|
||||
'topics/release-notes.md',
|
||||
'topics/credits.md',
|
||||
]
|
||||
|
||||
prev_url_map = {}
|
||||
next_url_map = {}
|
||||
for idx in range(len(path_list)):
|
||||
path = path_list[idx]
|
||||
rel = '../' * path.count('/')
|
||||
|
||||
if idx == 1 and not local:
|
||||
# Link back to '/', not '/index'
|
||||
prev_url_map[path] = '/'
|
||||
elif idx > 0:
|
||||
prev_url_map[path] = rel + path_list[idx - 1][:-3] + suffix
|
||||
|
||||
if idx < len(path_list) - 1:
|
||||
next_url_map[path] = rel + path_list[idx + 1][:-3] + suffix
|
||||
|
||||
|
||||
for (dirpath, dirnames, filenames) in os.walk(docs_dir):
|
||||
relative_dir = dirpath.replace(docs_dir, '').lstrip(os.path.sep)
|
||||
build_dir = os.path.join(html_dir, relative_dir)
|
||||
|
||||
if not os.path.exists(build_dir):
|
||||
os.makedirs(build_dir)
|
||||
|
||||
for filename in filenames:
|
||||
path = os.path.join(dirpath, filename)
|
||||
relative_path = os.path.join(relative_dir, filename)
|
||||
|
||||
if not filename.endswith('.md'):
|
||||
if relative_dir:
|
||||
output_path = os.path.join(build_dir, filename)
|
||||
shutil.copy(path, output_path)
|
||||
continue
|
||||
|
||||
output_path = os.path.join(build_dir, filename[:-3] + '.html')
|
||||
|
||||
toc = ''
|
||||
text = open(path, 'r').read().decode('utf-8')
|
||||
main_title = None
|
||||
description = 'Django, API, REST'
|
||||
for line in text.splitlines():
|
||||
if line.startswith('# '):
|
||||
title = line[2:].strip()
|
||||
template = main_header
|
||||
description = description + ', ' + title
|
||||
elif line.startswith('## '):
|
||||
title = line[3:].strip()
|
||||
template = sub_header
|
||||
else:
|
||||
continue
|
||||
|
||||
if not main_title:
|
||||
main_title = title
|
||||
anchor = title.lower().replace(' ', '-').replace(':-', '-').replace("'", '').replace('?', '').replace('.', '')
|
||||
template = template.replace('{{ title }}', title)
|
||||
template = template.replace('{{ anchor }}', anchor)
|
||||
toc += template + '\n'
|
||||
|
||||
if filename == 'index.md':
|
||||
main_title = 'Django REST framework - Web APIs for Django'
|
||||
else:
|
||||
main_title = main_title + ' - Django REST framework'
|
||||
|
||||
if relative_path == 'index.md':
|
||||
canonical_url = base_url
|
||||
else:
|
||||
canonical_url = base_url + '/' + relative_path[:-3] + suffix
|
||||
prev_url = prev_url_map.get(relative_path)
|
||||
next_url = next_url_map.get(relative_path)
|
||||
|
||||
content = markdown.markdown(text, ['headerid'])
|
||||
|
||||
output = page.replace('{{ content }}', content).replace('{{ toc }}', toc).replace('{{ base_url }}', base_url).replace('{{ suffix }}', suffix).replace('{{ index }}', index)
|
||||
output = output.replace('{{ title }}', main_title)
|
||||
output = output.replace('{{ description }}', description)
|
||||
output = output.replace('{{ page_id }}', filename[:-3])
|
||||
output = output.replace('{{ canonical_url }}', canonical_url)
|
||||
|
||||
if filename =='index.md':
|
||||
output = output.replace('{{ ad_block }}', """<hr/>
|
||||
<script type="text/javascript" src="//cdn.fusionads.net/fusion.js?zoneid=1332&serve=C6SDP2Y&placement=djangorestframework" id="_fusionads_js"></script>""")
|
||||
else:
|
||||
output = output.replace('{{ ad_block }}', '')
|
||||
|
||||
if prev_url:
|
||||
output = output.replace('{{ prev_url }}', prev_url)
|
||||
output = output.replace('{{ prev_url_disabled }}', '')
|
||||
else:
|
||||
output = output.replace('{{ prev_url }}', '#')
|
||||
output = output.replace('{{ prev_url_disabled }}', 'disabled')
|
||||
|
||||
if next_url:
|
||||
output = output.replace('{{ next_url }}', next_url)
|
||||
output = output.replace('{{ next_url_disabled }}', '')
|
||||
else:
|
||||
output = output.replace('{{ next_url }}', '#')
|
||||
output = output.replace('{{ next_url_disabled }}', 'disabled')
|
||||
|
||||
output = re.sub(r'a href="([^"]*)\.md"', r'a href="\1%s"' % suffix, output)
|
||||
output = re.sub(r'<pre><code>:::bash', r'<pre class="prettyprint lang-bsh">', output)
|
||||
output = re.sub(r'<pre>', r'<pre class="prettyprint lang-py">', output)
|
||||
output = re.sub(r'<a class="github" href="([^"]*)"></a>', code_label, output)
|
||||
open(output_path, 'w').write(output.encode('utf-8'))
|
||||
|
||||
if preview:
|
||||
import subprocess
|
||||
|
||||
url = 'html/index.html'
|
||||
|
||||
try:
|
||||
subprocess.Popen(["open", url]) # Mac
|
||||
except OSError:
|
||||
subprocess.Popen(["xdg-open", url]) # Linux
|
||||
except:
|
||||
os.startfile(url) # Windows
|
57
mkdocs.yml
Normal file
57
mkdocs.yml
Normal file
|
@ -0,0 +1,57 @@
|
|||
site_name: Django REST framework
|
||||
site_url: http://www.django-rest-framework.org/
|
||||
site_description: Django REST framework - Web APIs for Django
|
||||
|
||||
repo_url: https://github.com/tomchristie/django-rest-framework
|
||||
|
||||
theme_dir: docs_theme
|
||||
|
||||
pages:
|
||||
- ['index.md', 'Home']
|
||||
- ['tutorial/quickstart.md', 'Quickstart']
|
||||
- ['tutorial/1-serialization.md', 'Tutorial', '1 - Serialization']
|
||||
- ['tutorial/2-requests-and-responses.md', 'Tutorial', '2 - Requests and responses']
|
||||
- ['tutorial/3-class-based-views.md', 'Tutorial', '3 - Class based views']
|
||||
- ['tutorial/4-authentication-and-permissions.md', 'Tutorial', '4 - Authentication and permissions']
|
||||
- ['tutorial/5-relationships-and-hyperlinked-apis.md', 'Tutorial', '5 - Relationships and hyperlinked APIs']
|
||||
- ['tutorial/6-viewsets-and-routers.md', 'Tutorial', '6 - Viewsets and routers']
|
||||
- ['api-guide/requests.md', 'API Guide', 'Requests']
|
||||
- ['api-guide/responses.md', 'API Guide', 'Responses']
|
||||
- ['api-guide/views.md', 'API Guide', 'Views']
|
||||
- ['api-guide/generic-views.md', 'API Guide', 'Generic views']
|
||||
- ['api-guide/viewsets.md', 'API Guide', 'Viewsets']
|
||||
- ['api-guide/routers.md', 'API Guide', 'Routers']
|
||||
- ['api-guide/parsers.md', 'API Guide', 'Parsers']
|
||||
- ['api-guide/renderers.md', 'API Guide', 'Renderers']
|
||||
- ['api-guide/serializers.md', 'API Guide', 'Serializers']
|
||||
- ['api-guide/fields.md', 'API Guide', 'Serializer fields']
|
||||
- ['api-guide/relations.md', 'API Guide', 'Serializer relations']
|
||||
# - ['api-guide/validators.md', 'API Guide', 'Validators']
|
||||
- ['api-guide/authentication.md', 'API Guide', 'Authentication']
|
||||
- ['api-guide/permissions.md', 'API Guide', 'Permissions']
|
||||
- ['api-guide/throttling.md', 'API Guide', 'Throttling']
|
||||
- ['api-guide/filtering.md', 'API Guide', 'Filtering']
|
||||
- ['api-guide/pagination.md', 'API Guide', 'Pagination']
|
||||
- ['api-guide/content-negotiation.md', 'API Guide', 'Content negotiation']
|
||||
- ['api-guide/format-suffixes.md', 'API Guide', 'Format suffixes']
|
||||
- ['api-guide/reverse.md', 'API Guide', 'Returning URLs']
|
||||
- ['api-guide/exceptions.md', 'API Guide', 'Exceptions']
|
||||
- ['api-guide/status-codes.md', 'API Guide', 'Status codes']
|
||||
- ['api-guide/testing.md', 'API Guide', 'Testing']
|
||||
- ['api-guide/settings.md', 'API Guide', 'Settings']
|
||||
- ['topics/documenting-your-api.md', 'Topics', 'Documenting your API']
|
||||
- ['topics/ajax-csrf-cors.md', 'Topics', 'AJAX, CSRF & CORS']
|
||||
- ['topics/browser-enhancements.md', 'Topics',]
|
||||
- ['topics/browsable-api.md', 'Topics', 'The Browsable API']
|
||||
- ['topics/rest-hypermedia-hateoas.md', 'Topics', 'REST, Hypermedia & HATEOAS']
|
||||
- ['topics/third-party-resources.md', 'Topics', 'Third Party Resources']
|
||||
- ['topics/contributing.md', 'Topics', 'Contributing to REST framework']
|
||||
- ['topics/rest-framework-2-announcement.md', 'Topics', '2.0 Announcement']
|
||||
- ['topics/2.2-announcement.md', 'Topics', '2.2 Announcement']
|
||||
- ['topics/2.3-announcement.md', 'Topics', '2.3 Announcement']
|
||||
- ['topics/2.4-announcement.md', 'Topics', '2.4 Announcement']
|
||||
- ['topics/kickstarter-announcement.md', 'Topics', 'Kickstarter Announcement']
|
||||
- ['topics/release-notes.md', 'Topics', 'Release Notes']
|
||||
- ['topics/credits.md', 'Topics', 'Credits']
|
||||
|
||||
google_analytics: ['UA-18852272-2', 'django-rest-framework.org']
|
|
@ -9,7 +9,7 @@ from django.test import TestCase
|
|||
from django.utils import six, unittest
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import status, permissions
|
||||
from rest_framework.compat import yaml, etree, StringIO
|
||||
from rest_framework.compat import yaml, etree, StringIO, BytesIO
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
|
||||
|
@ -467,7 +467,7 @@ if yaml:
|
|||
obj = {'foo': ['bar', 'baz']}
|
||||
renderer = YAMLRenderer()
|
||||
content = renderer.render(obj, 'application/yaml')
|
||||
self.assertEqual(content, _yaml_repr)
|
||||
self.assertEqual(content.decode('utf-8'), _yaml_repr)
|
||||
|
||||
def test_render_and_parse(self):
|
||||
"""
|
||||
|
@ -480,7 +480,7 @@ if yaml:
|
|||
parser = YAMLParser()
|
||||
|
||||
content = renderer.render(obj, 'application/yaml')
|
||||
data = parser.parse(StringIO(content))
|
||||
data = parser.parse(BytesIO(content))
|
||||
self.assertEqual(obj, data)
|
||||
|
||||
def test_render_decimal(self):
|
||||
|
@ -489,7 +489,7 @@ if yaml:
|
|||
"""
|
||||
renderer = YAMLRenderer()
|
||||
content = renderer.render({'field': Decimal('111.2')}, 'application/yaml')
|
||||
self.assertYAMLContains(content, "field: '111.2'")
|
||||
self.assertYAMLContains(content.decode('utf-8'), "field: '111.2'")
|
||||
|
||||
def assertYAMLContains(self, content, string):
|
||||
self.assertTrue(string in content, '%r not in %r' % (string, content))
|
||||
|
|
Loading…
Reference in New Issue
Block a user