This commit is contained in:
Bruno Alla 2026-02-17 17:28:38 +01:00 committed by GitHub
commit 6a2b0bde79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 236 additions and 7681 deletions

3
.gitignore vendored
View File

@ -1,7 +1,6 @@
*.pyc
*.db
*~
.*
*.py.bak
@ -14,6 +13,8 @@
/env/
MANIFEST
coverage.*
.coverage
.cache/
!.github
!.gitignore

19
.readthedocs.yaml Normal file
View File

@ -0,0 +1,19 @@
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version, and other tools you might need
build:
os: ubuntu-24.04
tools:
python: "3.13"
jobs:
install:
- pip install --upgrade pip
- pip install -e . --group docs
# Build documentation with Mkdocs
mkdocs:
configuration: mkdocs.yml

BIN
docs/img/logo-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/img/logo-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@ -17,7 +17,7 @@
}
</style>
<p class="badges" height=20px>
<div class="badges">
<iframe src="https://ghbtns.com/github-btn.html?user=encode&amp;repo=django-rest-framework&amp;type=watch&amp;count=true" class="github-star-button" allowtransparency="true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe>
<a href="https://github.com/encode/django-rest-framework/actions/workflows/main.yml">
@ -27,11 +27,10 @@
<a href="https://pypi.org/project/djangorestframework/">
<img src="https://img.shields.io/pypi/v/djangorestframework.svg" class="status-badge">
</a>
</p>
</div>
---
<p>
<h1 style="position: absolute;
width: 1px;
height: 1px;
@ -41,8 +40,8 @@
clip: rect(0,0,0,0);
border: 0;">Django REST Framework</h1>
<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](img/logo-light.png#only-light)
![Django REST Framework](img/logo-dark.png#only-dark)
Django REST framework is a powerful and flexible toolkit for building Web APIs.
@ -79,27 +78,35 @@ The following packages are optional:
Install using `pip`, including any optional packages you want...
pip install djangorestframework
pip install markdown # Markdown support for the browsable API.
pip install django-filter # Filtering support
```bash
pip install djangorestframework
pip install markdown # Markdown support for the browsable API.
pip install django-filter # Filtering support
```
...or clone the project from github.
git clone https://github.com/encode/django-rest-framework
```bash
git clone https://github.com/encode/django-rest-framework
```
Add `'rest_framework'` to your `INSTALLED_APPS` setting.
INSTALLED_APPS = [
...
'rest_framework',
]
```python
INSTALLED_APPS = [
# ...
"rest_framework",
]
```
If you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views. Add the following to your root `urls.py` file.
urlpatterns = [
...
path('api-auth/', include('rest_framework.urls'))
]
```python
urlpatterns = [
# ...
path("api-auth/", include("rest_framework.urls"))
]
```
Note that the URL path can be whatever you want.
@ -111,44 +118,51 @@ We'll create a read-write API for accessing information on the users of our proj
Any global settings for a REST framework API are kept in a single configuration dictionary named `REST_FRAMEWORK`. Start off by adding the following to your `settings.py` module:
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
```python
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly"
]
}
```
Don't forget to make sure you've also added `rest_framework` to your `INSTALLED_APPS`.
We're ready to create our API now.
Here's our project's root `urls.py` module:
from django.urls import path, include
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets
```python
from django.urls import path, include
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets
# Serializers define the API representation.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'is_staff']
# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# Serializers define the API representation.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ["url", "username", "email", "is_staff"]
# Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r"users", UserViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path("", include(router.urls)),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
]
```
You can now open the API in your browser at [http://127.0.0.1:8000/](http://127.0.0.1:8000/), and view your new 'users' API. If you use the login control in the top right corner you'll also be able to add, create and delete users from the system.

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
docs/theme/img/logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

13
docs/theme/main.html vendored Normal file
View File

@ -0,0 +1,13 @@
{% extends "base.html" %}
{% block scripts %}
{{ super() }}
<script>
document$.subscribe(function() {
document.querySelectorAll('pre code').forEach(code => {
code.parentElement.classList.add('prettyprint', 'well');
});
prettyPrint();
});
</script>
{% endblock %}

81
docs/theme/stylesheets/extra.css vendored Normal file
View File

@ -0,0 +1,81 @@
:root > * {
/* primary */
--md-primary-fg-color: #2c2c2c;
--md-primary-fg-color--light: #a8a8a8;
--md-primary-fg-color--dark: #181818;
/* accent */
--md-accent-fg-color: #c50d0d;
--md-accent-fg-color--light: #ff8f8f;
--md-accent-fg-color--dark: #A30000;
/* Style links */
--md-typeset-a-color: var(--md-typeset-color);
}
/* Dark theme customisation */
[data-md-color-scheme="slate"]
{}
.md-header {
border-top: 5px solid var(--md-accent-fg-color--dark);
}
body hr {
border-top: 1px dotted var(--md-accent-fg-color--dark);
}
.badges {
display: flex;
flex-direction: row-reverse;
align-content: end;
gap: 8px;
}
/* Cutesy quote styling */
[dir="ltr"] .md-typeset 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: var(--md-typeset-color);
border-left: none;
}
[dir="ltr"] .md-typeset blockquote:before {
display: block;
content: "\201C";
font-size: 80px;
position: absolute;
left: -10px;
top: -20px;
color: #7a7a7a;
}
[dir="ltr"] .md-typeset blockquote p:last-child {
color: #999999;
font-size: 14px;
display: block;
margin-top: 5px;
}
.md-typeset a {
color: var(--md-accent-fg-color--dark);
}
/* Replacement for `body { background-attachment: fixed; }`, which
has performance issues when scrolling on large displays. */
body::before {
content: ' ';
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: #f8f8f8;
background: url(../img/grid.png) repeat-x;
will-change: transform;
z-index: -1;
}

View File

@ -7,6 +7,16 @@
.typ, .atn, .dec, .var { color: teal; }
.pln { color: #48484c; }
[data-md-color-scheme="slate"]
{
.com { color: #687272; }
.lit { color: #2481c7; }
.str, .atv { color: #e02642; }
.kwd, .prettyprint .tag { color: #5b7acb; }
.typ, .atn, .dec, .var { color: #05abab; }
.pln { color: #d3d3dc; }
}
.prettyprint {
padding: 8px;
background-color: #f7f7f9;

View File

@ -1,9 +0,0 @@
{% extends "main.html" %}
{% block content %}
<h1 id="404-page-not-found" style="text-align: center">404</h1>
<p style="text-align: center"><strong>Page not found</strong></p>
<p style="text-align: center">Try the <a href="{{ base_url }}">homepage</a>, or <a href="#mkdocs_search_modal" data-toggle="modal">search the documentation</a>.</p>
{% endblock %}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +0,0 @@
.copy-block-button {
position: absolute;
top: 6px;
right: 6px;
z-index: 10;
white-space: nowrap; /* Prevent text wrap */
}
/* Ensure the PRE container provides positioning context */
pre {
position: relative;
padding-top: 35px; /* Room for the button */
overflow-x: auto; /* Allow horizontal scrolling */
}
/* Code block scrollable */
pre code {
display: block;
overflow-x: auto;
}
/*
The MkDocs/DRF theme injects a <span> inside buttons and applies
a text color that overrides btn-inverse defaults.
This override is intentionally scoped and limited to color only.
*/
.copy-block-button,
.copy-block-button span {
color: #ffffff !important;
}

View File

@ -1,473 +0,0 @@
/* Set the body padding-top when above 980px to push the content down from
below the navbar, which is fixed at >980px screen widths. */
pre {
font-size: 12px;
}
.dropdown .dropdown-menu {
display: none;
overflow-y: auto;
}
.dropdown.open .dropdown-menu {
display: block;
}
@media (max-width: 480px) {
.repo-link {
display: none;
}
}
/* Header link to GitHub */
.repo-link {
float: right;
margin-right: 10px;
margin-top: 9px;
}
body.index-page #main-content p.badges {
padding-bottom: 1px;
}
/* GitHub 'Star' badge */
body.index-page #main-content iframe.github-star-button {
float: right;
margin-top: -12px;
margin-right: -15px;
}
/* CI and PyPI badge */
body.index-page #main-content img.status-badge {
float: right;
margin-right: 8px;
margin-top: -11px;
margin-bottom: 0px;
}
/* Github source file badges */
a.github {
float: right;
margin-top: -12px;
margin-right: 12px;
}
a.github:hover {
text-decoration: none;
}
/* */
body hr {
border-top: 1px dotted #A30000;
}
/* Force TOC text to not overrun */
#table-of-contents {
overflow: hidden;
margin: 0 0 20px 0;
}
/* Code blocks should scroll horizontally */
pre {
overflow: auto;
word-wrap: normal;
white-space: pre;
}
code, pre {
font-family: Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif;
font-size: 13px;
}
/* Preserve the spacing of the navbar across different screen sizes. */
.navbar-inner {
/*padding: 5px 0;*/
}
@media (max-width: 979px) {
.navbar .brand {
margin-left: 0;
padding-left: 0;
}
.navbar-inner .container-fluid {
padding-left: 15px;
}
}
.nav-list li.main {
font-weight: bold;
}
.nav-list a {
overflow: hidden;
}
.nav-list > li > a {
padding: 2px 15px 3px;
}
/* Set the table of contents to static so it flows back into the content when
viewed on tablets and smaller. */
@media (max-width: 767px) {
#table-of-contents {
position: static;
}
}
/* When the page is in two-column layout, give the main content some room
to breath on the left. */
@media (min-width: 768px) {
#main-content {
padding-left: 1em;
}
}
/* Cutesy quote styling */
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;
}
/*=== dabapps bootstrap styles ====*/
html{
width:100%;
background: none;
}
body, .navbar .navbar-inner .container-fluid{
max-width: 1150px;
margin: 0 auto;
}
/* Replacement for `body { background-attachment: fixed; }`, which
has performance issues when scrolling on large displays. */
body::before {
content: ' ';
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: #f8f8f8;
background: url(../img/grid.png) repeat-x;
will-change: transform;
z-index: -1;
}
#main-content h1:first-of-type {
margin-top: 0
}
#main-content h1, #main-content h2 {
font-weight: 300;
margin-top: 20px
}
#main-content h3, #main-content h4, #main-content h5 {
font-weight: 300;
margin-top: 15px
}
#main-content img {
display: block;
margin: 40px auto;
}
/* custom navigation styles */
.navbar .navbar-inner{
background: #2C2C2C;
color: white;
border: none;
border-top: 5px solid #A30000;
}
.navbar .navbar-inner .nav li, .navbar .navbar-inner .nav li a, .navbar .navbar-inner .brand{
color: white;
}
.nav-list > .active > a, .navbar .navbar-inner .nav li a:hover {
background:#212121;
color:white;
}
.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;
}
/* custom general page styles */
.hero-unit h2, .hero-unit h1{
color: #A30000;
}
body a{
color: #A30000;
}
body a:hover{
color: #c20000;
}
/* subnavigation styles */
@media (min-width: 767px) {
.sidebar-nav-fixed {
position:fixed;
width:19%;
max-width: 240px;
}
.navbar {
position: fixed;
}
.navbar .navbar-inner .container-fluid{
max-width: 1110px;
}
}
h1 code, h2 code, h3 code, h4 code, h5 code {
color: #333;
}
/* sticky footer and footer */
html, body {
height: 100%;
}
.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -60px;
}
.body-content{
padding-top: 70px;
padding-bottom: 70px;
}
@media (max-width: 979px) {
.navbar-fixed-top .navbar-inner {
padding: 0px;
}
}
@media (max-width: 767px) {
.body-content{
padding-top: 0px;
}
}
@media (min-width: 768px) {
footer.span12 {
width: 95%;
}
}
footer, .push {
height: 60px; /* .push must be the same height as .footer */
}
footer p {
text-align: center;
color: gray;
border-top: 1px solid #DDD;
padding-top: 10px;
}
footer a {
color: gray;
font-weight: bold;
}
footer a:hover {
color: gray;
}
.btn-inverse {
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#606060), to(#404040)) !important;
background-image: -webkit-linear-gradient(top, #606060, #404040) !important;
}
.modal-open .modal,.btn:focus{outline:none;}
@media (max-width: 650px) {
.repo-link.btn-inverse {display: none;}
}
td, th {
padding: 0.25em;
background-color: #f7f7f9;
border-color: #e1e1e8;
}
table {
border-color: white;
margin-bottom: 0.6em;
}
.side-nav {
overflow-y: scroll;
}
ul.sponsor.diamond li a {
float: left;
width: 600px;
height: 20px;
text-align: center;
margin: 10px 70px;
padding: 300px 0 0 0;
background-position: 0 50%;
background-size: 600px auto;
background-repeat: no-repeat;
font-size: 200%;
}
@media (max-width: 1000px) {
ul.sponsor.diamond li a {
float: left;
width: 300px;
height: 20px;
text-align: center;
margin: 10px 40px;
padding: 300px 0 0 0;
background-position: 0 50%;
background-size: 280px auto;
background-repeat: no-repeat;
font-size: 150%;
}
}
ul.sponsor.platinum li a {
float: left;
width: 300px;
height: 20px;
text-align: center;
margin: 10px 40px;
padding: 300px 0 0 0;
background-position: 0 50%;
background-size: 280px auto;
background-repeat: no-repeat;
font-size: 150%;
}
ul.sponsor.gold li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
}
ul.sponsor.silver li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
}
ul.sponsor {
list-style: none;
display: block;
}
#mkdocs_search_modal article p{
word-wrap: break-word;
}
.toclink {
color: #333;
}
.book-cover img {
margin: 0 !important;
display: inline-block !important;
}
/* admonition */
.admonition {
border: .075rem solid #448aff;
border-radius: .2rem;
margin: 1.5625em 0;
padding: 0 .6rem;
}
.admonition-title {
background: #448aff1a;
font-weight: 700;
margin: 0 -.6rem 1em;
padding: 0.4rem 0.6rem;
}
.admonition.tip {
border: .075rem solid #1e8d21;
}
.admonition.tip .admonition-title {
background: #1e8d211a;
}
.admonition.warning {
border: .075rem solid #ff9844;
}
.admonition.warning .admonition-title {
background: #ff98441a;
}
.admonition.danger {
border: .075rem solid #f63a3a;
}
.admonition.danger .admonition-title {
background: #f63a3a1a;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,24 +0,0 @@
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll("pre > code").forEach(function (codeBlock) {
const button = document.createElement("button");
button.className = "copy-block-button btn btn-inverse btn-mini";
button.type = "button";
button.textContent = "Copy";
button.addEventListener("click", function () {
navigator.clipboard.writeText(codeBlock.textContent)
.then(() => {
button.textContent = "Copied!";
setTimeout(() => button.textContent = "Copy", 1200);
})
.catch(() => {
button.textContent = "Failed";
setTimeout(() => button.textContent = "Copy", 1200);
});
});
const pre = codeBlock.parentNode;
pre.style.position = "relative";
pre.appendChild(button);
});
});

