这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战。
FastAPI 有一个很大的亮点,那就是提供了一个简单易用,但是功能非常强大的依赖注入系统,使用依赖注入系统,我们可以轻而易举的把各种功能的组件集成到 FastAPI 应用中,接下来就一起来了解一下。
什么是依赖注入
所谓依赖注入,就是声明一些程序代码必须依赖的项,FastAPI 中称之为依赖项 dependencies,然后在实际运行中,FastAPI 会把所有的依赖项提供给有需要的程序,这个过程就是依赖注入。依赖注入非常适合在业务逻辑复用的场景使用,可以有效地减少代码重复,除此之外,在进行权限校验、身份验证、共享数据库连接等场景也非常适用。
使用依赖注入系统
简单使用
要是用依赖注入系统,首先需要创建依赖项,依赖项实际上是一个函数,如下:
async def verify_token(request: Request):
token = request.headers.get("token")
if not token:
raise HTTPException(
status_code=HTTP_401_UNAUTHORIZED,
detail="token 不正确"
)
# 验证、解析token,假设解析出user_id···
user_id = 111
return user_id
复制代码
可见,声明依赖项和普通函数一样,可接收任意参数,返回任意信息。上面代码中,接收来自客户端的 request 对象并获取 header 中的 token,获取不到的话直接抛 HTTPException 异常(HTTPException 异常之后再介绍),会直接返回给客户端异常信息,获取到的话再对 token 进行验证、解析(例如JWT token 的解析),这里省略细节,假设解析出的 user_id 为111。
创建好依赖项之后,使用时在需要此依赖的路由函数的参数中使用Depends
声明依赖,如下:
@app.get("/get_info")
async def get_info(user_id: int = Depends(verify_token)):
# 通过user_id获取用户信息
user_info = {
"user_id": user_id,
"name": "tigeriaf"
}
return user_info
复制代码
解释一下,上面的user_id: int = Depends(verify_token)
对此接口声明了一个依赖Depends(verify_token)
,那么当该接口被调用的时候,先调用此依赖项函数,传递合适的参数,依赖函数执行,返回结果再传递给路由函数的参数,如 user_id。
请求示例:
验证失败的请求结果:
可见,如果请求时不上送 token 信息,不会通过。
我们可以定义我们需要的任意依赖项,然后在需要的路由函数中声明使用。
把类当作被依赖对象
上面的依赖项是以函数的形式出现,其实 FastAPI 也支持以类的形式来创建依赖项。
class UserInfo:
def __init__(self, request: Request):
token = request.headers.get("token")
if not token:
raise HTTPException(
status_code=HTTP_401_UNAUTHORIZED,
detail="token 不正确"
)
# 验证、解析token,假设解析出user_id···
self.user_id = 111
self.name = "tigeriaf"
@app.get("/get_info")
async def get_info(user_info: UserInfo = Depends(UserInfo)):
user_info = {
"user_id": user_info.user_id,
"name": user_info.name
}
return user_info
复制代码
上面的 UserInfo 是一个类,当接口被调用的时候,类对象就会被初始化,返回类的实例 user_info,然后在路由函数内获取对象的相关属性。
多层嵌套依赖项
FastAPI 支持多层嵌套依赖项,可以根据需求创建创建有子依赖项的依赖项,深度不受限制,使用方法也非常简单,只需在依赖函数内使用Depends
声明依赖即可,此处不作详细展开。
总结
除此之外,FastAPI 还支持路由声明多个依赖、使用 yield 关键字的依赖项等,总之,FastAPI 依赖注入系统非常强大,值得学习。
原创不易,如果小伙伴们觉得有帮助,麻烦点个赞再走呗~
最后,感谢女朋友在工作和生活中的包容、理解与支持 !