FastAPI 依赖注入之类依赖:使用类声明依赖项并简化查询参数

FastAPI 依赖注入之类依赖:使用类声明依赖项并简化查询参数

在 FastAPI 中,依赖注入(DI)不仅支持函数,还支持类作为依赖项,这使得代码更加模块化与易于维护。通过类依赖,开发者能够封装复杂的业务逻辑与参数验证,提高代码的可复用性与可读性。本文介绍了如何使用类来声明依赖项并应用于路径操作,展示了类依赖与函数依赖的差异以及如何使用 FastAPI 中的 Depends 来自动处理类实例的创建与注入,极大简化了查询参数的处理和验证过程。

文章目录

  • FastAPI 依赖注入之类依赖:使用类声明依赖项并简化查询参数
      • 一 示例代码
      • 二 类依赖和函数依赖
      • 三 使用类声明依赖项
      • 四 类依赖的多种写法
        • 1 第一种
        • 2 第二种
        • 3 第三种
      • 五 完整代码示例
      • 六 源码地址
      • 七 参考

预备课:FastAPI 依赖注入之函数依赖:高效管理路径操作的全局共享资源

以下示例中使用的 Python 版本为 Python 3.10.15FastAPI 版本为 0.115.4

一 示例代码

from fastapi import Depends, FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


class CommonQueryParams:
    def __init__(self, q: str | None = 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)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip: commons.skip + commons.limit]
    response.update({"items": items})
    return response

依赖项通常被声明为函数,但也可以是其他可调用对象。Python 中的 可调用对象 是指任何可以像函数一样执行的对象。运行代码文件 di02.py 来启动应用:

$ uvicorn di02:app --reload

在 SwaggerUI 中可以查看在线文档:http://127.0.0.1:8000/docs

二 类依赖和函数依赖

# 定义一个类,用于封装查询参数
class CommonQueryParams:
    def __init__(self, q: str | None = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit

# 定义一个异步函数,作为依赖项返回查询参数字典
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
    """
    返回查询参数字典,用于处理请求中的查询参数。
    参数与 CommonQueryParams 类中的一致。
    """
    return {"q": q, "skip": skip, "limit": limit}

用于创建类实例的 __init__ 方法,其参数与之前的 common_parameters 函数相同,FastAPI 会处理这些参数,包括数据转换、验证,并在 OpenAPI 文档中生成相应的 schema。

三 使用类声明依赖项

@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip : commons.skip + commons.limit]
    response.update({"items": items})
    return response

FastAPI 调用 CommonQueryParams 类,创建该类的一个实例,并将其作为参数 commons 传递给路径操作函数

四 类依赖的多种写法

1 第一种

FastAPI 依赖注入之类依赖:使用类声明依赖项并简化查询参数_第1张图片

FastAPI 通过 Depends(CommonQueryParams) 知道需要调用 CommonQueryParams 类,并从中提取参数以创建一个实例。此时,FastAPI 会执行数据转换、验证,并将创建的实例作为参数传递给函数。如图所示:

  • 第一个 CommonQueryParams 仅为类型声明,对 FastAPI 并不产生特殊影响,它没有任何特殊的意义。
  • 第二个 CommonQueryParamsDepends 配合使用,才是 FastAPI 识别并处理依赖项的实际机制。
2 第二种
@app.get("/items02/")
async def read_items(commons=Depends(CommonQueryParams)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip: commons.skip + commons.limit]
    response.update({"items": items})
    return response

声明类型是推荐的做法,因为这样编辑器就能识别 commons 参数的类型,进而提供代码补全、类型检查等帮助。

3 第三种
@app.get("/items02/")
async def read_items(commons: CommonQueryParams = Depends()):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip: commons.skip + commons.limit]
    response.update({"items": items})
    return response

如果这种写法难以理解,那么可以忽略它。

五 完整代码示例

from fastapi import Depends, FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


class CommonQueryParams:
    def __init__(self, q: str | None = 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)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip: commons.skip + commons.limit]
    response.update({"items": items})
    return response


@app.get("/items02/")
async def read_items(commons=Depends(CommonQueryParams)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip: commons.skip + commons.limit]
    response.update({"items": items})
    return response


@app.get("/items02/")
async def read_items(commons: CommonQueryParams = Depends()):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip: commons.skip + commons.limit]
    response.update({"items": items})
    return response

六 源码地址

详情见:GitHub FastApiProj

七 参考

[1] FastAPI 文档

你可能感兴趣的:(fastapi,python)