FastAPI 是一个现代、快速(高性能)的 Web 框架,用于基于标准 Python 类型提示使用 Python 3.7+ 构建 API。FastAPI 的主要功能之一是它能够与模板集成以创建动态网页。这允许您呈现 HTML 模板并向用户提供动态内容,这对于构建 Web 应用程序至关重要。
在此博客中,我们将探讨如何在 FastAPI 中使用模板创建动态网页。我们将介绍设置 Jinja2 模板、将数据传递给模板以及呈现 HTML 页面的基础知识。我们还将提供一些实用的演示来帮助您入门。
在 FastAPI 中设置 Jinja2 模板
Jinja2 是一个强大的 Python 模板引擎,可让您将 HTML 结构与 Python 代码分开。FastAPI 开箱即用地支持 Jinja2,使呈现模板变得容易。
步骤 1:安装 Jinja2
首先,您需要安装 Jinja2 包。您可以使用 pip 执行此操作:
pip install jinja2
步骤 2:创建模板目录
接下来,在项目根目录中创建一个名为 templates 的目录。您将在此处存储 HTML 模板。
my_fastapi_project/
├── main.py
└── templates/
└── index.html
步骤 3:编写 HTML 模板
在 templates 目录中创建一个名为 index.html 的文件,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FastAPI Template Example</title>
</head>
<body>
<h1>Hello, {{ name }}!</h1>
<p>Welcome to FastAPI with Jinja2 templates.</p>
</body>
</html>
步骤 4:配置 FastAPI 以使用模板
在您的 main.py 文件中,配置 FastAPI 以使用 Jinja2 模板。您需要使用 fastapi.templating 模块中的 Jinja2Templates 类。
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request, "name": "FastAPI User"})
在此示例中,我们导入必要的模块并创建 Jinja2Templates 的实例,将其指向 templates 目录。然后,我们定义一个呈现 index.html 模板的路由并将 name 变量传递给它。
演示
让我们创建更多演示来演示如何使用模板在 FastAPI 中呈现动态内容。
演示 1:呈现项目列表
在 templates 目录中创建一个名为 items.html 的新模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Items List</title>
</head>
<body>
<h1>Items</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>
更新您的 main.py 以包含呈现此模板的新路由:
@app.get("/items/", response_class=HTMLResponse)
async def read_items(request: Request):
items = ["Item 1", "Item 2", "Item 3"]
return templates.TemplateResponse("items.html", {"request": request, "items": items})
演示 2:呈现用户数据
在 templates 目录中创建一个名为 user.html 的新模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Profile</title>
</head>
<body>
<h1>User Profile</h1>
<p>Name: {{ user.name }}</p>
<p>Age: {{ user.age }}</p>
<p>Email: {{ user.email }}</p>
</body>
</html>
更新您的 main.py 以包含呈现此模板的新路由:
@app.get("/user/", response_class=HTMLResponse)
async def read_user(request: Request):
user = {
"name": "John Doe",
"age": 30,
"email": "john.doe@example.com"
}
return templates.TemplateResponse("user.html", {"request": request, "user": user})
演示 3:呈现表单
在 templates 目录中创建一个名为 form.html 的新模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form</title>
</head>
<body>
<h1>Form</h1>
<form action="/submit/" method="post">
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<button type="submit">Submit</button>
</form>
</body>
</html>
更新您的 main.py 以包含一个呈现此模板的新路由和一个处理表单提交的路由:
from fastapi import Form
@app.get("/form/", response_class=HTMLResponse)
async def form(request: Request):
return templates.TemplateResponse("form.html", {"request": request})
@app.post("/submit/", response_class=HTMLResponse)
async def submit(request: Request, name: str = Form(...)):
return templates.TemplateResponse("index.html", {"request": request, "name": name})
在此示例中,我们创建一个向 /submit/ 路由提交数据的表单。submit 函数处理表单提交并使用提交的名称呈现 index.html 模板。
演示 4:条件渲染
在模板目录中创建一个名为 conditional.html 的新模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Conditional Rendering</title>
</head>
<body>
<h1>Conditional Rendering Example</h1>
{% if user.is_authenticated %}
<p>Welcome back, {{ user.name }}!</p>
{% else %}
<p>Please log in to see your profile.</p>
{% endif %}
</body>
</html>
更新您的 main.py 以包含呈现此模板的新路由:
@app.get("/conditional/", response_class=HTMLResponse)
async def conditional(request: Request):
user = {
"is_authenticated": True,
"name": "Jane Doe"
}
return templates.TemplateResponse("conditional.html", {"request": request, "user": user})
演示 5:循环遍历字典
在 templates 目录中创建一个名为 dictionary.html 的新模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dictionary Loop</title>
</head>
<body>
<h1>Dictionary Loop Example</h1>
<ul>
{% for key, value in data.items() %}
<li>{{ key }}: {{ value }}</li>
{% endfor %}
</ul>
</body>
</html>
更新您的 main.py 以包含呈现此模板的新路由:
@app.get("/dictionary/", response_class=HTMLResponse)
async def dictionary(request: Request):
data = {
"Name": "Alice",
"Age": 25,
"Email": "alice@example.com"
}
return templates.TemplateResponse("dictionary.html", {"request": request, "data": data})
演示 6:包含模板
在 templates 目录中创建一个名为 base.html 的新基础模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block 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>
<footer>
<p>? 2024 My Website</p>
</footer>
</body>
</html>
创建一个名为 about.html 的新模板,该模板扩展了 base.html:
{% extends "base.html" %}
{% block title %}About Us{% endblock %}
{% block content %}
<h2>About Us</h2>
<p>Welcome to the about page of our website.</p>
{% endblock %}
更新您的 main.py 以包含呈现此模板的新路由:
@app.get("/about/", response_class=HTMLResponse)
async def about(request: Request):
return templates.TemplateResponse("about.html", {"request": request})
演示 7:使用静态文件
FastAPI 还可以提供静态文件(例如 CSS 和 JavaScript)来增强您的模板。
在项目根目录中创建一个名为 static 的目录,并在其中放置一个名为 style.css 的 CSS 文件:
my_fastapi_project/
├── main.py
├── static/
│ └── style.css
└── templates/
└── index.html
向 style.css 添加一些样式:
body {
font-family: Arial, sans-serif;
}
header {
background-color: #f8f9fa;
padding: 10px;
}
nav a {
margin: 0 10px;
text-decoration: none;
color: #007bff;
}
更新 base.html 模板以包含 CSS 文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/style.css">
<title>{% block 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>
<footer>
<p>? 2024 My Website</p>
</footer>
</body>
</html>
更新 main.py 以包含必要的静态文件配置:
from fastapi.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="static"), name="static")
演示 8:模板继承和块
创建一个名为 layout.html 的基本模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<header>
<h1>My App</h1>
</header>
<nav>
<a href="/">Home</a> |
<a href="/about/">About</a> |
<a href="/contact/">Contact</a>
</nav>
<div>
{% block content %}{% endblock %}
</div>
</body>
</html>
创建一个扩展 layout.html 的 contact.html 模板:
{% extends "layout.html" %}
{% block title %}Contact Us{% endblock %}
{% block content %}
<h2>Contact Us</h2>
<p>Feel free to reach out via email or phone.</p>
{% endblock %}
更新您的 main.py 以包含呈现 contact.html 模板的路由:
@app.get("/contact/", response_class=HTMLResponse)
async def contact(request: Request):
return templates.TemplateResponse("contact.html", {"request": request})
使用 FastAPI 中的模板可让您轻松创建动态网页。通过集成 Jinja2 模板,您可以将 HTML 结构与 Python 代码分开,从而使您的 Web 应用程序更易于维护和扩展。本博客提供的演示应该可以帮助您开始在 FastAPI 中使用模板。祝您编码愉快!