现在位置: 首页 > FastAPI 教程 > 正文

Jinja2 模板

本章你将学会在 FastAPI 中配置 Jinja2 模板引擎,用静态文件和模板继承构建完整的 HTML 页面。


FastAPI 的两种渲染模式

FastAPI 默认返回 JSON(适合 API),但也能返回 HTML(适合 SSR)。

两种模式可以共存——同一个项目既可以提供 JSON API,也可以渲染网页。


挂载静态文件

静态文件(CSS、JS、图片)通过 StaticFiles 挂载到指定路径。

实例

# 文件路径:main.py
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()

# 将 static/ 目录挂载到 /static 路径
# 访问 /static/css/style.css → 实际读取 static/css/style.css
app.mount("/static", StaticFiles(directory="static"), name="static")

模板中引用静态文件:

实例

<link rel="stylesheet" href="/static/css/style.css">
<img src="/static/images/logo.png">

配置 Jinja2 模板

实例

# 文件路径:main.py
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")

# 指定模板目录
templates = Jinja2Templates(directory="templates")

@app.get("/")
def index(request: Request):       # 注意:模板路由必须接收 Request 参数
    """博客首页"""
    return templates.TemplateResponse(
        "index.html",              # 模板文件名
        {                          # context 数据
            "request": request,    # request 必须传入(Jinja2Templates 要求)
            "title": "RUNOOB 博客"
        }
    )

FastAPI 的模板渲染与 Flask 有两个关键区别:1. 视图函数必须接收 request: Request 参数;2. request 必须作为 context 传给模板。如果漏传 request,模板中的 url_for 功能会失效。


创建 base.html 父模板

实例

<!-- 文件路径:templates/base.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}RUNOOB 博客{% endblock %}</title>
    <link rel="stylesheet" href="/static/css/style.css">
    {% block extra_head %}{% endblock %}
</head>
<body>
    <header class="navbar">
        <a href="/" class="logo">RUNOOB 博客(FastAPI)</a>
        <nav>
            <a href="/">首页</a>
            <a href="#">关于</a>
        </nav>
    </header>

    <main class="container">
        {% block content %}{% endblock %}
    </main>

    <footer class="footer">
        <p>© 2024 RUNOOB 博客. Powered by FastAPI.</p>
    </footer>
</body>
</html>

创建 index.html 子模板

实例

<!-- 文件路径:templates/index.html -->
{% extends 'base.html' %}

{% block title %}{{ title }}{% endblock %}

{% block content %}
<h2 class="section-title">最新文章</h2>
<p>文章列表将在后续章节展示。</p>
{% endblock %}

FastAPI 模板中的 url_for()

与 Flask 类似,FastAPI 也支持 url_for(),但需要先给路由起名字。

实例

@app.get("/post/{post_id}", name="post_detail")   # name= 给路由命名
def post_detail(request: Request, post_id: int):
    return templates.TemplateResponse("post_detail.html",
        {"request": request, ...})

实例

<!-- 模板中引用 -->
<a href="{{ url_for('post_detail', post_id=3) }}">文章 3</a>

创建基础 CSS 样式

实例

/* 文件路径:static/css/style.css */
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: #f5f5f5;
    color: #333;
}

.navbar {
    display: flex; justify-content: space-between; align-items: center;
    padding: 16px 40px; background: #fff;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.navbar .logo {
    font-size: 22px; font-weight: bold;
    color: #009688; text-decoration: none;
}

.navbar nav a {
    margin-left: 20px; text-decoration: none; color: #333;
}

.container { max-width: 960px; margin: 40px auto; padding: 0 20px; }

.footer { text-align: center; padding: 20px; color: #999; border-top: 1px solid #eee; }

.section-title { font-size: 24px; margin-bottom: 20px; }

本章小结

本章你学会了 FastAPI 中的前端渲染配置:StaticFiles 挂载静态资源、Jinja2Templates 配置模板目录、TemplateResponse 返回 HTML、与 Flask 在模板渲染上的关键差异(Request 参数必须传入)。