File diff suppressed because one or more lines are too long

View File

@ -1,29 +0,0 @@
var getSearchTerm = function() {
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++) {
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === 'q') {
return sParameterName[1];
}
}
};
$(function() {
var searchTerm = getSearchTerm(),
$searchModal = $('#mkdocs_search_modal'),
$searchQuery = $searchModal.find('#mkdocs-search-query'),
$searchResults = $searchModal.find('#mkdocs-search-results');
$('pre code').parent().addClass('prettyprint well');
if (searchTerm) {
$searchQuery.val(searchTerm);
$searchResults.text('Searching...');
$searchModal.modal();
}
$searchModal.on('shown', function() {
$searchQuery.focus();
});
});

View File

@ -1,174 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>{% if page.title %}{{ page.title }} - {% endif %}{{ config.site_name }}</title>
<link href="{{ 'img/favicon.ico'|url }}" rel="icon" type="image/x-icon">
<link rel="canonical" href="{{ page.canonical_url|url }}" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Django, API, REST{% if page %}, {{ page.title }}{% endif %}">
<meta name="author" content="Tom Christie">
<!-- Le styles -->
<link href="{{ 'css/prettify.css'|url }}" rel="stylesheet">
<link href="{{ 'css/bootstrap.css'|url }}" rel="stylesheet">
<link href="{{ 'css/bootstrap-responsive.css'|url }}" rel="stylesheet">
<link href="{{ 'css/default.css'|url }}" rel="stylesheet">
{% for path in config.extra_css %}
<link href="{{ path|url }}" rel="stylesheet">
{% endfor %}
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-18852272-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#sidebarInclude img {
margin-bottom: 10px;
}
#sidebarInclude a.promo {
color: black;
}
@media (max-width: 767px) {
div.promo {
display: none;
}
}
</style>
</head>
<body onload="prettyPrint()" class="{% if page and page.is_homepage %}index{% endif %}-page">
<div class="wrapper">
{% include "nav.html" %}
<div class="body-content">
<div class="container-fluid">
<!-- Search Modal -->
<div id="mkdocs_search_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3 id="myModalLabel">Documentation search</h3>
</div>
<div class="modal-body">
<form role="form" autocomplete="off">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search..." id="mkdocs-search-query">
</div>
</form>
<div id="mkdocs-search-results"></div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<div id="table-of-contents">
<ul class="nav nav-list side-nav well sidebar-nav-fixed">
{% if page and page.is_homepage %}
<li class="main">
<a href="#">Django REST framework</a>
</li>
{% endif %}
{% for toc_item in page.toc %}
<li class="{% if page and not 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 %}
<div class="promo">
{% if page.toc %}<hr/>{% endif %}
<div id="sidebarInclude">
</div>
</ul>
</div>
</div>
<div id="main-content" class="span9">
{% block content %}
{% if page.meta.source %}
{% for filename in page.meta.source %}
<a class="github" href="https://github.com/encode/django-rest-framework/tree/main/rest_framework/{{ filename }}">
<span class="label label-info">{{ filename }}</span>
</a>
{% endfor %}
{% endif %}
{{ page.content }}
{% endblock %}
</div> <!--/span-->
</div> <!--/row-->
</div> <!--/.fluid-container-->
</div> <!--/.body content-->
<div id="push"></div>
</div> <!--/.wrapper -->
<footer class="span12">
<p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.
</p>
</footer>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script async src="https://fund.django-rest-framework.org/sidebar_include.js"></script>
<script src="{{ 'js/jquery-1.8.1-min.js'|url }}"></script>
<script src="{{ 'js/prettify-1.0.js'|url }}"></script>
<script src="{{ 'js/bootstrap-2.1.1-min.js'|url }}"></script>
<script src="{{ 'js/theme.js'|url }}"></script>
<script>var base_url = '{{ base_url }}';</script>
{% for path in config.extra_javascript %}
<script src="{{ path|url }}" defer></script>
{% endfor %}
<script>
var shiftWindow = function() {
scrollBy(0, -50)
};
if (location.hash) shiftWindow();
window.addEventListener("hashchange", shiftWindow);
$('.dropdown-menu').on('click touchstart', function(event) {
event.stopPropagation();
});
// Dynamically force sidenav/dropdown to no higher than browser window
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
$(function() {
$(window).resize(function() {
$('.side-nav, .dropdown-menu').css('max-height', window.innerHeight - 130);
});
});
</script>
</body>
</html>

