Skip to main content

Jinja Environment and Templates

The application integrates the Jinja2 templating engine through the App and Scaffold classes. While Scaffold (defined in src/flask/sansio/scaffold.py) provides the foundational structure for template folders and context processors, the App class (defined in src/flask/sansio/app.py) manages the actual Jinja environment and provides the registration interface for filters, globals, and tests.

The Jinja Environment

The central point of template management is the App.jinja_env property. This is a cached property that initializes the Jinja environment the first time it is accessed.

The environment is created via App.create_jinja_environment(). Developers can influence this environment in two primary ways:

  1. Configuration via jinja_options: This dictionary in the App class contains options passed directly to the Jinja environment constructor.
  2. Custom Environment Classes: By overriding the jinja_environment class attribute on a subclass of App, you can change the underlying environment implementation.
# Example of overriding the environment class (from tests/test_templating.py)
class CustomEnvironment(flask.templating.Environment):
pass

class CustomFlask(flask.Flask):
jinja_environment = CustomEnvironment

app = CustomFlask(__name__)

Note: Changing jinja_options after app.jinja_env has been accessed will have no effect because the environment is cached.

Extending Templates

The App class provides several decorators and methods to extend Jinja's functionality. These must be called before the application handles its first request, enforced by the @setupmethod decorator.

Custom Filters

Filters are used to transform data within templates. You can register them using the @app.template_filter() decorator or the add_template_filter() method.

# From src/flask/sansio/app.py
@app.template_filter("reverse")
def reverse_filter(s):
return reversed(s)

# Manual registration
def my_filter(s):
return s[::-1]
app.add_template_filter(my_filter, name="rev")

Globals and Tests

Similar to filters, globals and tests can be registered to provide functions or boolean checks available in all templates.

  • Globals: Registered via @app.template_global() or add_template_global(). These are added to jinja_env.globals.
  • Tests: Registered via @app.template_test() or add_template_test(). These are added to jinja_env.tests.
@app.template_global
def double(n):
return 2 * n

@app.template_test("prime")
def is_prime_test(n):
# ... logic to check if n is prime ...
return True

Context Processors

Context processors are managed by the Scaffold class and allow you to inject variables into the template context automatically. These functions run before a template is rendered and must return a dictionary.

The Scaffold.template_context_processors attribute stores these functions. By default, it includes a default processor that provides standard variables like config, request, session, and g.

# From src/flask/sansio/scaffold.py pattern
@app.context_processor
def inject_user():
return {"user": g.user}

When a template is rendered, the application merges the dictionaries returned by all registered context processors into the template's namespace.

Template Resolution and Loading

Template loading is handled by a combination of the jinja_loader and the DispatchingJinjaLoader.

  1. Scaffold.template_folder: Both the application and blueprints can define a template_folder. This path is relative to the root_path of the object.
  2. Scaffold.jinja_loader: This property creates a jinja2.loaders.FileSystemLoader pointing to the configured template_folder.
  3. DispatchingJinjaLoader: The App class uses create_global_jinja_loader() to instantiate a DispatchingJinjaLoader. This loader coordinates template lookups by first checking the application's loader and then iterating through the loaders of all registered blueprints.

Configuration and Auto-Reloading

The behavior of the Jinja environment is influenced by the application's configuration:

  • TEMPLATES_AUTO_RELOAD: If set to True, the environment will check for template source changes and reload them. If left as None, it automatically follows the DEBUG flag.
  • EXPLAIN_TEMPLATE_LOADING: When enabled, Flask logs the attempts made by the loader to find a template, which is useful for debugging TemplateNotFound errors.
  • Autoescaping: The App.select_jinja_autoescape() method determines if autoescaping is active based on the template filename. By default, it enables autoescaping for .html, .htm, .xml, .xhtml, and .svg files.
# How DEBUG influences auto_reload in App.debug setter
if self.config["TEMPLATES_AUTO_RELOAD"] is None:
self.jinja_env.auto_reload = value