Jinja2
raw JSON → 3.1.6 verified Tue May 12 auth: no python install: verified quickstart: verified
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.
pip install Jinja2 Common errors
error jinja2.exceptions.TemplateNotFound: index.html ↓
cause This error occurs when Jinja2 cannot locate the specified template file, often due to incorrect template directory configuration or the template file being absent.
fix
Ensure 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.
error jinja2.exceptions.UndefinedError: 'form' is undefined ↓
cause This error arises when a variable expected in the template is not passed from the Flask route, leading to it being undefined during rendering.
fix
Pass the 'form' variable to the template by including it in the 'render_template' function call, like 'render_template("form.html", form=form)'.
error jinja2.exceptions.UndefinedError: 'message' is undefined ↓
cause This error occurs when the 'message' variable is referenced in the template but is not provided by the Flask route.
fix
Ensure that the 'message' variable is defined and passed to the template in the 'render_template' function, such as 'render_template("index.html", message=message)'.
error jinja2.exceptions.UndefinedError: 'btn' is undefined ↓
cause This error indicates that the 'btn' variable is used in the template without being defined or passed from the Flask route.
fix
Define the 'btn' variable in your Flask route and pass it to the template using 'render_template("index.html", btn=btn)'.
error jinja2.exceptions.UndefinedError: 'detail' is undefined ↓
cause This error signifies that the 'detail' variable is referenced in the template but has not been defined or passed from the Flask route.
fix
Define the 'detail' variable in your Flask route and pass it to the template using 'render_template("detail.html", detail=detail)'.
Warnings
breaking jinja2.Markup and jinja2.escape were removed in 3.1.0. Any code doing `from jinja2 import Markup` or `from jinja2 import escape` raises ImportError. ↓
fix Replace with `from markupsafe import Markup, escape`. MarkupSafe is always installed as a dependency.
breaking contextfunction, contextfilter, environmentfunction, environmentfilter, evalcontextfunction, and evalcontextfilter decorators were removed in 3.0. Importing them raises ImportError. ↓
fix Use pass_context, pass_environment, and pass_eval_context from jinja2 instead.
breaking Python 2.7 and 3.5 support was dropped in 3.0; Python 3.6 support was dropped in 3.1.0. Running on these versions will fail. ↓
fix Use Python 3.7+. Pin to Jinja2<3.0 only if you must support Python 2.7 (EOL).
gotcha autoescape defaults to False in Environment. Rendering HTML with user input without enabling autoescape exposes the app to XSS attacks. Bandit (B701) and CodeQL flag this as high severity. ↓
fix Always pass `autoescape=select_autoescape(['html', 'htm', 'xml'])` or `autoescape=True` when creating an Environment for HTML output.
gotcha Wrapping user-supplied strings in Markup() bypasses autoescaping entirely and causes XSS. Markup() signals a string is already safe; passing untrusted input to it is a common mistake. ↓
fix Only pass developer-controlled or sanitized (e.g. via bleach) content to Markup(). Never do Markup(user_input).
gotcha Server-Side Template Injection (SSTI): passing user-controlled strings as the template source (e.g. env.from_string(user_input) or render_template_string(request.args['tmpl'])) allows arbitrary code execution. ↓
fix Never use user input as the template string. Use pre-defined file-based templates. For sandboxed user templates use jinja2.sandbox.SandboxedEnvironment, which still does not guarantee full isolation.
gotcha Macros imported from another file do not have access to the calling template's context variables by default. Accessing outer-scope variables inside imported macros silently returns Undefined. ↓
fix Pass all required values as explicit macro arguments. Use `{% import 'macros.html' as macros with context %}` only if you intentionally need the full context available (performance and caching implications apply).
Install
pip install "Jinja2>=3.1.6" Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) "Jinja2>=3.1.6" - - 0.10s 18.9M
3.10 alpine (musl) Jinja2 - - 0.10s 18.9M
3.10 slim (glibc) "Jinja2>=3.1.6" - - 0.07s 19M
3.10 slim (glibc) Jinja2 - - 0.07s 19M
3.11 alpine (musl) "Jinja2>=3.1.6" - - 0.20s 21.0M
3.11 alpine (musl) Jinja2 - - 0.19s 21.0M
3.11 slim (glibc) "Jinja2>=3.1.6" - - 0.15s 22M
3.11 slim (glibc) Jinja2 - - 0.16s 22M
3.12 alpine (musl) "Jinja2>=3.1.6" - - 0.15s 12.8M
3.12 alpine (musl) Jinja2 - - 0.15s 12.8M
3.12 slim (glibc) "Jinja2>=3.1.6" - - 0.15s 13M
3.12 slim (glibc) Jinja2 - - 0.16s 13M
3.13 alpine (musl) "Jinja2>=3.1.6" - - 0.14s 12.5M
3.13 alpine (musl) Jinja2 - - 0.14s 12.5M
3.13 slim (glibc) "Jinja2>=3.1.6" - - 0.14s 13M
3.13 slim (glibc) Jinja2 - - 0.15s 13M
3.9 alpine (musl) "Jinja2>=3.1.6" - - 0.10s 18.4M
3.9 alpine (musl) Jinja2 - - 0.10s 18.4M
3.9 slim (glibc) "Jinja2>=3.1.6" - - 0.10s 19M
3.9 slim (glibc) Jinja2 - - 0.08s 19M
Imports
- Environment
from jinja2 import Environment - FileSystemLoader
from jinja2 import FileSystemLoader - PackageLoader
from jinja2 import PackageLoader - select_autoescape
from jinja2 import select_autoescape - Markup wrong
from jinja2 import Markupcorrectfrom markupsafe import Markup - escape wrong
from jinja2 import escapecorrectfrom markupsafe import escape - pass_context / pass_environment / pass_eval_context wrong
from jinja2 import contextfunctioncorrectfrom jinja2 import pass_context - SandboxedEnvironment
from jinja2.sandbox import SandboxedEnvironment - UndefinedError
from jinja2 import UndefinedError
Quickstart verified last tested: 2026-04-23
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>