Jinja2 is a fast, expressive, extensible templating engine for Python. Special placeholders in templates allow writing code similar to Python syntax, which is then rendered against passed data to produce a final document. It supports template inheritance, macros, autoescaping, sandboxed execution, async rendering, and i18n via Babel. Current stable version is 3.1.6 (a security patch release); the 3.1.x branch receives active bugfix and security updates with no fixed cadence.
Install & Compatibility
Where this runs
tested against v3.1.6 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.950 runs
installs and imports cleanly · install 0.0s · import 0.134s · 18.9MB
glibcpy 3.10–3.950 runs
installs and imports cleanly · install 1.7s · import 0.122s · 19MB
17MB installed
● package 17MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Environment
✓ from jinja2 import Environment
Central object; always instantiate with a Loader and explicit autoescape setting
FileSystemLoader
✓ from jinja2 import FileSystemLoader
Loads templates from the filesystem by search path
PackageLoader
✓ from jinja2 import PackageLoader
Loads templates from inside a Python package's directory; no longer requires setuptools as of 3.0
select_autoescape
✓ from jinja2 import select_autoescape
Recommended helper for configuring autoescape per file extension; pass to Environment(autoescape=...)
Markup
✓ from markupsafe import Markup
✗ from jinja2 import Markup
jinja2.Markup and jinja2.escape were removed in 3.1.0; import both from markupsafe directly
escape
✓ from markupsafe import escape
✗ from jinja2 import escape
jinja2.escape was removed in 3.1.0; use markupsafe.escape
pass_context / pass_environment / pass_eval_context
✓ from jinja2 import pass_context
✗ from jinja2 import contextfunction
contextfunction, contextfilter, environmentfunction, environmentfilter, evalcontextfunction, evalcontextfilter were all removed in 3.0; use pass_context, pass_environment, pass_eval_context decorators instead
SandboxedEnvironment
✓ from jinja2.sandbox import SandboxedEnvironment
Required when rendering untrusted templates; not imported from jinja2 top-level
UndefinedError
✓ from jinja2 import UndefinedError
Raised when a variable is accessed that is not defined and StrictUndefined or DebugUndefined is used
Basic Environment setup and template rendering, demonstrating safe autoescape configuration for HTML and plain-text contexts.
from jinja2 import Environment, FileSystemLoader, select_autoescape
# Always set autoescape explicitly; default is False which is a security risk for HTML output
env = Environment(
loader=FileSystemLoader("."),
autoescape=select_autoescape(["html", "htm", "xml"]),
)
# Render from a string (autoescape=False for non-HTML plain text)
text_env = Environment()
template = text_env.from_string("Hello, {{ name }}! You have {{ count }} message(s).")
result = template.render(name="World", count=3)
print(result)
# -> Hello, World! You have 3 message(s).
# Render an HTML template string safely
html_env = Environment(autoescape=True)
html_tmpl = html_env.from_string("<p>Hello, {{ name }}!</p>")
print(html_tmpl.render(name="<script>alert(1)</script>"))
# -> <p>Hello, <script>alert(1)</script>!</p>
Errors
Common errors & fixes
jinja2.exceptions.TemplateNotFound: index.html
This error occurs when Jinja2 cannot locate the specified template file, often due to incorrect template directory configuration or the template file being absent.
fixEnsure that the 'templates' directory is correctly named and located at the same level as your main application file, and that the 'index.html' file exists within it.
jinja2.exceptions.UndefinedError: 'form' is undefined
This error arises when a variable expected in the template is not passed from the Flask route, leading to it being undefined during rendering.
fixPass the 'form' variable to the template by including it in the 'render_template' function call, like 'render_template("form.html", form=form)'. jinja2.exceptions.UndefinedError: 'message' is undefined
This error occurs when the 'message' variable is referenced in the template but is not provided by the Flask route.
fixEnsure that the 'message' variable is defined and passed to the template in the 'render_template' function, such as 'render_template("index.html", message=message)'. jinja2.exceptions.UndefinedError: 'btn' is undefined
This error indicates that the 'btn' variable is used in the template without being defined or passed from the Flask route.
fixDefine the 'btn' variable in your Flask route and pass it to the template using 'render_template("index.html", btn=btn)'. jinja2.exceptions.UndefinedError: 'detail' is undefined
This error signifies that the 'detail' variable is referenced in the template but has not been defined or passed from the Flask route.
fixDefine the 'detail' variable in your Flask route and pass it to the template using 'render_template("detail.html", detail=detail)'. Audit
Dependencies
MarkupSaferequiredRequired for HTML escaping and the Markup/escape types used throughout the API (>=2.0 for Jinja2 3.x)
BabeloptionalRequired only for i18n/l10n support via the jinja2.ext.i18n extension