{"id":276,"library":"Jinja2","title":"Jinja2","description":"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.","status":"active","version":"3.1.6","language":"python","source_language":"en","source_url":"https://github.com/pallets/jinja","tags":["templating","html","web","flask","django","rendering","jinja","markup"],"install":[{"cmd":"pip install Jinja2","lang":"bash","label":"Latest stable"},{"cmd":"pip install \"Jinja2>=3.1.6\"","lang":"bash","label":"Pin to secure minimum"}],"dependencies":[{"reason":"Required for HTML escaping and the Markup/escape types used throughout the API (>=2.0 for Jinja2 3.x)","package":"MarkupSafe","optional":false},{"reason":"Required only for i18n/l10n support via the jinja2.ext.i18n extension","package":"Babel","optional":true}],"imports":[{"note":"Central object; always instantiate with a Loader and explicit autoescape setting","symbol":"Environment","correct":"from jinja2 import Environment"},{"note":"Loads templates from the filesystem by search path","symbol":"FileSystemLoader","correct":"from jinja2 import FileSystemLoader"},{"note":"Loads templates from inside a Python package's directory; no longer requires setuptools as of 3.0","symbol":"PackageLoader","correct":"from jinja2 import PackageLoader"},{"note":"Recommended helper for configuring autoescape per file extension; pass to Environment(autoescape=...)","symbol":"select_autoescape","correct":"from jinja2 import select_autoescape"},{"note":"jinja2.Markup and jinja2.escape were removed in 3.1.0; import both from markupsafe directly","wrong":"from jinja2 import Markup","symbol":"Markup","correct":"from markupsafe import Markup"},{"note":"jinja2.escape was removed in 3.1.0; use markupsafe.escape","wrong":"from jinja2 import escape","symbol":"escape","correct":"from markupsafe import escape"},{"note":"contextfunction, contextfilter, environmentfunction, environmentfilter, evalcontextfunction, evalcontextfilter were all removed in 3.0; use pass_context, pass_environment, pass_eval_context decorators instead","wrong":"from jinja2 import contextfunction","symbol":"pass_context / pass_environment / pass_eval_context","correct":"from jinja2 import pass_context"},{"note":"Required when rendering untrusted templates; not imported from jinja2 top-level","symbol":"SandboxedEnvironment","correct":"from jinja2.sandbox import SandboxedEnvironment"},{"note":"Raised when a variable is accessed that is not defined and StrictUndefined or DebugUndefined is used","symbol":"UndefinedError","correct":"from jinja2 import UndefinedError"}],"quickstart":{"code":"from jinja2 import Environment, FileSystemLoader, select_autoescape\n\n# Always set autoescape explicitly; default is False which is a security risk for HTML output\nenv = Environment(\n    loader=FileSystemLoader(\".\"),\n    autoescape=select_autoescape([\"html\", \"htm\", \"xml\"]),\n)\n\n# Render from a string (autoescape=False for non-HTML plain text)\ntext_env = Environment()\ntemplate = text_env.from_string(\"Hello, {{ name }}! You have {{ count }} message(s).\")\nresult = template.render(name=\"World\", count=3)\nprint(result)\n# -> Hello, World! You have 3 message(s).\n\n# Render an HTML template string safely\nhtml_env = Environment(autoescape=True)\nhtml_tmpl = html_env.from_string(\"<p>Hello, {{ name }}!</p>\")\nprint(html_tmpl.render(name=\"<script>alert(1)</script>\"))\n# -> <p>Hello, &lt;script&gt;alert(1)&lt;/script&gt;!</p>\n","lang":"python","description":"Basic Environment setup and template rendering, demonstrating safe autoescape configuration for HTML and plain-text contexts."},"warnings":[{"fix":"Replace with `from markupsafe import Markup, escape`. MarkupSafe is always installed as a dependency.","message":"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.","severity":"breaking","affected_versions":"<3.1.0"},{"fix":"Use pass_context, pass_environment, and pass_eval_context from jinja2 instead.","message":"contextfunction, contextfilter, environmentfunction, environmentfilter, evalcontextfunction, and evalcontextfilter decorators were removed in 3.0. Importing them raises ImportError.","severity":"breaking","affected_versions":"<3.0"},{"fix":"Use Python 3.7+. Pin to Jinja2<3.0 only if you must support Python 2.7 (EOL).","message":"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.","severity":"breaking","affected_versions":"<3.1.0"},{"fix":"Always pass `autoescape=select_autoescape(['html', 'htm', 'xml'])` or `autoescape=True` when creating an Environment for HTML output.","message":"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.","severity":"gotcha","affected_versions":"all"},{"fix":"Only pass developer-controlled or sanitized (e.g. via bleach) content to Markup(). Never do Markup(user_input).","message":"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.","severity":"gotcha","affected_versions":"all"},{"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.","message":"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.","severity":"gotcha","affected_versions":"all"},{"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).","message":"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.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T12:45:20.604Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"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.","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.","error":"jinja2.exceptions.TemplateNotFound: index.html"},{"fix":"Pass the 'form' variable to the template by including it in the 'render_template' function call, like 'render_template(\"form.html\", form=form)'.","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.","error":"jinja2.exceptions.UndefinedError: 'form' is undefined"},{"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)'.","cause":"This error occurs when the 'message' variable is referenced in the template but is not provided by the Flask route.","error":"jinja2.exceptions.UndefinedError: 'message' is undefined"},{"fix":"Define the 'btn' variable in your Flask route and pass it to the template using 'render_template(\"index.html\", btn=btn)'.","cause":"This error indicates that the 'btn' variable is used in the template without being defined or passed from the Flask route.","error":"jinja2.exceptions.UndefinedError: 'btn' is undefined"},{"fix":"Define the 'detail' variable in your Flask route and pass it to the template using 'render_template(\"detail.html\", detail=detail)'.","cause":"This error signifies that the 'detail' variable is referenced in the template but has not been defined or passed from the Flask route.","error":"jinja2.exceptions.UndefinedError: 'detail' is undefined"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.9,"disk_size":"18.9M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.9,"disk_size":"18.9M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":3.9,"disk_size":"19M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":3.9,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.2,"mem_mb":4.5,"disk_size":"21.0M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":4.5,"disk_size":"21.0M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":4.5,"disk_size":"22M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":4.5,"disk_size":"22M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":4.5,"disk_size":"12.8M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":4.5,"disk_size":"12.8M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":4.5,"disk_size":"13M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":4.5,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":4.8,"disk_size":"12.5M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":4.8,"disk_size":"12.5M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":4.8,"disk_size":"13M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":4.8,"disk_size":"13M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":4,"disk_size":"18.4M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":4,"disk_size":"18.4M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":4,"disk_size":"19M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":4,"disk_size":"19M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}