Skip to content

依赖注入 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 时:

  1. FastAPI 发现 page 依赖 pagination。
  2. 解析并校验 skip、limit。
  3. 调用 pagination。
  4. 把返回的字典传给 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 何时调用函数、如何传递结果,以及请求资源与应用连接池的管理范围有何区别。