Environment, loaders and render

Jinja · Essentials · 10 min

Every use of Jinja goes through an Environment, and its settings decide escaping, loading and errors.

A template is text with placeholders. The central object is the `Environment`: it holds configuration (autoescaping, undefined handling, filters, globals) and a loader that finds templates by name.

env = Environment(loader=FileSystemLoader("templates"), autoescape=select_autoescape())
template = env.get_template("hello.html")
html = template.render(name="Ann", items=[1, 2])

render() takes keyword arguments or a single dict; the names become template variables, called the context. The result is a string. For huge outputs, template.generate() yields chunks and template.stream() can write to a file.

For quick scripts, Template("Hello {{ name }}!") or env.from_string(source) compiles a template from a string. Prefer one shared environment with a loader for real projects: it caches compiled templates and enables inheritance and imports between files.

An important default: a bare Environment() has autoescaping off. That is correct for plain text, YAML or SQL generation, but for HTML you must turn it on, usually with select_autoescape(), which enables it for .html, .htm and .xml templates. Frameworks such as Flask configure this for you.

Templates can use any file extension, but select_autoescape() only checks how the name ends: page.html.j2 is not escaped unless you pass enabled_extensions=("html", "j2") or similar.

Template syntax has three delimiters: {{ ... }} prints an expression, {% ... %} runs a statement such as if or for, and {# ... #} is a comment that produces no output.

Example

from jinja2 import DictLoader, Environment, Template, select_autoescape

print(Template("Hello {{ name }}!").render(name="Ann"))    # Hello Ann!

env = Environment(
    loader=DictLoader({                 # FileSystemLoader("templates") in real projects
        "greet.html": "<p>Hi {{ user }}{# not rendered #}</p>",
        "greet.txt": "Hi {{ user }}",
    }),
    autoescape=select_autoescape(),     # on for .html/.htm/.xml
)
print(env.get_template("greet.html").render(user="<b>Bo</b>"))
# <p>Hi &lt;b&gt;Bo&lt;/b&gt;</p>
print(env.get_template("greet.txt").render({"user": "<b>Bo</b>"}))
# Hi <b>Bo</b>

Remember

  • An Environment holds config and a loader; get_template loads by name
  • render(**vars) or render(dict) returns a string
  • {{ }} prints, {% %} executes, {# #} comments
  • Environment() has autoescaping off; enable it for HTML

Watch out for

  • Rendering HTML with a default Environment(), leaving output unescaped.

Check yourself

  1. What is the default autoescape setting of a plain Environment()?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: jinja.palletsprojects.com/en/stable/api/#basics

Environment, loaders and render · Jinja · Topolearn