Skip to content

超能力: 依赖注入

依赖注入 (DI) 系统被广泛认为是 FastAPI 最强大和最有用的功能。在软件工程中,DI 是一种设计模式,它允许程序消除硬编码的依赖关系,并使其能够更改这些依赖关系,通常是为了便于测试。

在许多框架(如 Java 的 Spring)中,DI 可能复杂且冗长。FastAPI 使其变得异常简单。您不需要创建类或注册容器。在 FastAPI 中,依赖项只是一个向您的路径操作提供数据或逻辑的函数(或类)。

想象一下,您有用于分页的查询参数 (skip 和 limit),并在许多不同的端点中使用它们。您可以将它们定义在一个函数中,而不是在每个路径操作中重复编写这些参数。

from typing import Annotated
from fastapi import Depends, FastAPI
app = FastAPI()
# 1. Create the dependency function
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
# 2. Inject it into the path operation
@app.get("/items/")
async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
return commons
@app.get("/users/")
async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
return commons

当请求访问 /items/ 时,FastAPI 会看到 Depends(common_parameters):

  • 它会调用 common_parameters 函数。
  • 它会将查询参数 (q, skip, limit) 传递给该函数。
  • 它会获取 common_parameters 返回的结果。
  • 它会将该结果分配给您的路径操作中的 commons 参数。

FastAPI 允许您构建依赖关系图。一个依赖函数本身可以使用 Depends 来要求其他依赖项。

例如,您可能有一个 get_token 依赖项,用于提取请求头。然后,一个 get_user 依赖项依赖于 get_token 来查找用户。最后,您的路径操作依赖于 get_user。FastAPI 会自动处理整个依赖链。

有时您需要在请求处理之后执行某些操作,例如关闭数据库连接或文件。FastAPI 通过 yield 关键字支持这一点。

这与 Python 的上下文管理器 (with 语句) 非常相似。yield 之前的代码在请求处理之前运行,而 yield 之后的代码在响应发送之后运行。

async def get_db():
db = DBSession()
try:
yield db
finally:
# 这在请求完成后运行
db.close()

通过使用 yield,您可以确保资源得到正确清理,即使在请求处理过程中发生异常。