The Django Template Engine is a text-based templating system that separates presentation logic from business logic using a syntax of variables ({{ variable }}), tags ({% tag %}), and filters ({{ value|filter }}), with support for template inheritance, inclusion, and automatic HTML escaping for security.
The template engine solves the problem of generating dynamic HTML (or any text format) without embedding business logic in presentation code. Templates contain only display logic — loops, conditionals, variable interpolation — while views prepare context data. The engine compiles templates to an intermediate representation, then renders them with a context dictionary, auto-escaping variables to prevent XSS unless explicitly marked safe.
- Template loaded —
get_template('name.html')orrender()loads template fromTEMPLATESdirs - Template parsed — Lexer tokenizes into
TextNode,VariableNode,BlockNode,IfNode,ForNode - Context created — View builds context dict; context processors add global variables (
request,user,messages) - Template rendered —
template.render(context)walks node tree, resolves variables, executes tags - Auto-escaping applied — All
{{ variable }}output passed throughescape()unless|safeormark_safe() - Result returned — Rendered string wrapped in
HttpResponse
- Auto-escaping by default:
{{ user_input }}safe from XSS; opt-out with|safeormark_safe() - Template inheritance:
{% extends 'base.html' %}+{% block content %}enables layout reuse - Custom tags/filters:
@register.simple_tag,@register.filterextend template language - Loader flexibility:
TEMPLATES['loaders']supports filesystem, app directories, cached loader - Debug integration:
TEMPLATE_DEBUGshows template source lines in error pages
- Built from: Function-Based Views — Primary consumer via
render() - Built from: Class-Based Views —
TemplateView,DetailViewuse templates - Built from: Context Processors — Inject global template variables
- Builds into: Template Inheritance — Layout composition pattern
- Builds into: Static Files Integration —
{% static 'css/style.css' %} - Builds into: Form Rendering —
{{ form.as_p }},{{ field }} - Contrasts with: Jinja2 — Faster, more Pythonic, standalone, similar syntax
- Contrasts with: Client-Side Templates — SPA frameworks (React/Vue) render in browser
- Related: CSRF Protection —
{% csrf_token %}tag - Related: Internationalization —
{% trans %},{% blocktrans %}tags
- Variable lookup order: Dict key → attribute → list index → callable (no args) → empty string
- Silent failures: Missing variables render as empty string (configurable via
string_if_invalid) |safedanger: Marking user-controlled data as safe enables XSS; only use on trusted content- Performance: Uncached template loading hits filesystem on every request; use
cached.Loaderin production