View File

@ -1,46 +0,0 @@
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="repo-link btn btn-primary btn-small" href="https://github.com/encode/django-rest-framework">GitHub</a>
<a class="repo-link btn btn-inverse btn-small {% if not page.next_page %}disabled{% endif %}" rel="next" {% if page.next_page %}href="{{ page.next_page.url|url }}"{% endif %}>
Next <i class="icon-arrow-right icon-white"></i>
</a>
<a class="repo-link btn btn-inverse btn-small {% if not page.previous_page %}disabled{% endif %}" rel="prev" {% if page.previous_page %}href="{{ page.previous_page.url|url }}"{% endif %}>
<i class="icon-arrow-left icon-white"></i> Previous
</a>
<a id="search_modal_show" class="repo-link btn btn-inverse btn-small" href="#mkdocs_search_modal" data-toggle="modal" data-target="#mkdocs_search_modal"><i class="icon-search icon-white"></i> Search</a>
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="https://www.django-rest-framework.org/">Django REST framework</a>
<div class="nav-collapse collapse">
{% if nav|length>1 %}
<!-- Main navigation -->
<ul class="nav navbar-nav">
{% 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|url }}">{{ nav_item.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li {% if nav_item.active %}class="active" {% endif %}>
<a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
</li>
{% endif %} {% endfor %}
</ul>
{% endif %}
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>

