掌握 FastAPI 依赖注入 这篇文章就够了!!!

FastAPI 依赖注入

FastAPI的依赖注入是一个强大的功能,它允许您在路由函数中声明需要的组件或依赖项。这些依赖项会在请求处理之前自动解析和注入,使代码更加模块化、易于测试和维护。

FastAPI依赖注入的基本概念

依赖注入(Dependency Injection)是一种设计模式,它将对象的创建与使用分离开来。在FastAPI中,依赖注入系统允许您声明函数所需的依赖项,然后框架会自动处理这些依赖项的创建和传递。

FastAPI依赖注入的语法

FastAPI依赖注入主要通过以下几种方式实现:

  1. 通过参数声明依赖
from fastapi import Depends, FastAPI

app = FastAPI()

async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
    return {"q": q, "skip": skip, "limit": limit}

@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
    return commons
  1. 类作为依赖项
from fastapi import Depends, FastAPI

app = FastAPI()

class CommonQueryParams:
    def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit

@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
    return {"q": commons.q, "skip": commons.skip, "limit": commons.limit}
  1. 嵌套依赖
async def dependency_a():
    return {"message": "dependency_a"}

async def dependency_b(a: dict = Depends(dependency_a)):
    a_result = a["message"]
    return {"message": f"dependency_b with {a_result}"}

@app.get("/nested-dependencies/")
async def read_nested(b: dict = Depends(dependency_b)):
    return b

FastAPI依赖注入的小案例

下面是一个更完整的案例,展示了依赖注入在身份验证中的应用:

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from typing import Optional

app = FastAPI()

# 模拟数据库
fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "johndoe@example.com",
        "hashed_password": "fakehashed123",
        "disabled": False,
    }
}

# 创建OAuth2密码流的依赖项
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

# 用户模型
class User:
    def __init__(self, username: str, email: str, full_name: str, disabled: bool):
        self.username = username
        self.email = email
        self.full_name = full_name
        self.disabled = disabled

# 根据token获取当前用户的依赖项
async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = fake_users_db.get(token)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return User(**user)

# 检查用户是否激活的依赖项
async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user

# 使用依赖项的路由
@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    return {
        "username": current_user.username,
        "full_name": current_user.full_name,
        "email": current_user.email
    }

在这个例子中:

  1. oauth2_scheme 是一个依赖项,它处理获取和验证token
  2. get_current_user 依赖于 oauth2_scheme,用于根据token获取用户信息
  3. get_current_active_user 依赖于 get_current_user,用于检查用户是否激活
  4. 最后,路由处理函数依赖于 get_current_active_user,从而形成了一个依赖链

这种依赖注入的方式使代码更加模块化,每个组件都有明确的职责,便于单元测试和代码维护。同时,FastAPI会自动处理依赖项的解析、验证和异常处理,使开发者可以专注于业务逻辑的实现。

FastAPI 依赖注入的原理

FastAPI 依赖注入的核心原理其实很简单,可以用三个关键步骤来解释:

1. 函数参数的类型提示检查

当你定义一个带 Depends() 的路由函数时,FastAPI 会检查函数参数的类型提示。这个过程基于 Python 的类型注解系统。

async def read_items(commons: dict = Depends(common_parameters)):
    return commons

在这个例子中,FastAPI 看到 Depends(common_parameters) 就知道需要调用 common_parameters 函数并将结果注入到这个位置。

2. 依赖图的构建与解析

FastAPI 会为每个路由构建一个依赖关系图。当请求到达时,它会按照这个图的顺序解析所有依赖项。

比如在嵌套依赖的情况下:

@app.get("/nested/")
async def read_nested(b: dict = Depends(dependency_b)):
    return b

async def dependency_b(a: dict = Depends(dependency_a)):
    return {"result": f"B depends on {a['result']}"}

async def dependency_a():
    return {"result": "A"}

FastAPI 会先解析 dependency_a,然后将结果传给 dependency_b,最后将 dependency_b 的结果传给路由函数。

3. 依赖的执行与结果传递

当请求到达时,FastAPI 会:

  1. 执行依赖函数
  2. 捕获其返回值
  3. 将这个返回值作为参数传递给需要它的下一个函数

这个过程利用了 Python 的异步特性,所以依赖可以是同步或异步函数。

# 当请求到达 /items/ 路径时
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
    # FastAPI 会先调用 common_parameters 函数
    # 然后将返回值作为 commons 参数传入 read_items
    return commons

本质总结

FastAPI 依赖注入的本质是函数调用的自动化与编排。它使用了 Python 的类型注解和 Pydantic 的数据验证能力,将一系列函数调用编排成一个有序的执行流程,然后自动处理函数间的参数传递。

这种设计让你可以将复杂逻辑分解为小型、专注的组件,每个组件只负责一个特定任务,而不需要关心这些组件如何被组装和调用的细节。这正是依赖注入模式的核心价值:关注点分离与代码重用。

### FastAPI依赖注入的用法 在 FastAPI 中,依赖注入是一种强大的机制,用于简化代码结构并提高可维护性和重用性。以下是关于如何在 FastAPI 中实现依赖注入的具体方法。 #### 使用类型注解声明依赖 可以通过 Python 的类型注解来定义依赖项。FastAPI识别这些注解,并根据它们自动生成所需的依赖关系[^1]。 ```python from fastapi import FastAPI, Depends app = FastAPI() async def common_parameters(q: str = None, skip: int = 0, limit: int = 100): return {"q": q, "skip": skip, "limit": limit} @app.get("/items/") async def read_items(commons: dict = Depends(common_parameters)): return commons ``` 上述代码展示了 `common_parameters` 函数作为依赖被注入到 `/items/` 路由中。当请求到达该路径时,FastAPI 自动调用 `common_parameters` 并将其返回值传递给 `read_items` 函数。 #### 生命周期管理中的依赖注入 FastAPI 不仅支持简单的依赖注入,还能通过其内置的生命周期管理功能优化资源分配和释放过程。这使得开发者可以更有效地控制应用程序运行期间的各种状态变化[^2]。 例如,在启动阶段初始化数据库连接池或者关闭服务前清理缓存等操作都可以借助于这种机制完成: ```python import asyncio from contextlib import asynccontextmanager from fastapi import FastAPI, Depends @asynccontextmanager async def lifespan(app: FastAPI): # 启动时执行的任务 await startup_event() yield # 关闭时执行的任务 await shutdown_event() def get_db(): db = ... try: yield db finally: db.close() @app.post("/users/") async def create_user(user: User, session=Depends(get_db)): ... app = FastAPI(lifespan=lifespan) ``` 这里展示了一个完整的例子,其中包含了从应用启动直到终止过程中涉及到的所有重要环节——包括但不限于设置全局变量、加载配置文件以及销毁不再使用的对象等等。 #### 实际案例分析 下面给出一个具体的场景说明:假设我们需要获取 URL 查询字符串中的某个特定参数,则可以直接利用 `Depends()` 方法配合辅助函数一起工作[^3]: ```python from typing import Optional from fastapi import FastAPI, Depends app = FastAPI() def get_query_token(token: Optional[str]): if not token: raise HTTPException(status_code=400, detail="No token provided") return token @app.get("/") def read_root(query_token: str = Depends(get_query_token)): return {"token": query_token} ``` 在这个例子当中,我们先定义好了一个名为 `get_query_token` 的小型工具类;随后再把它当作参数传入目标 API 接口之中即可轻松达成目的。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI Agent首席体验官

您的打赏是我继续创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值