模板標(biāo)簽除了幾個(gè)常用的,還真心沒有仔細(xì)了解一下齐苛,看到2.0發(fā)布后翘盖,翻譯學(xué)習(xí)一下。
本文盡量忠實(shí)原著凹蜂,畢竟大神的東西不好褻瀆馍驯。翻譯中我盡量加入自己做項(xiàng)目時(shí)候經(jīng)驗(yàn),不至于翻譯出來不是人類能讀的玛痊。
一泥彤、模板介紹
作為鼎鼎大名的網(wǎng)絡(luò)框架,Django不能很方便的動(dòng)態(tài)生成HTML卿啡,它還好意思出門吟吝?最普通的方式就是依靠模板來動(dòng)態(tài)生成。模板主要包括兩個(gè)內(nèi)容颈娜,一是包含了HTML輸出的靜態(tài)部分剑逃,二是怎么樣插入動(dòng)態(tài)內(nèi)容的語(yǔ)法浙宜。在教程的第三部分中有一個(gè)例子就是用模板生成HTML網(wǎng)頁(yè)的,有興趣可以去參考一下蛹磺。
一個(gè)Django 工程一般配置一個(gè)或者幾個(gè)模板引擎粟瞬,如果你不用模板,當(dāng)然可以沒有萤捆。Django自帶自己獨(dú)創(chuàng)的叫DTL的引擎裙品,作為自己模板系統(tǒng)的后端。當(dāng)然也支持流行的Jinja2引擎俗或。如果你要用其他第三方的引擎市怎,稍加配置后端也支持。
無論那種后端引擎辛慰,Django提供了一套標(biāo)準(zhǔn)的API來加載和渲染模板区匠。所謂的加載包括兩步,首先找到你指定的模板帅腌,然后預(yù)處理一下驰弄,一般就是編譯一下放到內(nèi)存里備用。所謂的渲染也包括兩步速客,首先把環(huán)境變量的數(shù)據(jù)插入到模板中戚篙,然后返回一個(gè)結(jié)果字符串。
DTL是Django自己的模板系統(tǒng)溺职,在1.8版本以前它僅僅是可選的岔擂。以后就默認(rèn)內(nèi)置了。Django的開發(fā)大神們相當(dāng)?shù)目春盟ㄔ福梢悦霘⑵渌0逭Z(yǔ)言智亮。大神這么推崇的模板忆某,如果你沒有特別理由点待,建議用DTL吧。特別是你想開發(fā)一個(gè)可以隨時(shí)加入插件的應(yīng)用并且要發(fā)布他的時(shí)候弃舒。Django自帶的像django.contrib.admin的管理后臺(tái)就是用的DTL 模板癞埠。
歷史原因,模板引擎和模板語(yǔ)言都在django.template的模塊中
警告聋呢!
模板系統(tǒng)對(duì)惡意模板沒有反制措施苗踪。所以網(wǎng)站不要允許用戶提供自己的模板,惡意的用戶有可能會(huì)實(shí)施XSS攻擊削锰,獲取模板中的隱私數(shù)據(jù)
二通铲、對(duì)模板引擎的支持
2.1模板引擎的設(shè)置
模板引擎在TEMPLATES設(shè)置中配置。對(duì)每個(gè)引擎的配置就是一個(gè)字典器贩。默認(rèn)是空的颅夺。如果你用startproject命令來生成你的工程朋截,在setting.py中會(huì)默認(rèn)提供一點(diǎn)有用的配置。
TEMPLATES = [
? ? {
? ? ? ? 'BACKEND': 'django.template.backends.django.DjangoTemplates',
? ? ? ? 'DIRS': [],
? ? ? ? 'APP_DIRS': True,
? ? ? ? 'OPTIONS': {
? ? ? ? ? ? # ... some options here ...
? ? ? ? },
? ? },
]
后端這個(gè)鍵值是個(gè)python路徑吧黄,它指向了一個(gè)模板引擎的類部服,這個(gè)類實(shí)現(xiàn)了模本后端的API。自帶的后端引擎類是django.template.backend.django.DjangoTemplate和django.template.bakend.jinja2.Jinja2
一般來說拗慨,引擎是從文件中載入模板廓八,所以頂級(jí)配置中為每個(gè)引擎提供了兩個(gè)通用設(shè)置選項(xiàng)
DIRS定義了引擎搜索模板源文件的一系列文件夾。搜索的時(shí)候是按照你提供的文件夾的順序來搜索的赵抢。
APP_DIRS是告訴引擎你要在安裝的應(yīng)用中搜索模板剧蹂。每個(gè)后端為應(yīng)用存儲(chǔ)模板的下層文件夾提供了通用的名字。
OPTIONS昌讲。特殊情況下国夜,你可以為相同的后端用不同的選項(xiàng)值來配置不同的后端實(shí)例。這種情況下短绸,你要為每個(gè)引擎提供獨(dú)特的名字车吹。OPTIONS 就是設(shè)置后端特殊值的地方
2.2模板的使用
django.template.loader模塊里有兩個(gè)函數(shù)來加載模板
get_template(template_name, using=None)
這個(gè)函數(shù)用指定的模板名字來加載模本,返回一個(gè)模板對(duì)象
不同的后端加載模板后返回的模板對(duì)象是不同的醋闭,每個(gè)后端都有自己的模板類窄驹。
get_template()會(huì)按順序嘗試模板引擎,直到成功证逻。注:引擎是自帶的不會(huì)拋出異常乐埠。如果模板沒有找到就拋出TemplateDoesNotExist的異常,如果找到模板囚企,但是模板里面有語(yǔ)法錯(cuò)誤丈咐,就拋出TemplateSyntaxError的異常。
怎么搜索模板以及怎么加載模板龙宏?每個(gè)引擎后端不同棵逊,方式也不同,相同的引擎后端因?yàn)榕渲貌煌铮矔?huì)有差別辆影。
如果你想限制在搜索某個(gè)引擎,你可以給引擎的NAME變量賦值
select_template(template_name_list, using=None)
select_template() 和get_template()類似黍特,不同之處在于它的參數(shù)是一個(gè)模板名字的列表蛙讥。這個(gè)方法蔣按順序搜索每一個(gè)名字,搜索到一個(gè)符合就停止灭衷,返回模板對(duì)象次慢。
如果加載模板失敗,會(huì)拋出下面兩個(gè)異常,這兩個(gè)異常實(shí)在django.temolate定義好的迫像。
exception TemplateDoesNotExist(msg, tried=None, backend=None, chain=None)
沒有找到匹配的模板會(huì)拋出這個(gè)異常拭抬。在調(diào)試頁(yè)面它會(huì)用下面這些參數(shù)來填充模板
參數(shù) backend
產(chǎn)生這個(gè)異常的模板后端實(shí)例。實(shí)際就是那個(gè)引擎
參數(shù)tried
在尋找模板的時(shí)候都尋找了那些目錄侵蒙。調(diào)試頁(yè)面會(huì)以tuple的形式展示出來造虎,這個(gè)tuple包含原始的文件目錄和狀態(tài)。 (origin, status)纷闺,origin是一個(gè)原始樣子的對(duì)象算凿,status是一個(gè)字符串,內(nèi)容找不到模板的原因
參數(shù)chain
加載模板時(shí)一系列中間TemplateDoesNotExist異常犁功,一般發(fā)生在用多個(gè)引擎加載模板的時(shí)候氓轰,如在get_template方法中
exception TemplateSyntaxError(msg)
This exception is raised when a template was found but contains errors.
Template objects returned by get_template() and select_template() must provide a render() method with the following signature:
Template.render(context=None, request=None)?
Renders this template with a given context.
If context is provided, it must be a dict. If it isn’t provided, the engine will render the template with an empty context.
If request is provided, it must be an HttpRequest. Then the engine must make it, as well as the CSRF token, available in the template. How this is achieved is up to each backend.
Here’s an example of the search algorithm. For this example the TEMPLATES setting is:
TEMPLATES = [
? ? {
? ? ? ? 'BACKEND': 'django.template.backends.django.DjangoTemplates',
? ? ? ? 'DIRS': [
? ? ? ? ? ? '/home/html/example.com',
? ? ? ? ? ? '/home/html/default',
? ? ? ? ],
? ? },
? ? {
? ? ? ? 'BACKEND': 'django.template.backends.jinja2.Jinja2',
? ? ? ? 'DIRS': [
? ? ? ? ? ? '/home/html/jinja2',
? ? ? ? ],
? ? },
]
If you call get_template('story_detail.html'), here are the files Django will look for, in order:
/home/html/example.com/story_detail.html ('django' engine)
/home/html/default/story_detail.html ('django' engine)
/home/html/jinja2/story_detail.html ('jinja2' engine)
If you call select_template(['story_253_detail.html', 'story_detail.html']), here’s what Django will look for:
/home/html/example.com/story_253_detail.html ('django' engine)
/home/html/default/story_253_detail.html ('django' engine)
/home/html/jinja2/story_253_detail.html ('jinja2' engine)
/home/html/example.com/story_detail.html ('django' engine)
/home/html/default/story_detail.html ('django' engine)
/home/html/jinja2/story_detail.html ('jinja2' engine)
When Django finds a template that exists, it stops looking.
Tip
You can use select_template() for flexible template loading. For example, if you’ve written a news story and want some stories to have custom templates, use something like select_template(['story_%s_detail.html' % story.id, 'story_detail.html']). That’ll allow you to use a custom template for an individual story, with a fallback template for stories that don’t have custom templates.
It’s possible – and preferable – to organize templates in subdirectories inside each directory containing templates. The convention is to make a subdirectory for each Django app, with subdirectories within those subdirectories as needed.
Do this for your own sanity. Storing all templates in the root level of a single directory gets messy.
To load a template that’s within a subdirectory, just use a slash, like so:
get_template('news/story_detail.html')
Using the same TEMPLATES option as above, this will attempt to load the following templates:
/home/html/example.com/news/story_detail.html ('django' engine)
/home/html/default/news/story_detail.html ('django' engine)
/home/html/jinja2/news/story_detail.html ('jinja2' engine)
In addition, to cut down on the repetitive nature of loading and rendering templates, Django provides a shortcut function which automates the process.
render_to_string(template_name, context=None, request=None, using=None)[source]?
render_to_string() loads a template like get_template() and calls its render() method immediately. It takes the following arguments.
template_name
The name of the template to load and render. If it’s a list of template names, Django uses select_template() instead of get_template() to find the template.
context
A dict to be used as the template’s context for rendering.
request
An optional HttpRequest that will be available during the template’s rendering process.
using
An optional template engine NAME. The search for the template will be restricted to that engine.
Usage example:
from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', {'foo': 'bar'})
See also the render() shortcut which calls render_to_string() and feeds the result into an HttpResponse suitable for returning from a view.
Finally, you can use configured engines directly:
engines?
Template engines are available in django.template.engines:
from django.template import engines
django_engine = engines['django']
template = django_engine.from_string("Hello {{ name }}!")
The lookup key — 'django' in this example — is the engine’s NAME.
Built-in backends?
class DjangoTemplates[source]?
Set BACKEND to 'django.template.backends.django.DjangoTemplates' to configure a Django template engine.
When APP_DIRS is True, DjangoTemplates engines look for templates in the templates subdirectory of installed applications. This generic name was kept for backwards-compatibility.
DjangoTemplates engines accept the following OPTIONS:
'autoescape': a boolean that controls whether HTML autoescaping is enabled.
It defaults to True.
Warning
Only set it to False if you’re rendering non-HTML templates!
'context_processors': a list of dotted Python paths to callables that are used to populate the context when a template is rendered with a request. These callables take a request object as their argument and return a dict of items to be merged into the context.
It defaults to an empty list.
See RequestContext for more information.
'debug': a boolean that turns on/off template debug mode. If it is True, the fancy error page will display a detailed report for any exception raised during template rendering. This report contains the relevant snippet of the template with the appropriate line highlighted.
It defaults to the value of the DEBUG setting.
'loaders': a list of dotted Python paths to template loader classes. Each Loader class knows how to import templates from a particular source. Optionally, a tuple can be used instead of a string. The first item in the tuple should be the Loader class name, and subsequent items are passed to the Loader during initialization.
The default depends on the values of DIRS and APP_DIRS.
See Loader types for details.
'string_if_invalid': the output, as a string, that the template system should use for invalid (e.g. misspelled) variables.
It defaults to an empty string.
See How invalid variables are handled for details.
'file_charset': the charset used to read template files on disk.
It defaults to the value of FILE_CHARSET.
'libraries': A dictionary of labels and dotted Python paths of template tag modules to register with the template engine. This can be used to add new libraries or provide alternate labels for existing ones. For example:
OPTIONS={
? ? 'libraries': {
? ? ? ? 'myapp_tags': 'path.to.myapp.tags',
? ? ? ? 'admin.urls': 'django.contrib.admin.templatetags.admin_urls',
? ? },
}
Libraries can be loaded by passing the corresponding dictionary key to the {% load %} tag.
'builtins': A list of dotted Python paths of template tag modules to add to built-ins. For example:
OPTIONS={
? ? 'builtins': ['myapp.builtins'],
}
Tags and filters from built-in libraries can be used without first calling the {% load %} tag.
class Jinja2[source]?
Requires Jinja2 to be installed:
$ pip install Jinja2
Set BACKEND to 'django.template.backends.jinja2.Jinja2' to configure a Jinja2 engine.
When APP_DIRS is True, Jinja2 engines look for templates in the jinja2 subdirectory of installed applications.
The most important entry in OPTIONS is 'environment'. It’s a dotted Python path to a callable returning a Jinja2 environment. It defaults to 'jinja2.Environment'. Django invokes that callable and passes other options as keyword arguments. Furthermore, Django adds defaults that differ from Jinja2’s for a few options:
'autoescape': True
'loader': a loader configured for DIRS and APP_DIRS
'auto_reload': settings.DEBUG
'undefined': DebugUndefined if settings.DEBUG else Undefined
Jinja2 engines also accept the following OPTIONS:
'context_processors': a list of dotted Python paths to callables that are used to populate the context when a template is rendered with a request. These callables take a request object as their argument and return a dict of items to be merged into the context.
It defaults to an empty list.
Using context processors with Jinja2 templates is discouraged.
Context processors are useful with Django templates because Django templates don’t support calling functions with arguments. Since Jinja2 doesn’t have that limitation, it’s recommended to put the function that you would use as a context processor in the global variables available to the template using jinja2.Environment as described below. You can then call that function in the template:
{{ function(request) }}
Some Django templates context processors return a fixed value. For Jinja2 templates, this layer of indirection isn’t necessary since you can add constants directly in jinja2.Environment.
The original use case for adding context processors for Jinja2 involved:
Making an expensive computation that depends on the request.
Needing the result in every template.
Using the result multiple times in each template.
Unless all of these conditions are met, passing a function to the template is simpler and more in line with the design of Jinja2.
New in Django 1.11:
The 'context_processors' option was added.
The default configuration is purposefully kept to a minimum. If a template is rendered with a request (e.g. when using render()), the Jinja2 backend adds the globals request, csrf_input, and csrf_token to the context. Apart from that, this backend doesn’t create a Django-flavored environment. It doesn’t know about Django filters and tags. In order to use Django-specific APIs, you must configure them into the environment.
For example, you can create myproject/jinja2.py with this content:
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
? ? env = Environment(**options)
? ? env.globals.update({
? ? ? ? 'static': staticfiles_storage.url,
? ? ? ? 'url': reverse,
? ? })
? ? return env
and set the 'environment' option to 'myproject.jinja2.environment'.
Then you could use the following constructs in Jinja2 templates:
<img src="{{ static('path/to/company-logo.png') }}" alt="Company Logo">
<a href="{{ url('admin:index') }}">Administration</a>
The concepts of tags and filters exist both in the Django template language and in Jinja2 but they’re used differently. Since Jinja2 supports passing arguments to callables in templates, many features that require a template tag or filter in Django templates can be achieved simply by calling a function in Jinja2 templates, as shown in the example above. Jinja2’s global namespace removes the need for template context processors. The Django template language doesn’t have an equivalent of Jinja2 tests.
Custom backends?
Here’s how to implement a custom template backend in order to use another template system. A template backend is a class that inherits django.template.backends.base.BaseEngine. It must implement get_template() and optionally from_string(). Here’s an example for a fictional foobar template library:
from django.template import TemplateDoesNotExist, TemplateSyntaxError
from django.template.backends.base import BaseEngine
from django.template.backends.utils import csrf_input_lazy, csrf_token_lazy
import foobar
class FooBar(BaseEngine):
? ? # Name of the subdirectory containing the templates for this engine
? ? # inside an installed application.
? ? app_dirname = 'foobar'
? ? def __init__(self, params):
? ? ? ? params = params.copy()
? ? ? ? options = params.pop('OPTIONS').copy()
? ? ? ? super().__init__(params)
? ? ? ? self.engine = foobar.Engine(**options)
? ? def from_string(self, template_code):
? ? ? ? try:
? ? ? ? ? return Template(self.engine.from_string(template_code))
? ? ? ? except foobar.TemplateCompilationFailed as exc:
? ? ? ? ? ? raise TemplateSyntaxError(exc.args)
? ? def get_template(self, template_name):
? ? ? ? try:
? ? ? ? ? ? return Template(self.engine.get_template(template_name))
? ? ? ? except foobar.TemplateNotFound as exc:
? ? ? ? ? ? raise TemplateDoesNotExist(exc.args, backend=self)
? ? ? ? except foobar.TemplateCompilationFailed as exc:
? ? ? ? ? ? raise TemplateSyntaxError(exc.args)
class Template:
? ? def __init__(self, template):
? ? ? ? self.template = template
? ? def render(self, context=None, request=None):
? ? ? ? if context is None:
? ? ? ? ? ? context = {}
? ? ? ? if request is not None:
? ? ? ? ? ? context['request'] = request
? ? ? ? ? ? context['csrf_input'] = csrf_input_lazy(request)
? ? ? ? ? ? context['csrf_token'] = csrf_token_lazy(request)
? ? ? ? return self.template.render(context)
See DEP 182 for more information.
Debug integration for custom engines?
The Django debug page has hooks to provide detailed information when a template error arises. Custom template engines can use these hooks to enhance the traceback information that appears to users. The following hooks are available:
Template postmortem?
The postmortem appears when TemplateDoesNotExist is raised. It lists the template engines and loaders that were used when trying to find a given template. For example, if two Django engines are configured, the postmortem will appear like:
../../_images/postmortem.png
Custom engines can populate the postmortem by passing the backend and tried arguments when raising TemplateDoesNotExist. Backends that use the postmortem should specify an origin on the template object.
Contextual line information?
If an error happens during template parsing or rendering, Django can display the line the error happened on. For example:
../../_images/template-lines.png
Custom engines can populate this information by setting a template_debug attribute on exceptions raised during parsing and rendering. This attribute is a dict with the following values:
'name': The name of the template in which the exception occurred.
'message': The exception message.
'source_lines': The lines before, after, and including the line the exception occurred on. This is for context, so it shouldn’t contain more than 20 lines or so.
'line': The line number on which the exception occurred.
'before': The content on the error line before the token that raised the error.
'during': The token that raised the error.
'after': The content on the error line after the token that raised the error.
'total': The number of lines in source_lines.
'top': The line number where source_lines starts.
'bottom': The line number where source_lines ends.
Given the above template error, template_debug would look like:
{
? ? 'name': '/path/to/template.html',
? ? 'message': "Invalid block tag: 'syntax'",
? ? 'source_lines': [
? ? ? ? (1, 'some\n'),
? ? ? ? (2, 'lines\n'),
? ? ? ? (3, 'before\n'),
? ? ? ? (4, 'Hello {% syntax error %} {{ world }}\n'),
? ? ? ? (5, 'some\n'),
? ? ? ? (6, 'lines\n'),
? ? ? ? (7, 'after\n'),
? ? ? ? (8, ''),
? ? ],
? ? 'line': 4,
? ? 'before': 'Hello ',
? ? 'during': '{% syntax error %}',
? ? 'after': ' {{ world }}\n',
? ? 'total': 9,
? ? 'bottom': 9,
? ? 'top': 1,
}
Origin API and 3rd-party integration?
Django templates have an Origin object available through the template.origin attribute. This enables debug information to be displayed in the template postmortem, as well as in 3rd-party libraries, like the Django Debug Toolbar.
Custom engines can provide their own template.origin information by creating an object that specifies the following attributes:
'name': The full path to the template.
'template_name': The relative path to the template as passed into the the template loading methods.
'loader_name': An optional string identifying the function or class used to load the template, e.g. django.template.loaders.filesystem.Loader.
The Django template language?
Syntax?
About this section
This is an overview of the Django template language’s syntax. For details see the language syntax reference.
A Django template is simply a text document or a Python string marked-up using the Django template language. Some constructs are recognized and interpreted by the template engine. The main ones are variables and tags.
A template is rendered with a context. Rendering replaces variables with their values, which are looked up in the context, and executes tags. Everything else is output as is.
The syntax of the Django template language involves four constructs.
Variables?
A variable outputs a value from the context, which is a dict-like object mapping keys to values.
Variables are surrounded by {{ and }} like this:
My first name is {{ first_name }}. My last name is {{ last_name }}.
With a context of {'first_name': 'John', 'last_name': 'Doe'}, this template renders to:
My first name is John. My last name is Doe.
Dictionary lookup, attribute lookup and list-index lookups are implemented with a dot notation:
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}
If a variable resolves to a callable, the template system will call it with no arguments and use its result instead of the callable.
Tags?
Tags provide arbitrary logic in the rendering process.
This definition is deliberately vague. For example, a tag can output content, serve as a control structure e.g. an “if” statement or a “for” loop, grab content from a database, or even enable access to other template tags.
Tags are surrounded by {% and %} like this:
{% csrf_token %}
Most tags accept arguments:
{% cycle 'odd' 'even' %}
Some tags require beginning and ending tags:
{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}
A reference of built-in tags is available as well as instructions for writing custom tags.
Filters?
Filters transform the values of variables and tag arguments.
They look like this:
{{ django|title }}
With a context of {'django': 'the web framework for perfectionists with deadlines'}, this template renders to:
The Web Framework For Perfectionists With Deadlines
Some filters take an argument:
{{ my_date|date:"Y-m-d" }}
A reference of built-in filters is available as well as instructions for writing custom filters.
Comments?
Comments look like this:
{# this won't be rendered #}
A {% comment %} tag provides multi-line comments.
Components?
About this section
This is an overview of the Django template language’s APIs. For details see the API reference.
Engine?
django.template.Engine encapsulates an instance of the Django template system. The main reason for instantiating an Engine directly is to use the Django template language outside of a Django project.
django.template.backends.django.DjangoTemplates is a thin wrapper adapting django.template.Engine to Django’s template backend API.
Template?
django.template.Template represents a compiled template. Templates are obtained with Engine.get_template() or Engine.from_string()
Likewise django.template.backends.django.Template is a thin wrapper adapting django.template.Template to the common template API.
Context?
django.template.Context holds some metadata in addition to the context data. It is passed to Template.render() for rendering a template.
django.template.RequestContext is a subclass of Context that stores the current HttpRequest and runs template context processors.
The common API doesn’t have an equivalent concept. Context data is passed in a plain dict and the current HttpRequest is passed separately if needed.
Loaders?
Template loaders are responsible for locating templates, loading them, and returning Template objects.
Django provides several built-in template loaders and supports custom template loaders.
Context processors?
Context processors are functions that receive the current HttpRequest as an argument and return a dict of data to be added to the rendering context.
Their main use is to add common data shared by all templates to the context without repeating code in every view.
Django provides many built-in context processors. Implementing a custom context processor is as simple as defining a function.
Form Assets (the Media class)Class-based views
BACK TO TOP
Additional Information
Search:
Search 2.0 documentation
搜索
Support Django!
Support Django!
Chris Cogdon donated to the Django Software Foundation to support Django development. Donate today!
Contents
Templates
Support for template engines
Configuration
Usage
Built-in backends
Custom backends
Debug integration for custom engines
Template postmortem
Contextual line information
Origin API and 3rd-party integration
The Django template language
Syntax
Variables
Tags
Filters
Comments
Components
Engine
Template
Context
Loaders
Context processors
Browse
Prev: Form Assets (the Media class)
Next: Class-based views
Table of contents
General Index
Python Module Index
You are here:
Django 2.0 documentation
Using Django
Templates
Getting help
FAQ
Try the FAQ — it's got answers to many common questions.
Index, Module Index, or Table of Contents
Handy when looking for specific information.
django-users mailing list
Search for information in the archives of the django-users mailing list, or post a question.
#django IRC channel
Ask a question in the #django IRC channel, or search the IRC logs to see if it’s been asked before.
Ticket tracker
Report bugs with Django or Django documentation in our ticket tracker.
Download:
Offline (Django 2.0): HTML | PDF | ePub
Provided by Read the Docs.
Django Links
Learn More
About Django
Getting Started with Django
Team Organization
Django Software Foundation
Code of Conduct
Diversity Statement
Get Involved
Join a Group
Contribute to Django
Submit a Bug
Report a Security Issue
Follow Us
GitHub
News RSS
Django Users Mailing List
Django
Hosting by
Rackspace
Design by
Threespot
&
? 2005-2018 Django Software Foundation and individual contributors. Django is a registered trademark of the Django Software Foundation.