# How to Use render_template in Flask to Display Dynamic HTML Content

> Learn to correctly use render_template in Flask for dynamic HTML. Pass template names and keyword arguments to generate customized content efficiently.

- Repository: [Pallets/flask](https://github.com/pallets/flask)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Use `render_template` in Flask by passing the template filename and keyword arguments for dynamic data, which Flask automatically combines with request context and Jinja2 to generate HTML.**

When building web applications with the `pallets/flask` repository, you need to generate HTML responses that incorporate dynamic data from your Python code. Learning how to use `render_template` in Flask allows you to leverage Jinja2 templating while automatically injecting request-specific variables like `session`, `g`, and `config`.

## What Is Flask render_template?

`render_template` is a thin wrapper around Jinja2 that lives in [`src/flask/templating.py`](https://github.com/pallets/flask/blob/main/src/flask/templating.py). It bridges your Python view functions and HTML templates by handling context injection and rendering.

## How render_template Works Under the Hood

When you call `render_template` in Flask, the framework executes a six-step pipeline defined in the source code:

### 1. Acquire the Current Application Context

Flask retrieves the active `AppContext` via `app_ctx._get_current_object()` in [`src/flask/app.py`](https://github.com/pallets/flask/blob/main/src/flask/app.py) (lines 589-595). This ensures the template has access to the current application instance.

### 2. Select the Template

The system looks up the template using `ctx.app.jinja_env.get_or_select_template` in [`src/flask/templating.py`](https://github.com/pallets/flask/blob/main/src/flask/templating.py) (lines 45-48). You can pass a single template name or a list of names, and Flask selects the first existing match.

### 3. Update the Template Context

The `App.update_template_context` method in [`src/flask/app.py`](https://github.com/pallets/flask/blob/main/src/flask/app.py) (lines 889-904) merges default context variables (`request`, `session`, `g`, `config`) with any values from registered context processors, while preserving explicitly passed arguments.

### 4. Send the before_render_template Signal

Before rendering, Flask dispatches the `before_render_template` signal from [`src/flask/templating.py`](https://github.com/pallets/flask/blob/main/src/flask/templating.py) (lines 22-27), allowing extensions to modify the template or context.

### 5. Render with Jinja2

The selected `Template` object's `render` method generates the final HTML string, as implemented in [`src/flask/templating.py`](https://github.com/pallets/flask/blob/main/src/flask/templating.py) (lines 22-28).

### 6. Send the template_rendered Signal

Finally, Flask emits the `template_rendered` signal from [`src/flask/templating.py`](https://github.com/pallets/flask/blob/main/src/flask/templating.py) (lines 30-33) for logging or post-processing.

## How to Use render_template in Flask: Practical Example

Here is a complete implementation showing how to use `render_template` with explicit variables and context processors:

```python

# app.py

from flask import Flask, render_template, request

app = Flask(__name__)

# A context processor that adds site-wide variables

@app.context_processor
def inject_site_name():
    return {"site_name": "My Awesome Site"}

@app.route("/")
def index():
    # Explicit data passed to the template

    user = {"username": "alice", "email": "alice@example.com"}
    return render_template("index.html", user=user)

```

```html
<!-- templates/index.html -->
<!doctype html>
<html>
  <head>
    <title>{{ site_name }}</title>
  </head>
  <body>
    <h1>Hello, {{ user.username }}!</h1>
    <p>Your email is {{ user.email }}.</p>
  </body>
</html>

```

In this example, `render_template` combines the explicit `user` dictionary with the `site_name` variable from the context processor. The Jinja2 syntax (`{{ variable }}`) inserts these values into the HTML.

## Key Source Files in the Flask Repository

Understanding how to use `render_template` in Flask requires familiarity with these core files:

- **[`src/flask/templating.py`](https://github.com/pallets/flask/blob/main/src/flask/templating.py)**: Contains the `render_template` function, signal definitions (`before_render_template`, `template_rendered`), and the Flask-aware Jinja environment.
- **[`src/flask/app.py`](https://github.com/pallets/flask/blob/main/src/flask/app.py)**: Implements `App.update_template_context` and context processor registration, managing how request-specific objects merge with template variables.
- **[`src/flask/__init__.py`](https://github.com/pallets/flask/blob/main/src/flask/__init__.py)**: Re-exports `render_template` and related templating utilities for public API access.
- **[`src/flask/helpers.py`](https://github.com/pallets/flask/blob/main/src/flask/helpers.py)**: Demonstrates usage patterns for rendering error pages and utility templates.

## Summary

- **`render_template`** is Flask's standard function for generating HTML from Jinja2 templates.
- The function automatically injects **request context** (`request`, `session`, `g`, `config`) and **context processor** results.
- The rendering pipeline involves six steps: context acquisition, template selection, context updates, pre-render signals, Jinja2 rendering, and post-render signals.
- Source code resides primarily in **[`src/flask/templating.py`](https://github.com/pallets/flask/blob/main/src/flask/templating.py)** and **[`src/flask/app.py`](https://github.com/pallets/flask/blob/main/src/flask/app.py)**.

## Frequently Asked Questions

### What is the difference between render_template and render_template_string?

`render_template` loads a template file from the templates directory using `get_or_select_template`, while `render_template_string` parses a Jinja2 template directly from a string argument. Use `render_template` for file-based templates and `render_template_string` for dynamic template generation from strings.

### How do I pass variables to render_template in Flask?

Pass variables as keyword arguments to `render_template`, such as `render_template("index.html", user=user, items=items)`. These values merge with automatic context variables (request, session, g, config) and context processor output, with explicit arguments taking precedence in case of naming conflicts.

### Why is my render_template not finding the template file?

Flask looks for templates in the `templates` folder relative to your application root. If `render_template` raises a `TemplateNotFound` exception, verify that the template file exists in the correct directory, check for typos in the filename, and ensure your working directory is set correctly when running the application.

### Can I use render_template with Flask blueprints?

Yes, `render_template` works seamlessly with blueprints. When using blueprints, you can reference templates stored in a blueprint's `templates` folder without specifying the full path, as Flask's Jinja environment (configured in [`src/flask/templating.py`](https://github.com/pallets/flask/blob/main/src/flask/templating.py)) automatically handles blueprint-aware template resolution.