Skillversitas

Templates

For HTML-heavy endpoints (server-rendered pages, email bodies, report pages), FastAPI integrates Jinja2 templates through the Jinja2Templates class. You pass a templates directory, render a template with context variables, and return the TemplateResponse - all while keeping the rest of the API JSON-based.

Setup

pip install jinja2
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates

app = FastAPI()
templates = Jinja2Templates(directory="templates")

@app.get("/hello/{name}")
def hello(request: Request, name: str):
    return templates.TemplateResponse("hello.html", {"request": request, "name": name})

Recent Starlette versions still expect the request object in the context for URL generation; pass it explicitly as shown.

The Template File

<!doctype html>
<html>
  <head><title>Hello</title></head>
  <body>
    <h1>Hello, {{ name }}!</h1>
    <a href="/">Home</a>
  </body>
</html>

Template Features

  • Variables: {{ name }} with autoescaping on by default in Jinja2.
  • Control flow: {% for item in items %} ... {% endfor %}, {% if %}.
  • Inheritance: {% extends "base.html" %} with {% block content %} for shared layouts.
  • Filters: {{ name | upper }}, {{ price | round(2) }}.
<ul>
{% for item in items %}
  <li>{{ item.name }} - ${{ item.price }}</li>
{% endfor %}
</ul>

Generating URLs in Templates

Use the url_for helper with the request object to build URLs that stay correct if the app is mounted at a subpath:

<a href="{{ url_for('hello', name='Ada') }}">Greet Ada</a>

Summary

Render HTML with Jinja2Templates: pass a templates directory, return TemplateResponse("page.html", context) with the request in the context, and use Jinja2 syntax for variables, loops, and base-template inheritance. Templates coexist happily with JSON endpoints in the same app.