目录
[一、FastAPI 的请求与响应](#一、FastAPI 的请求与响应)
[二、FastAPI 获取请求数据](#二、FastAPI 获取请求数据)
[1. 查询参数](#1. 查询参数)
[2. 路径参数](#2. 路径参数)
[3. 请求头](#3. 请求头)
[4. Cookie](#4. Cookie)
[三、FastAPI 的响应机制](#三、FastAPI 的响应机制)
[1. 返回 JSON 数据](#1. 返回 JSON 数据)
[2. 返回 Pydantic Model](#2. 返回 Pydantic Model)
[3. 状态码配置](#3. 状态码配置)
[HTTP 常见状态码](#HTTP 常见状态码)
[4. 重定向](#4. 重定向)
[5. 自定义 Response Header](#5. 自定义 Response Header)
[四、Pydantic 数据模型](#四、Pydantic 数据模型)
[1. 为什么 FastAPI 依赖 Pydantic](#1. 为什么 FastAPI 依赖 Pydantic)
[2. 定义 Pydantic Model](#2. 定义 Pydantic Model)
[五、Pydantic 与 Request / Response](#五、Pydantic 与 Request / Response)
[1. 作为 Request Body 处理请求](#1. 作为 Request Body 处理请求)
[2. Response Model](#2. Response Model)
[3. Pydantic v2 常用方法](#3. Pydantic v2 常用方法)
[4. Model Config](#4. Model Config)
[5. 模型继承](#5. 模型继承)
[六、什么是 Dependency Injection](#六、什么是 Dependency Injection)
[1 缺乏依赖注入的弊端](#1 缺乏依赖注入的弊端)
[2 依赖注入逻辑与处理流程](#2 依赖注入逻辑与处理流程)
[七、用数据库理解 Depends 与 yield](#七、用数据库理解 Depends 与 yield)
[1. 最基本的 Depends](#1. 最基本的 Depends)
[2. 带有资源清理能力的 yield 依赖](#2. 带有资源清理能力的 yield 依赖)
[3. 在装饰器中声明依赖](#3. 在装饰器中声明依赖)
[4. 全局依赖](#4. 全局依赖)
一、FastAPI 的请求与响应
在上一篇中,我们建立了 FastAPI 的基础认知,明确了客户端与服务端的交互建立在标准的请求与响应循环之上:

在实际的 API 开发中,需要将这一生命周期的中间环节进行细化拆解。Web 服务调用的本质,就是提取 HTTP 请求中的不同数据分块并将其映射为 Python 函数参数,再将函数的执行结果包装为符合 HTTP 协议规范的响应对象
展开后的完整请求与响应数据流向如下:

在该数据流模型中:
-
请求(HTTP Request):客户端发送的请求数据分布在路径、查询字符串、请求头、Cookie 以及请求体中。FastAPI 负责从这些位置提取数据、执行自动化校验与类型转换,并将其注入到路径操作函数中
-
业务处理(Python Function):路径操作函数接收解包后的数据,执行具体的业务逻辑、数据持久化或外部服务调用
-
响应(HTTP Response):业务逻辑执行完毕后,FastAPI 将 Python 返回值序列化为指定格式的响应体,并结合状态码、响应头与 Cookies 组装成完整的 HTTP 响应输出给客户端
二、FastAPI 获取请求数据
客户端发送给 HTTP 服务端的数据通常分布在请求的不同位置。FastAPI 提供了统一强类型的声明方式,用来提取、转换并校验来自 Query、Path、Headers 以及 Cookies 的数据
为了保证代码可读性与兼容性,FastAPI 推荐使用 Python 标准库 typing.Annotated 来组合 "字段类型"
1. 查询参数
查询参数附着在 URL 问号后(如 /users?page=1&size=10)。通过 Query 类,可对参数施加默认值设置、可选性声明以及数值或字符串范围约束
python
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/users")
async def get_users(
page: Annotated[int, Query(ge=1, description="当前页码,必须大于等于 1")] = 1,
size: Annotated[int, Query(ge=1, le=100)] = 10,
keyword: Annotated[str | None, Query(max_length=20)] = None
):
return {"page": page, "size": size, "keyword": keyword}
输出示例:

-
默认值:给参数赋予默认值即代表该参数可选;声明为 str | None 且默认值为 None 则允许请求时不传该参数
-
类型自动转换:请求中的字符串数据会被自动转换为 Python 的 int 类型
-
参数验证:ge(Greater than or Equal)表示大于等于,le(Less than or Equal)表示小于等于,max_length 限制最大长度。若客户端传入不合规数值,FastAPI 会自动拦截并返回 HTTP 422 错误
2. 路径参数
路径参数嵌于 URL 路径模板之中(如 /users/{user_id})。使用 Path 类可以为其添加额外的格式约束
python
@app.get("/users/{user_id}")
async def get_user(
user_id: Annotated[int, Path(ge=1, title="用户唯一 ID")]
):
return {"user_id": user_id}
输出示例:

路径参数的提取与处理流程如下:
python
请求路径 /users/1001
↓
匹配 {user_id}
↓
Path 约束校验
↓
提取为字符串 "10"
↓
自动类型转换为 int(10)
↓
注入函数形参 user_id
与查询参数不同,路径参数是 URL 结构的组成部分,因此不能将其定义为可选参数(即不建议为其设置默认值)
3. 请求头
通过 Header 类可以从 HTTP 请求头中提取信息
python
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/info")
async def get_info(
user_agent: Annotated[str | None, Header()] = None,
accept_language: Annotated[str | None, Header(alias="Accept-Language", default=None)] = None
):
return {"user_agent": user_agent, "accept_language": accept_language}
输出示例:

标准的 HTTP Header 名称使用下划线以外的破折号连接(例如 User-Agent、Accept-Language)。但在 Python 中,标准变量名不能包含短横线
FastAPI 内置了命名映射机制:声明为 user_agent 的形参会自动匹配请求头中的 User-Agent。如果需要严格指定不常规的 Header 字段名,可以通过 alias 参数进行显示的名称别名映射
4. Cookie
提取客户端传来的 Cookie 数据,其声明语法与 Header 保持一致:
python
from fastapi import FastAPI, Cookie
app = FastAPI()
@app.get("/profile")
async def profile(
session_id: Annotated[str | None, Cookie()] = None
):
return {"session_id": session_id}
输出示例:

Header 与 Cookie
| 来源 | 常见用途 | 典型字段 |
|---|---|---|
| Header | 传递元数据、客户端信息、认证 Token | Authorization(身份令牌)、User-Agent(客户端环境)、Content-Type(请求数据格式) |
| Cookie | 保持会话状态、会话跟踪、存储客户端状态 | session_id(会话标识)、用户偏好设置 |
三、FastAPI 的响应机制
在处理完 HTTP 请求后,服务端需要将处理结果构建为符合 HTTP 协议的输出。FastAPI 提供了丰富灵活的响应构建机制,支持从简单的字典数据返回到复杂的自定义 HTTP 响应报头控制
1. 返回 JSON 数据
在路径操作函数中,最基础的响应方式是直接返回 Python 的原生数据结构(如 dict)。FastAPI 底层会自动将其转换为符合 JSON 规范的数据格式,并附带默认的状态码 200 OK
python
@app.get("/user")
async def get_user():
return {
"id": 1,
"name": "Tom"
}
2. 返回 Pydantic Model
除了返回原生数据类型,路径操作函数还可以直接返回一个 Pydantic 实例,或通过类型注解声明返回值的结构
python
from pydantic import BaseModel
app = FastAPI()
class UserResponse(BaseModel):
id: int
name: str
@app.get("/user")
async def get_user() -> UserResponse:
return UserResponse(id=1, name="Tom")
此处表明,Pydantic 模型不仅参与请求体的解析与校验,同时也在 Response 数据序列化阶段起着定义返回规范的作用
输出示例:

3. 状态码配置
标准 RESTful API 规范要求针对不同的操作结果返回恰当的 HTTP 状态码。在 FastAPI 中,可以通过路径操作装饰器的 status_code 参数显式定义默认返回的状态码
python
from fastapi import FastAPI, status
app = FastAPI()
@app.post("/users", status_code=status.HTTP_201_CREATED)
async def create_user():
return {"message": "用户创建成功"}
输出示例:

HTTP 常见状态码
HTTP 协议的状态码划分为五个区间,开发中常用的标准状态码如下:
-
2xx 成功类
-
200 OK:请求已被成功处理(默认状态码)
-
201 Created:请求成功且新资源已成功创建(常见于 POST 请求)
-
204 No Content:请求成功处理,但响应体无任何返回内容(常见于 DELETE 请求)
-
-
3xx 重定向类
-
301 / 308 Permanent Redirect:永久重定向
-
302 / 307 Temporary Redirect:临时重定向
-
-
4xx 客户端错误类
-
400 Bad Request:客户端发送的请求报文存在语法错误
-
404 Not Found:请求的 URL 资源在服务端不存在
-
422 Unprocessable Entity:请求语法正确,但内部包含的参数未通过类型校验(FastAPI 校验失败默认返回码)
-
-
5xx 服务端错误类
- 500 Internal Server Error:服务端内部代码出现未捕获的运行时异常
4. 重定向
当需要引导客户端跳转到新的 URL 路径时,可以借助 RedirectResponse 类返回 3xx 类的响应报文
python
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/old")
async def old_route():
return RedirectResponse(url="/new", status_code=307)
@app.get("/new")
async def new_route():
return {"message": "此页面为重定向目标页面"}
输出示例:

处理流程:
访问旧地址 /old
↓
返回 RedirectResponse (307)
↓
客户端自动请求 /new
↓
获取目标页面响应
5. 自定义 Response Header
一个完整的 HTTP Response 由三部分构成:
HTTP Response
│
├── Status Code(状态码,如 200 OK)
├── Headers(响应头,如 Content-Type, Custom Header)
└── Body(响应体,如 JSON 字符串数据)
当业务逻辑需要在响应头中注入自定义属性(例如分页总数、Token 或跟踪 ID)时,可以在路径操作函数中引入 Response 参数进行动态设置
python
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/custom-header")
async def set_custom_header(response: Response):
response.headers["X-Custom-Header"] = "Value-123"
response.headers["X-Process-Time"] = "0.015"
return {"message": "响应报头已注入自定义信息"}
输出示例:

通过这种方式,开发者不仅能够控制返回的数据内容,还具备了操作完整 HTTP 响应报文的能力
四、Pydantic 数据模型
在前面的章节中,无论是处理 Request Body 还是校验 Response 结构,都多次出现了 BaseModel 。Pydantic 作为 FastAPI 的核心数据引擎,承载了数据解析、校验、转换与序列化的任务
1. 为什么 FastAPI 依赖 Pydantic
在传统的 Web 服务开发中,如果缺失自动化的数据校验层,处理客户端传入的 JSON 数据将变得非常繁琐
传统手工处理模式
假设客户端提交了如下请求载荷:
python
{
"name": "Tom",
"age": "abc"
}
在缺少 Pydantic 的情况下,后端业务代码需要显式地编写大量防御性逻辑:
python
解析原始 JSON 文本
↓
检查必需字段是否存在?
↓
检查数据类型是否匹配
↓
检查数值范围是否合法?
↓
数据手动类型转换
↓
捕获异常并手动组装 400/422 错误响应
这种模式会导致业务逻辑中充斥着大量的重复校验代码,难以维护且极易疏漏
Pydantic 处理模式
Pydantic 通过声明式的数据模型,将底层的 HTTP 无类型 JSON 数据转化为 Python 中的强类型对象:
JSON 数据 (HTTP 协议层)
↓
Pydantic Model
↓
自动结构解析与提取
↓
严格类型校验与隐式强转
↓
Python Object (业务逻辑层)
借助 Pydantic,FastAPI 能够在请求进入业务函数之前,自动完成格式拦截与类型转换;若校验失败,则自动组装统一规范的 HTTP 422 异常响应,无需编写防御性代码
2. 定义 Pydantic Model
在 Pydantic 中,定义数据模型需要继承自 pydantic.BaseModel 类,并利用 Python 强类型注解标记各个属性
python
from pydantic import BaseModel, Field
class User(BaseModel):
name: str = Field(min_length=2, max_length=20, description="用户名")
age: int = Field(gt=0, lt=150, description="年龄")
email: str | None = Field(default=None, description="电子邮箱")
is_active: bool = True
字段配置与规则解析
在上述模型定义中,包含了四种常见的字段配置方式:
-
**必填字段:**如 name 和 age。没有声明默认值,在实例化或反序列化时客户端必须显式提供,否则校验报错
-
**可选字段:**如 email。类型允许为 None,且默认值设为 None。如果客户端未传该字段,模型会将其赋予默认值 None
-
**带默认值的字段:**如 is_active。如果不传该字段,模型会自动使用默认值 True
-
**Field 约束配置:**Field() 用于对属性追加元数据与校验条件
-
description:字段文本说明,用于自动渲染 OpenAPI/Swagger UI 文档
-
gt(Greater than)/ lt(Less than):设置数值的严格上下限(gt=0 即大于 0)
-
min_length / max_length:限制字符串长度范围
-
五、Pydantic 与 Request / Response
在 FastAPI 框架中,Pydantic 模型不仅用于对客户端提交的请求数据进行校验,还充当了服务端数据响应转换的核心工具。通过将其贯穿于请求与响应两端,可以建立起清晰、类型安全且易于维护的数据处理链路
1. 作为 Request Body 处理请求
将 Pydantic 模型作为参数声明时,FastAPI 会自动将 HTTP 请求体中的 JSON 数据反序列化为该模型的实例
python
from pydantic import BaseModel
from fastapi import FastAPI
app = FastAPI()
class UserCreate(BaseModel):
username: str
email: str
password: str
@app.post("/users")
async def create_user(user: UserCreate):
return {"status": "created", "username": user.username}
参数输入示例:

如果在校验环节发现数据不符合模型要求(例如缺少必填字段),请求将被立刻拦截,并直接返回 HTTP 422 异常报文,不会触发后续的业务逻辑函数
2. Response Model
在业务系统中,数据库或服务内部的数据模型往往包含敏感信息(如加密密钥等),这些数据绝不能直接抛给客户端
通过在路径操作装饰器中配置 response_model 参数, Fast API 会自动按照声明的响应模型对数据进行二次筛选与清洗
python
app = FastAPI()
# 业务或数据库层数据结构(包含敏感字段 password_hash)
db_user = {
"id": 1001,
"username": "johndoe",
"password_hash": "pbkdf2:sha256:260000$xyz123...",
"email": "john@example.com"
}
# 暴露给对外 API 的数据模型
class UserResponse(BaseModel):
id: int
username: str
email: str
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
# 此处返回包含了 password_hash 的完整数据字典
return db_user
输出示例:

数据过滤流程如下:
Database Model / 内部完整数据 (包含 password_hash)
↓
Response Model (仅定义 id, username, email)
↓
自动过滤剔除未定义属性 (过滤 password_hash)
↓
Client Response (安全的 JSON 数据)
尽管函数内部返回了完整的 _db_user 字典,但经过 response_model=UserResponse 过滤后,输出给客户端的 JSON 数据中将彻底剔除 password_hash 字段,确保了系统敏感数据的安全
3. Pydantic v2 常用方法
在现行的 Pydantic v2 版本中,对模型操作的底层 API 进行了一次重构。在阅读旧教程或迁移旧代码时,需要注意对应方法的替代关系:
| 功能定义 | Pydantic v2 推荐 API | Pydantic v1 旧版 API(已废弃) |
|---|---|---|
| 转为 Python 字典 | model.model_dump() | model.dict() |
| 转为 JSON 字符串 | model.model_dump_json() | model.json() |
| 从字典解析生成模型对象 | Model.model_validate(data) | Model.parse_obj(data) |
| 从 JSON 串解析模型对象 | Model.model_validate_json(json_str) | Model.parse_raw(json_str) |
| 复制并修改模型对象 | model.model_copy() | model.copy() |
| 生成 JSON Schema 结构 | Model.model_json_schema() | Model.schema() |
4. Model Config
当 FastAPI 需要结合第三方 ORM 框架(如 SQLAlchemy)使用时,由于 ORM 对象通常是通过属性(user.id)而非字典索引(user"id")来访问数据的,直接进行序列化会抛出异常
可以在 Pydantic 模型中增加 model_config 配置,开启 from_attributes=True 支持
python
from pydantic import BaseModel, ConfigDict
class UserResponse(BaseModel):
id: int
username: str
email: str
# Pydantic v2 配置语法
model_config = ConfigDict(from_attributes=True)
当配置了 from_attributes=True(在 v1 中被称为 orm_mode = True)后,Pydantic 将自动兼容通过 getattr() 方式提取 ORM 实例中的成员变量,从而无需手动将 ORM 对象转换为字典即可直接用于 response_model
5. 模型继承
在业务接口中,针对同一实体(如 "用户"),不同的接口场景所需的字段集合往往高度重合但存在微小差异。利用 Python 的类继承机制,可以实现数据模型的模块化复用
python
# 1. 基础模型:提取共享的通用属性
class UserBase(BaseModel):
username: str
# 2. 创建请求模型:继承基础模型,并扩展专属入参
class UserCreate(UserBase):
password: str
# 3. 响应模型:继承基础模型,并扩展服务端生成的字段
class UserResponse(UserBase):
id: int
is_active: bool = True
model_config = ConfigDict(from_attributes=True)
通过这种组合结构,可以极大减少重复的字段定义,确保数据字段修改时仅需在基类调整一次即可自动同步
六、什么是 Dependency Injection
依赖注入(Dependency Injection,简称 DI)是现代软件工程中一种重要的设计模式。在 FastAPI 中,依赖注入不仅是一项高级特性,更是整个框架组织代码、共享资源和管理对象生命周期的底层核心机制
在直接使用 FastAPI 提供的 Depends 之前,有必要先明确该模式所解决的痛点
1 缺乏依赖注入的弊端
假设在一个标准的 Web 应用中,每个 API 接口都需要操作数据库。如果不采用依赖注入机制,传统的代码组织方式通常如下:
python
@app.get("/users")
def get_users():
db = create_db_connection() # 手动创建资源
users = db.query_users()
db.close() # 手动释放资源
return users
@app.get("/books")
def get_books():
db = create_db_connection() # 逻辑重复
books = db.query_books()
db.close() # 逻辑重复
return books
@app.get("/orders")
def get_orders():
db = create_db_connection() # 逻辑重复
orders = db.query_orders()
db.close() # 逻辑重复
return orders
这种模式存在以下显著缺陷:
-
代码高度冗余:相同的资源创建与关闭逻辑重复出现在每一个路径操作函数中
-
强耦合难以维护:一旦数据库连接的创建逻辑发生变更,所有包含创建代码的路由函数都需要同步修改
-
难以测试:路由函数内部硬编码了具体的资源创建逻辑,导致在自动化测试阶段无法轻松更换为 Mock 对象或测试数据库
2 依赖注入逻辑与处理流程
路径操作函数的核心职责应当是处理 "业务逻辑",而不应该关心 "资源是如何被创建和销毁的"
符合单一职责原则的路由函数,其理想诉求仅仅是:我需要一个数据库 Session,请直接传给我
依赖注入机制正是基于这一理念运行的。通过将资源的控制权交由框架统一调度,控制流发生了反转,其完整的执行如下所示:

概括而言:
依赖注入的核心思想,是让函数通过参数显式声明 "自己需要什么",并由框架负责该依赖项的实例化、传递以及后续的资源清理,而非由函数内部自行创建和管理依赖
七、用数据库理解 Depends 与 yield
通过结合数据库 Session 的管理场景,能够直观地理解 FastAPI 中 Depends 的工作原理以及带有清理机制的 yield 依赖模式
1. 最基本的 Depends
在最基础的场景下,依赖项是一个普通的 Python 函数。通过 Depends(),FastAPI 会自动调用该依赖函数,并将返回值注入到路径操作函数的参数中
python
from typing import Annotated
from fastapi import FastAPI, Depends
app = FastAPI()
# 模拟数据库会话类
class DBSession:
def query(self):
return ["User A", "User B"]
def close(self):
print("数据库已关闭")
# 依赖项函数
def get_db():
db = DBSession()
return db
@app.get("/users")
async def get_users(
db: Annotated[DBSession, Depends(get_db)]
):
return db.query()
其内部的执行流程如下:
python
HTTP Request
↓
FastAPI 框架接收请求
↓
解析到 Depends(get_db)
↓
自动调用执行 get_db()
↓
获取返回的 db 实例
↓
将 db 注入到 get_users 函数中
↓
执行 get_users() 路由业务逻辑
↓
返回 HTTP Response
2. 带有资源清理能力的 yield 依赖
在实际开发中,数据库连接等资源在请求处理完毕后必须被关闭或释放。普通的 return 语句无法在响应生成后继续执行清理代码
为了解决这一问题,FastAPI 支持使用 Python 生成器(yield)来定义包含上下文生命周期管理的依赖项
python
def get_db():
db = DBSession()
try:
# yield 将资源提交给路由函数使用,并在此暂停
yield db
finally:
# 响应处理完毕后,继续执行下方的清理逻辑
db.close()
执行顺序
基于 yield 的依赖项将执行过程严格划分为 "请求前" 与 "响应后" 两个阶段:
HTTP Request 进入
↓
执行 get_db()
↓
创建 Session 资源
↓
触发 yield db 暂停执行
↓
─────────────────────────────
切换至路由函数运行(使用 db)
─────────────────────────────
↓
路由函数执行完毕并生成 Response
↓
回到 get_db() 恢复执行
↓
进入 finally 代码块
↓
执行 db.close() 释放资源
yield 之前的代码负责初始化并准备资源;yield 产出的值将被作为依赖注入到函数中;yield 之后的代码则在 HTTP 响应返回后负责清理与释放资源
3. 在装饰器中声明依赖
在部分场景下,依赖逻辑仅仅需要被执行(例如身份鉴权、访问日志记录、API Key 校验),而路由函数本身并不需要使用该依赖函数的返回值
此时,可以通过路径操作装饰器的 dependencies 参数来声明依赖,避免在函数体内定义未使用的参数
python
from fastapi import FastAPI, Depends, HTTPException, Header
app = FastAPI()
def verify_token(x_token: str = Header()):
if x_token != "fake-token":
raise HTTPException(status_code=400, detail="Token header invalid")
@app.get("/admin", dependencies=[Depends(verify_token)])
async def get_admin_data():
return {"status": "Admin Access Granted"}
依赖声明方式
| 声明方式 | 目的 | 路由是否获取返回值 |
|---|---|---|
| 函数参数依赖 | 获取数据库 Session、当前登录用户对象等实体资源 | 是(需使用返回值) |
| 装饰器依赖 | 执行前置校验、权限检查、速率限制、请求日志 | 否(仅关注执行过程与异常抛出) |
4. 全局依赖
FastAPI 允许将依赖项挂载到不同粒度的作用域中,实现从单接口到全应用级别的层级化拦截控制
依赖项的作用域包含以下四个层级:
-
参数级依赖:作用于单个路径操作函数的指定形参
-
路由级依赖:作用于单个路径操作装饰器(如 @app.get(dependencies=...))
-
路由器级依赖:作用于整个 APIRouter 实例,该路由器下的所有接口均生效
pythonrouter = APIRouter( prefix="/users", dependencies=[Depends(get_current_user)] ) @router.get("/") async def get_users(): return {"users": ["Tom", "Jack"]} -
全局应用级依赖:作用于主 FastAPI 应用实例,系统所有接口均生效
pythonapp = FastAPI( dependencies=[Depends(get_current_user)] ) @app.get("/users") async def users(): return {"message": "users"}
通过将 Depends() 组合运用于参数、路由、路由器与应用全局,FastAPI 提供了一套统一且可组合的切面编程(AOP)机制,极大简化了复杂的中间件逻辑与资源管理模式
总结
本章进一步深入 FastAPI 的核心开发机制,围绕 请求响应、Pydantic 数据模型与依赖注入三个部分展开
首先,我们学习了 Path、Query、Header、Cookie 等请求数据的获取方式,以及 JSON、Pydantic Model、状态码、重定向和自定义响应头等响应处理方式,进一步理解了一次 HTTP 请求在 FastAPI 中的完整流转过程
随后,我们系统学习了 Pydantic v2,包括模型定义、请求体解析、响应模型、常用方法、模型配置与继承,理解了 Pydantic 如何承担数据解析、验证、序列化与 Schema 定义工作
最后,我们学习了 FastAPI 的依赖注入机制,并通过数据库 Session 案例理解了 Depends()、装饰器依赖、全局依赖以及 yield 依赖的执行流程
至此,我们已经能够处理 FastAPI 中最核心的请求、响应、数据模型以及公共依赖。下一篇将继续扩展 HTTP 请求数据处理,进入表单数据、文件上传等更加贴近实际 Web 开发的内容
