Flask provides functions to render Jinja2 templates with context data.
Template Rendering
render_template
render_template(
template_name_or_list: str | Template | list[str | Template],
**context: Any
) -> str
Render a template by name with the given context.
template_name_or_list
str | Template | list[str | Template]
required
The name of the template to render. If a list is given, the first name to exist will be rendered.
The variables to make available in the template as keyword arguments.
Returns: The rendered template as a string.
Example
from flask import render_template
@app.route('/')
def index():
return render_template('index.html', title='Home', user='John')
@app.route('/profile/<username>')
def profile(username):
user = get_user(username)
return render_template(
'profile.html',
user=user,
posts=user.get_posts(),
followers=user.get_followers()
)
# Render first available template
@app.route('/error')
def error():
return render_template(
['errors/custom.html', 'errors/default.html'],
error_code=500
)
render_template_string
render_template_string(source: str, **context: Any) -> str
Render a template from the given source string with the given context.
The source code of the template to render.
The variables to make available in the template as keyword arguments.
Returns: The rendered template as a string.
Never render template strings from untrusted user input. This can lead to security vulnerabilities.
Example
from flask import render_template_string
@app.route('/hello/<name>')
def hello(name):
template = '<h1>Hello {{ name }}!</h1>'
return render_template_string(template, name=name)
# Render dynamic email template
@app.route('/send-email')
def send_email():
email_template = get_email_template_from_db()
content = render_template_string(
email_template,
user=current_user,
action_url=url_for('confirm_email', _external=True)
)
send_mail(current_user.email, content)
return 'Email sent'
Streaming Templates
stream_template
stream_template(
template_name_or_list: str | Template | list[str | Template],
**context: Any
) -> Iterator[str]
Render a template by name with the given context as a stream. This returns an iterator of strings, which can be used as a streaming response from a view.
template_name_or_list
str | Template | list[str | Template]
required
The name of the template to render. If a list is given, the first name to exist will be rendered.
The variables to make available in the template as keyword arguments.
Returns: An iterator of strings.
Example
from flask import stream_template, Response
@app.route('/large-report')
def large_report():
# Stream a large template to avoid loading it all in memory
return Response(stream_template(
'report.html',
data=get_large_dataset(),
title='Annual Report'
))
@app.route('/logs')
def stream_logs():
def generate_logs():
for log in get_log_entries():
yield log
return Response(stream_template(
'logs.html',
logs=generate_logs()
))
stream_template_string
stream_template_string(source: str, **context: Any) -> Iterator[str]
Render a template from the given source string with the given context as a stream. This returns an iterator of strings, which can be used as a streaming response from a view.
The source code of the template to render.
The variables to make available in the template as keyword arguments.
Returns: An iterator of strings.
Example
from flask import stream_template_string, Response
@app.route('/generate')
def generate():
template = '''
<html>
<head><title>{{ title }}</title></head>
<body>
{% for item in items %}
<p>{{ item }}</p>
{% endfor %}
</body>
</html>
'''
return Response(stream_template_string(
template,
title='Generated Page',
items=get_large_item_list()
))
Template Environment
Environment
class Environment(BaseEnvironment)
Works like a regular Jinja2 environment but has some additional knowledge of how Flask’s blueprint works so that it can prepend the name of the blueprint to referenced templates if necessary.
Example
from flask.templating import Environment
# The environment is created automatically by Flask
# Access it via app.jinja_env
@app.before_first_request
def configure_template_env():
# Add custom filters
app.jinja_env.filters['reverse'] = lambda s: s[::-1]
# Add custom globals
app.jinja_env.globals['app_name'] = 'My Application'
# Configure auto-escaping
app.jinja_env.autoescape = True
DispatchingJinjaLoader
class DispatchingJinjaLoader(BaseLoader)
A loader that looks for templates in the application and all the blueprint folders.
This is used internally by Flask and typically doesn’t need to be used directly.
Example
from flask.templating import DispatchingJinjaLoader
# Flask automatically creates this loader
# It searches for templates in:
# 1. Application template folder
# 2. Blueprint template folders
# Template lookup order:
# - app/templates/page.html
# - blueprint1/templates/page.html
# - blueprint2/templates/page.html
Template Context
Flask automatically makes several objects available in the template context:
config - The current configuration object
request - The current request object
session - The current session object
g - The request-bound object for global variables
url_for() - The url_for function
get_flashed_messages() - The get_flashed_messages function
Example
<!-- In your template -->
<h1>{{ config['APP_NAME'] }}</h1>
{% if request.method == 'POST' %}
<p>Form submitted</p>
{% endif %}
{% if session.user_id %}
<p>Welcome, user {{ session.user_id }}!</p>
{% endif %}
<a href="{{ url_for('profile', username=g.user.name) }}">Profile</a>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
{% endif %}
{% endwith %}
Custom Context Processors
You can add your own variables to the template context using context processors:
Example
@app.context_processor
def inject_user():
return dict(current_user=get_current_user())
@app.context_processor
def utility_processor():
def format_price(amount):
return f"${amount:.2f}"
return dict(format_price=format_price)
# Now available in all templates:
# {{ current_user.name }}
# {{ format_price(19.99) }}
Template Filters
Add custom filters to process template variables:
Example
@app.template_filter('reverse')
def reverse_filter(s):
return s[::-1]
@app.template_filter('pluralize')
def pluralize_filter(count, singular, plural):
return singular if count == 1 else plural
# Usage in templates:
# {{ "hello" | reverse }} -> "olleh"
# {{ count | pluralize('item', 'items') }}
Template Tests
Add custom tests for template conditions:
Example
@app.template_test('prime')
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
# Usage in templates:
# {% if value is prime %}
# {{ value }} is a prime number
# {% endif %}