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

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

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

预备课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 通过 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 文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

敲代码不忘补水

感谢有你,让我的创作更有价值!

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

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

打赏作者

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

抵扣说明:

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

余额充值