In FastAPI, templates are commonly used to render HTML pages dynamically. FastAPI supports templates through libraries like Jinja2, which allows you to inject dynamic content into HTML files.
Table of Contents
Installing Jinja2
pip install jinja2
PythonSetting Up Templates in FastAPI
You need to use Jinja2Templates from fastapi.templating and set up a templates directory.
Project Structure
/my_project
│-- main.py
│-- templates/
│ ├── index.html
│ ├── about.html
PythonExample
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from starlette.responses import HTMLResponse
app = FastAPI()
# Initialize Jinja2 templates
templates = Jinja2Templates(directory="templates")
@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
return templates.TemplateResponse("index.html", {"request": request, "title": "Home Page", "message": "Welcome to FastAPI!"})
@app.get("/about", response_class=HTMLResponse)
async def about(request: Request):
return templates.TemplateResponse("about.html", {"request": request, "title": "About Us", "message": "This is the about page."})
PythonCreating Template Files
Inside the templates/ folder, create index.html and about.html.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
</head>
<body>
<h1>{{ message }}</h1>
</body>
</html>
Pythonabout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
</head>
<body>
<h1>{{ message }}</h1>
</body>
</html>
PythonPassing Dynamic Data
You can pass data dynamically using Jinja2 syntax:
<h1>Hello, {{ username }}!</h1>
PythonModify the route to include the username:
@app.get("/user/{username}", response_class=HTMLResponse)
async def user_profile(request: Request, username: str):
return templates.TemplateResponse("index.html", {"request": request, "title": "User Profile", "message": f"Hello, {username}!"})
PythonNow, visiting /user/John will render:
Hello, John!
PythonUsing Template Inheritance
Instead of repeating HTML structures, use Jinja2 template inheritance.
base.html (Parent Template)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
<header>
<h1>My Website</h1>
<nav>
<a href="/">Home</a> | <a href="/about">About</a>
</nav>
</header>
<main>
{% block content %}{% endblock %}
</main>
</body>
</html>
Pythonindex.html (Child Template)
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<h2>Welcome to FastAPI with Jinja2 Templates</h2>
{% endblock %}
PythonNow, index.html inherits the structure from base.html and overrides only the necessary blocks.
Serving Static Files (CSS, JS, Images)
If you want to serve CSS, JavaScript, or images, create a static/ folder.
Project Structure
/my_project
│-- main.py
│-- templates/
│ ├── base.html
│ ├── index.html
│-- static/
│ ├── styles.css
│ ├── script.js
PythonRegister Static Files
Modify main.py:
from fastapi.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="static"), name="static")
PythonLink Static Files in Templates
Modify base.html:
<link rel="stylesheet" href="{{ url_for('static', path='styles.css') }}">
PythonConclusion
- Jinja2 Templates allow the rendering dynamic HTML pages.
- Template Inheritance helps avoid redundancy.
- Static Files can be served easily.