View File

@ -5,13 +5,61 @@ site_description: Django REST framework - Web APIs for Django
repo_url: https://github.com/encode/django-rest-framework
theme:
name: mkdocs
custom_dir: docs_theme
name: material
custom_dir: docs/theme
favicon: theme/img/favicon.ico
logo: theme/img/logo.png
palette:
- media: "(prefers-color-scheme)"
primary: custom
accent: custom
toggle:
icon: material/brightness-auto
name: "Switch to light mode"
- media: "(prefers-color-scheme: light)"
scheme: default
primary: custom
accent: custom
toggle:
icon: material/brightness-7
name: "Switch to dark mode"
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: custom
accent: custom
toggle:
icon: material/brightness-4
name: "Switch to system preference"
features:
- content.tabs.link
- content.code.annotate
- content.code.copy
- navigation.tabs
- navigation.instant
- navigation.instant.prefetch
- navigation.instant.progress
- navigation.path
- navigation.sections
- navigation.top
- navigation.tracking
- search.suggest
- toc.follow
extra_css:
- theme/stylesheets/extra.css
- theme/stylesheets/prettify.css
extra_javascript:
- theme/js/prettify-1.0.js
markdown_extensions:
- admonition
- toc:
anchorlink: True
permalink: true
- pymdownx.highlight:
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
nav:
- Home: 'index.md'
@ -86,9 +134,3 @@ nav:
- 'Kickstarter Announcement': 'community/kickstarter-announcement.md'
- 'Mozilla Grant': 'community/mozilla-grant.md'
- 'Jobs': 'community/jobs.md'
extra_css:
- css/copy-button.css
extra_javascript:
- js/copy-button.js

View File

@ -57,6 +57,7 @@ test = [
docs = [
# MkDocs to build our documentation.
"mkdocs==1.6.1",
"mkdocs-material[imaging]==9.7.0",
# pylinkvalidator to check for broken links in documentation.
"pylinkvalidator==0.3",
]