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:
- Configuration via
jinja_options: This dictionary in theAppclass contains options passed directly to the Jinja environment constructor. - Custom Environment Classes: By overriding the
jinja_environmentclass attribute on a subclass ofApp, 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()oradd_template_global(). These are added tojinja_env.globals. - Tests: Registered via
@app.template_test()oradd_template_test(). These are added tojinja_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.
Scaffold.template_folder: Both the application and blueprints can define atemplate_folder. This path is relative to theroot_pathof the object.Scaffold.jinja_loader: This property creates ajinja2.loaders.FileSystemLoaderpointing to the configuredtemplate_folder.DispatchingJinjaLoader: TheAppclass usescreate_global_jinja_loader()to instantiate aDispatchingJinjaLoader. 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 toTrue, the environment will check for template source changes and reload them. If left asNone, it automatically follows theDEBUGflag.EXPLAIN_TEMPLATE_LOADING: When enabled, Flask logs the attempts made by the loader to find a template, which is useful for debuggingTemplateNotFounderrors.- 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.svgfiles.
# How DEBUG influences auto_reload in App.debug setter
if self.config["TEMPLATES_AUTO_RELOAD"] is None:
self.jinja_env.auto_reload = value