前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FastAPI从入门到实战(16)——依赖项

FastAPI从入门到实战(16)——依赖项

作者头像
MinChess
发布2022-12-27 20:01:43
5480
发布2022-12-27 20:01:43
举报
文章被收录于专栏:九陌斋九陌斋

依赖注入是耳熟能详的一个词了,听起来很复杂,实际上并没那么复杂,正常的访问需要接受各种参数来构造一个对象,依赖注入就变成了只接收一个实例化对象,主要用于共享业务逻辑、共享数据库连接、实现安全、验证、权限等相关的业务功能,本文主要记录一下fastapi的依赖注入。

函数依赖项

代码语言:javascript
复制
# 创建、导入、声明依赖
async def user_verification(
        user: str,
        birthday: date,
        age: int
):
    return {
        "user": user,
        "birthday": birthday,
        "age": age
    }


# 同时依赖于user_verification
@app10.get("/user_verification/test1")
async def user_verification_test1(
        test1: dict = Depends(user_verification)
):
    return test1


@app10.get("/user_verification/test2")
async def user_verification_test2(
        test2: dict = Depends(user_verification),
        test2_param:Optional[str] = None
):
    return {
        "test2":test2,
        "test2_param":test2_param
    }

上面代码就完成了一个依赖项函数的创建和调用,首先是创建了一个依赖项函数user_verification,函数接受三个参数,并将三个参数以字典的形式返回; 后面的两个路径操作函数在本质上是一样的,对于test1,定义一个dict类型的参数test1用于接收依赖项函数的返回值,然后将test1进行返回,test2除了要接受依赖项user_verification需要的参数以外,还接受路径修饰函数的test2_param参数,并将其返回。 这个示例就很好的示例了依赖项函数的使用,fastapi的依赖注入系统会自动处理所有的依赖项及其子依赖项,并为每一步操作都注入结果。

  • http://127.0.0.1:8000/stu/user_verification/test1?user=MinChess&birthday=2021-12-23&age=11
  • http://127.0.0.1:8000/stu/user_verification/test2?test2_param=%E6%9C%AC%E8%BA%AB%E7%9A%84%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0&user=%E4%B9%9D%E9%99%8C%E6%96%8B&birthday=2012-12-03&age=23

类依赖项

代码语言:javascript
复制
# 类作为依赖项
class User:
    def __init__(self, name: str, age: Optional[str], birthday: date):
        self.name = name
        self.age = age
        self.birthday = birthday


@app10.get("/stu10_UserClass")
async def stu10_UserClass(
        user: User = Depends(User)
):
    return user

上面定义了一个User类,在默认的构造函数中,除了默认的self参数,另外指定了三个参数,和上面的例子一样;进一步在路径修饰函数中指定user参数依赖于User类。 FastAPI调用User类,以此会创建该类的一个"实例",该实例作为参数user传递给路径修饰函数。

多层依赖

代码语言:javascript
复制
# 多层依赖

def first_verification(
        param1: Optional[str] = None
):
    print(param1)
    return param1


def second_verification(
        param_1: str = Depends(first_verification),
        param_2: Optional[str] = None
):
    if not param_1:
        return param_2
    return param_1


@app10.get("/stu10_more_verification")
async def stu10_more_vberification(
        param: str = Depends(second_verification)
):
    return {"param": param}

这段代码包含三个函数,第一个函数是第一层依赖,声明了一个可选的参数param1,并将这个参数进行返回; 第二个参数是另一个依赖项函数,它自身还依赖于第一个依赖项函数,判断传入的值是哪一个,有值就返回; 最后一个路径操作函数,声明一个param参数,依赖于第二个依赖项函数,最后将param参数返回。 fastapi对于多层依赖,一层一层的处理,先处理第一个再处理第二个。 如果在同一个路径操作 多次声明了同一个依赖项,例如,多个依赖项共用一个子依赖项,FastAPI 在处理同一请求时,只调用一次该子依赖项。 FastAPI 不会为同一个请求多次调用同一个依赖项,而是把依赖项的返回值进行「缓存」,并把它传递给同一请求中所有需要使用该返回值的「依赖项」。

路径操作装饰器依赖项

代码语言:javascript
复制
# 路径操作装饰器依赖项
async def verify_token(x_token: str = Header()):
    if x_token != "fake-super-secret-token":
        raise HTTPException(status_code=400, detail="X-Token header invalid")


async def verify_key(x_key: str = Header()):
    if x_key != "fake-super-secret-key":
        raise HTTPException(status_code=400, detail="X-Key header invalid")
    return x_key


@app10.get("/stu10/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
async def read_items():
    return [{"item": "Foo"}, {"item": "Bar"}]

官方文档的解释是:有时,我们并不需要在路径操作函数中使用依赖项的返回值。 或者说,有些依赖项不返回值。 但仍要执行或解析该依赖项。 对于这种情况,不必在声明路径操作函数的参数时使用 Depends,而是可以在路径操作装饰器中添加一个由 dependencies 组成的 list。 如上代码,在路径操作装饰器中添加 dependencies 参数,这个参数是由Depends()组成的list。 它的解析和执行方法和普通的依赖项是一样的,但是它们的值不会传递给路径操作函数,不管有没有返回值,路径操作都不会使用这些值。

全局依赖项

代码语言:javascript
复制
async def main_depends():
    print("main depends")


app = FastAPI(
    title='FastAPI学习教程文档——title',
    description='这是FastAPI教程的文档——description',
    version='1.0.0',
    docs_url='/docs',
    redoc_url='/redoc',
    dependencies=[Depends(main_depends)]
)

全局依赖项就是为整个应用添加依赖项,添加方式和定义路径装饰器依赖项类似,可以把依赖项添加到整个FastAPI主应用中。 如上就是在FastAPI应用中添加dependencies参数。 以此,所有的路径操作都会默认依赖上面的依赖项函数。 如下,随便访问一个路径,控制台都会打印main depends

依赖项中使用 yield

代码语言:javascript
复制
# 依赖项中使用yield
async def get_yield():
    try:
        yield "yield param"
    finally:
        print("yield end!")


@app10.get("/stu10/yield")
async def stu10_yield(
        yieldparam: str = Depends(get_yield)
):
    return {
        "yield_param": yieldparam
    }

FastAPI 支持在依赖项返回后执行一些额外的步骤,但需要用 yield 代替 return 来达到这一目的。 也就是该依赖项函数返回值后还需要进行一些操作,这个时候就需要利用yield关键字。 如上代码,返回yield param后继续操作打印yield end!这里主要记录一下yield的简单使用,更多的可以参看下面的官网简介。 同样也可以多层依赖,还有很多底层的内容,可以参看官网:https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/


感谢阅读!

九陌斋地址:https://cloud.tencent.com/developer/article/2200726

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 函数依赖项
  • 类依赖项
  • 多层依赖
  • 路径操作装饰器依赖项
  • 全局依赖项
  • 依赖项中使用 yield
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档