fastapi依赖注入

依赖注入,是指在编程中,为了保证功能的使用,先导入或声明所需以来,如子函数、数据库连接等。但又不同于装饰器。
fastapi编写接口通常用函数式编程,没有像django似的视图编程的优势,所以就没有封装、继承、多态等,于是就依靠依赖注入来实现
优势是提高代码复用率:

  • 共享数据库连接
  • 增强安全、认证和角色管理
  • 响应数据注入,可以在原来的响应数据基础上再做出更改,如抽出公用函数,在公用函数中对数据处理

注入依赖

  • 函数作为依赖:定义公共函数(相当于创建依赖),如下,意思是返回的数据是字典形式,依赖于公共函数。可以在async def中调用def依赖,也可以在def中导入async def依赖
async def common_parameters(q: Optional[str] = None, page: int = 1, limit: int = 100):
    return {"q": q, "page": page, "limit": limit}

@app05.get("/dependency01")
async def dependency01(commons: dict = Depends(common_parameters)):
    return commons
  • 类作为依赖,有3种写法。下面实现的是更新数据
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


class CommonQueryParams:
    def __init__(self, q: Optional[str] = None, page: int = 1, limit: int = 100):
        self.q = q
        self.page = page
        self.limit = limit


@app05.get("/classes_as_dependencies")
# async def classes_as_dependencies(commons: CommonQueryParams = Depends(CommonQueryParams)):
# async def classes_as_dependencies(commons: CommonQueryParams = Depends()):
async def classes_as_dependencies(commons=Depends(CommonQueryParams)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.page: commons.page + commons.limit]
    response.update({"items": items})
    return response

多层嵌套依赖

use_cache默认是True, 表示当多个依赖有一个共同的子依赖时,每次request请求只会调用子依赖一次,多次调用将从缓存中获取

def query(q: Optional[str] = None):
    return q

def sub_query(q: str = Depends(query), last_query: Optional[str] = None):
    if not q:
        return last_query
    return q

@app05.get("/sub_dependency")
async def sub_dependency(final_query: str = Depends(sub_query, use_cache=True)):
    return {"sub_dependency": final_query}

路径操作装饰器依赖

当header中x_token=aaa,x_key=bbb时,才会正常返回[{“user”: “user01”}, {“user”: “user02”}]

async def verify_token(x_token: str = Header(...)):
    """没有返回值的子依赖"""
    if x_token != "aaa":
        raise HTTPException(status_code=400, detail="X-Token header invalid")

async def verify_key(x_key: str = Header(...)):
    """有返回值的子依赖,但是返回值不会被调用"""
    if x_key != "bbb":
        raise HTTPException(status_code=400, detail="X-Key header invalid")
    return x_key

@app05.get("/dependency_in_path_operation", dependencies=[Depends(verify_token), Depends(verify_key)])  # 这时候不是在函数参数中调用依赖,而是在路径操作中
async def dependency_in_path_operation():
    return [{"user": "user01"}, {"user": "user02"}]

全局依赖

可以加到组件中

app05 = APIRouter(dependencies=[Depends(verify_token), Depends(verify_key)])

也可以加到主程序中

app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)]

yield依赖和子依赖

通常用于数据库的连接,说明下yield:

def foo():
    print('111111')
    yield
    print('2222')
    yield
    print('3333')
    yield
    print('4444')
    yield


f = foo()
# print("1", next(f))
# print(next(f))
# print(next(f))
print(type(f))

每次执行next后前面的才输出,yield不返回具体的数据。生成器是根据一定的规律算法生成的列表,当我们去遍历它的时候,它可以通过特定的算法不断的推断出相应的元素,边运行边推算出结果,从而节省空间,所以yield一般会在for循环语句以一定的规则生成,yield需要放在函数内使用,如下面的伪代码

def demo():
	for i in range(10):
    	yield i*2
async def get_db():
    db = "db_connection"
    try:
        yield db
    finally:
        db.endswith("db_close")


async def dependency_a():
    dep_a = "generate_dep_a()"
    try:
        yield dep_a
    finally:
        dep_a.endswith("db_close")


async def dependency_b(dep_a=Depends(dependency_a)):
    dep_b = "generate_dep_b()"
    try:
        yield dep_b
    finally:
        dep_b.endswith(dep_a)   # 关闭子依赖的连接


async def dependency_c(dep_b=Depends(dependency_b)):
    dep_c = "generate_dep_c()"
    try:
        yield dep_c
    finally:
        dep_c.endswith(dep_b)

以上在数据库连接中使用yield是因为,当次调用函数的时候,执行yield,只有当下次再执行的时候,才会执行finally,关闭数据库连接

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值