django/django
Templates
django/template/ is the Django Template Language (DTL) — a tag-and-filter language for rendering HTML (and any text format). Since 1.8, the directory also exposes a backend abstraction so other engines (Jinja2, mostly) can plug in.
Purpose
Provide a sandboxed, designer-oriented templating language with autoescape, template inheritance, and a stable extension model (custom tags and filters via django.template.Library). Pluggable backends let projects use multiple engines side-by-side.
Directory layout
django/template/
├── __init__.py
├── engine.py # Engine: the central per-engine config
├── loader.py # get_template, select_template, render_to_string
├── loader_tags.py # {% extends %}, {% block %}, {% include %}
├── base.py # Lexer, Parser, Token, Variable, Node, NodeList (~44 KB)
├── context.py # Context, RequestContext, ContextDict
├── context_processors.py # csrf token processor (others live in contrib apps)
├── defaulttags.py # {% if %}, {% for %}, {% url %}, {% with %}, … (~55 KB)
├── defaultfilters.py # |default, |length, |slice, |date, |upper, … (~28 KB)
├── library.py # Library, simple_tag, inclusion_tag, register_filter
├── response.py # TemplateResponse, SimpleTemplateResponse
├── smartif.py # The expression parser used by {% if %}
├── exceptions.py # TemplateDoesNotExist, TemplateSyntaxError, …
├── utils.py # InvalidTemplateLibrary, get_app_template_dirs
├── autoreload.py # Templates aware of the runserver autoreloader
├── backends/
│ ├── base.py # BaseEngine
│ ├── django.py # DjangoTemplates (DTL backend)
│ ├── jinja2.py # Jinja2 backend
│ ├── dummy.py # No-op backend for tests
│ └── utils.py
└── loaders/
├── base.py # Loader base class
├── filesystem.py # FilesystemLoader
├── app_directories.py # AppDirectoriesLoader
├── cached.py # CachedLoader
└── locmem.py # LocMemLoaderKey abstractions
| Type | File | Role |
|---|---|---|
Engine |
engine.py |
Per-engine config (loaders, dirs, builtins, libraries) |
Template |
base.py |
A parsed template tree (a list of Nodes) |
Lexer, Parser |
base.py |
Tokenise and parse the template source |
Token |
base.py |
A token (text, var, block, comment) |
Variable |
base.py |
A {{ var.attr }} expression |
Node, NodeList |
base.py |
Compiled template nodes; render(context) |
Context, RequestContext |
context.py |
The variable lookup stack |
Library |
library.py |
The register object for custom tags/filters |
BaseEngine |
backends/base.py |
The pluggable backend interface |
DjangoTemplates, Jinja2 |
backends/django.py, backends/jinja2.py |
The two shipped backends |
Origin |
base.py |
A loader-aware identifier for a template source |
TemplateResponse |
response.py |
A response that defers rendering until needed |
How it works
graph TD
Source["template source<br/>e.g., 'index.html'"]
Loader["Loader<br/>(filesystem / app_directories / cached)"]
Lexer
Tokens["[Token, Token, …]"]
Parser
Tree["NodeList of Node objects"]
Context["Context (dict-like stack)"]
Render["Node.render(context)"]
Output["rendered text (SafeString)"]
Source --> Loader
Loader --> Lexer
Lexer --> Tokens
Tokens --> Parser
Parser --> Tree
Tree --> Render
Context --> Render
Render --> OutputLexing and parsing
Lexer.tokenize() walks the source string and emits Tokens of four kinds:
TOKEN_TEXT— literal text outside of any tag.TOKEN_VAR—{{ ... }}.TOKEN_BLOCK—{% ... %}.TOKEN_COMMENT—{# ... #}.
Parser.parse() turns the token stream into a NodeList. For variable tokens, it builds a VariableNode wrapping a FilterExpression. For block tokens, it consults the parser's tag library to find a compile function that consumes from the parser to produce a Node (e.g., IfNode for {% if %} reads tokens until it sees {% endif %}).
Variable lookup
Variable.resolve(context) is the workhorse for {{ ... }}. It:
- Splits on
.to get a sequence of attribute lookups. - For each step, tries (in order): dictionary lookup, attribute access, list-index access, callable call (with no args, only if
do_not_call_in_templatesis not set). - Returns the resolved value or raises
VariableDoesNotExist. The default templating treats failure as an empty string, configurable viastring_if_invalid.
Filters
FilterExpression parses var|filter:"arg"|filter2 syntax and holds a list of (filter_func, args) tuples. The library lookup happens at parse time; rendering applies each filter in order.
Tags
A custom tag is a Python function that takes a parser and a token, optionally consumes more tokens from the parser (for block tags like {% if %}...{% endif %}), and returns a Node instance whose render(context) produces output.
Library.simple_tag and Library.inclusion_tag are decorators that wrap simple cases. Library.tag is the lower-level decorator for full block tags.
Template inheritance
{% extends %} and {% block %} are implemented in loader_tags.py. ExtendsNode.render():
- Loads the parent template (lazily, with
select_template). - Walks the parent's NodeList and replaces any
BlockNodewith the child's override (if present). - Renders the modified parent.
{% include %} similarly loads another template and renders it inline with the current (or a fresh) context.
Pluggable backends
Engine is the DTL configuration object. The bigger BaseEngine interface in backends/base.py lets non-DTL engines participate. Each backend exposes:
__init__(params)— accepts a config dict from theTEMPLATESsetting.from_string(template_code)— return aTemplatefrom a string.get_template(template_name)— return aTemplatefrom a loaded file.
The Jinja2 backend (backends/jinja2.py) wraps jinja2.Environment and adapts its API to Django's template protocol. The shared cross-engine surface is template_rendered signal, TemplateResponse, and RequestContext (DTL-only).
Loaders
A loader resolves a template name to source code. The default chain is app_directories (look in <app>/templates/) then filesystem (look in TEMPLATES["DIRS"]). The cached loader wraps another loader and caches parsed Template objects in memory.
Context processors
Context processors are functions that run on every render and inject extra variables into a RequestContext. Built-in:
django.template.context_processors.csrf(intemplate/context_processors.py).django.contrib.auth.context_processors.auth(incontrib/auth/context_processors.py) — addsuserandperms.django.contrib.messages.context_processors.messages.django.template.context_processors.{request,debug,i18n,media,static,tz}.
Integration points
- Views (views) —
render(request, template_name, context)andTemplateResponseare the standard view-side entry points. - Forms (forms) — render via
as_p,as_table,as_div,as_ulor per-template form rendering. - Admin (
contrib/admin/) — built entirely on the DTL. - i18n (
django/utils/translation/) —{% trans %},{% blocktrans %},{% blocktranslate %}tags are implemented indefaulttags.py. - Static files (
contrib/staticfiles/) — provides{% static %}tag. - Autoreload — the dev server's reloader registers template directories so editing a template invalidates the loader cache.
Entry points for modification
- Custom tag or filter: create a
templatetags/<name>.pyin your app, instantiateregister = template.Library(), and decorate with@register.simple_tag,@register.filter, etc. - Custom loader: subclass
django.template.loaders.base.Loaderand overrideget_contents(). Add it to yourTEMPLATES["OPTIONS"]["loaders"]. - Custom backend: subclass
BaseEngineintemplate/backends/base.py. Mirror the API ofDjangoTemplates. - Built-in tag/filter: edits to
defaulttags.py/defaultfilters.py. These changes go through Django's deprecation cycle.
Key source files
| File | Purpose |
|---|---|
django/template/base.py |
Lexer, Parser, Variable, Node — the language core (~44 KB) |
django/template/engine.py |
Engine |
django/template/loader.py |
get_template, select_template, render_to_string |
django/template/defaulttags.py |
Built-in tags ({% if %}, {% for %}, {% url %}, …) |
django/template/defaultfilters.py |
Built-in filters (default, date, length, …) |
django/template/loader_tags.py |
{% extends %}, {% block %}, {% include %} |
django/template/context.py |
Context, RequestContext |
django/template/library.py |
Library, simple_tag, inclusion_tag |
django/template/response.py |
TemplateResponse, SimpleTemplateResponse |
django/template/backends/django.py |
DTL backend |
django/template/backends/jinja2.py |
Jinja2 backend |
django/template/loaders/cached.py |
Loader cache |
django/template/smartif.py |
{% if %} expression parser |
Where to read tests
tests/template_tests/— exhaustive lexer, parser, tag, filter, and inheritance coverage.tests/template_backends/— backend-level tests.tests/templates/— fixture templates used by the test apps.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.