Debugging Template Resolution
When working with complex Flask applications that use multiple blueprints, it can be difficult to determine why a specific template is being loaded or why a TemplateNotFound error is occurring. This project provides a built-in mechanism to explain the template resolution process.
Enable Template Loading Explanation
To see exactly how Flask is searching for your templates, set the EXPLAIN_TEMPLATE_LOADING configuration key to True.
from flask import Flask
app = Flask(__name__)
app.config["EXPLAIN_TEMPLATE_LOADING"] = True
When this is enabled, the DispatchingJinjaLoader in src/flask/templating.py switches from a "fast" search to an "explained" search. Every time a template is rendered, Flask will log the sequence of attempts it made to find that template.
Interpreting the Resolution Log
The logs are sent to the application's logger at the INFO level. A typical log entry for a failed template lookup looks like this:
Locating template 'missing_template.html':
1: trying loader of application 'myapp'
class: jinja2.loaders.FileSystemLoader
searchpath:
- /path/to/myapp/templates
-> no match
2: trying loader of blueprint 'admin' (myapp.apps.admin)
class: jinja2.loaders.FileSystemLoader
searchpath:
- /path/to/myapp/apps/admin/templates
-> no match
Error: the template could not be found.
The template was looked up from an endpoint that belongs to the blueprint 'admin'.
Maybe you did not place a template in the right folder?
The explain_template_loading_attempts function in src/flask/debughelpers.py generates this output by iterating through:
- The main application's
jinja_loader. - Each registered blueprint's
jinja_loaderin the order they were registered.
Troubleshooting Common Issues
Missing Logs
If you have enabled EXPLAIN_TEMPLATE_LOADING but do not see any output in your console, check your logger configuration. The explanation is logged using app.logger.info. If your log level is set to WARNING or higher, these messages will be suppressed.
import logging
# Ensure the level is at least INFO
app.logger.setLevel(logging.INFO)
Multiple Matches Warning
If multiple loaders find a match for the same template name, Flask will log a warning:
Warning: multiple loaders returned a match for the template.
This often happens when two blueprints define a template with the same name (e.g., layout.html) without namespacing them. Flask will always use the first match it finds based on the registration order.
Blueprint Resolution Order
The DispatchingJinjaLoader._iter_loaders method determines the search order:
# src/flask/templating.py
def _iter_loaders(self, template: str) -> t.Iterator[tuple[Scaffold, BaseLoader]]:
loader = self.app.jinja_loader
if loader is not None:
yield self.app, loader
for blueprint in self.app.iter_blueprints():
loader = blueprint.jinja_loader
if loader is not None:
yield blueprint, loader
Because the application loader is checked first, a template in the main templates folder will always override a template with the same name in a blueprint's folder. If you need a blueprint to provide its own version of a template, ensure the main application does not have a conflicting file at the same path.