{"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,"search_vec":"'3.1':59 '3.1.6':53 'activ':63 'allow':16 'async':43 'autoescap':40 'babel':48 'branch':61 'bugfix':64 'cadenc':71 'code':18 'current':49 'data':29 'django':76 'document':34 'engin':9 'execut':42 'express':6 'extens':7 'fast':5 'final':33 'fix':70 'flask':75 'html':73 'i18n':46 'inherit':38 'jinja':78 'jinja2':1,2 'macro':39 'markup':79 'pass':28 'patch':56 'placehold':13 'produc':31 'python':11,21 'receiv':62 'releas':57 'render':26,44,77 'sandbox':41 'secur':55,66 'similar':19 'special':12 'stabl':50 'support':36 'syntax':22 'templat':8,15,37,72 'updat':67 'version':51 'via':47 'web':74 'write':17 'x':60","created_at":"2026-03-28T05:38:19.743252+00:00","updated_at":"2026-04-15T19:01:15.673906+00:00","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,"quickstart_score":80,"quickstart_tag":"verified","pypi_latest":"3.1.6","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/pallets/jinja","docs":"https://jinja.palletsprojects.com/","changelog":"https://jinja.palletsprojects.com/changes/","pypi":"https://pypi.org/project/Jinja2/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["web-framework","serialization"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-06-28","next_check":"2026-07-28","install_tag":"verified"}}