依赖注入 Depends
用“先准备,再处理”理解依赖
多个接口都需要解析分页参数。如果每个接口都重复写一遍,修改规则时容易漏改。
依赖注入的思路是:你声明“这个接口需要分页条件”,FastAPI 先调用依赖函数,得到结果后再传给接口函数。官方依赖注入说明
完整示例:共用分页依赖
python
from typing import Annotated
from fastapi import Depends, FastAPI, Query
app = FastAPI()
def pagination(
skip: Annotated[int, Query(ge=0)] = 0,
limit: Annotated[int, Query(ge=1, le=100)] = 10,
):
return {"skip": skip, "limit": limit}
PageDep = Annotated[dict, Depends(pagination)]
@app.get("/books")
def list_books(page: PageDep):
return {"resource": "books", **page}
@app.get("/users")
def list_users(page: PageDep):
return {"resource": "users", **page}处理 GET /books?limit=5 时:
- FastAPI 发现
page依赖pagination。 - 解析并校验
skip、limit。 - 调用
pagination。 - 把返回的字典传给
list_books。
**page 是 Python 的字典展开语法,会把分页字典中的键值加入新字典。
传函数本身,不要提前调用
python
# 正确:由框架在处理请求时调用
Depends(pagination)
# 不适合这里:立刻执行 pagination 并把结果传给 Depends
# Depends(pagination())依赖也可以依赖另一个依赖。例如“读取当前用户”依赖“解析 Token”,而“检查管理员权限”又依赖“读取当前用户”。
只执行检查,不接收返回值
追加到本章完整示例:
python
from fastapi import Header, HTTPException
def verify_demo_header(
x_demo_key: Annotated[str | None, Header()] = None,
):
if x_demo_key != "learning-only":
raise HTTPException(status_code=401, detail="缺少教学请求头")
@app.get("/protected-demo", dependencies=[Depends(verify_demo_header)])
def protected_demo():
return {"message": "检查通过"}这是演示依赖检查的例子,不是一套真实用户认证方案。认证流程见第 16 章。
带 yield 的依赖管理资源
下面是通用资源管理片段:
python
def request_context():
context = {"message": "请求开始"}
try:
yield context
finally:
context.clear()yield 把准备好的值交给依赖它的接口,finally 负责清理。真实资源可用上下文管理器包裹。
本手册使用 Tortoise ORM:连接池在应用 lifespan 中初始化和关闭,不需要套用同步 ORM 的会话模板;当前用户等请求准备可以用 Depends,多个写入的一致性用显式事务,分别见第 26、37、38 章。
不要把 yield 的清理时机固定记成“函数一返回就立即关闭”。当前 FastAPI 还支持依赖作用域设置,流式响应等场景需要结合所用版本与作用域理解。官方带 yield 的依赖说明
依赖缓存的范围
同一请求中重复使用同一个依赖时,FastAPI 默认通常复用该请求内已经得到的结果。这不是“所有用户共用一次结果”。需要特殊行为时可研究 use_cache=False,入门项目保持默认即可。
本章练习
为图书和商品列表共用一个分页依赖,并在 /docs 中确认分页参数仍然可见。
过关标准:能说明 Depends 何时调用函数、如何传递结果,以及请求资源与应用连接池的管理范围有何区别。