FastAPI 3 依赖注入系统

FastAPI-3 依赖注入系统

依赖注入

"依赖注入"是指在编程中,为了保证代码成功运行,先导入或声明其他需要的"依赖",如子函数、数据库连接等

注:优点类似于鸭子模型

优点:

  • 提高代码的复用率
  • 共享数据库的连接
  • 增强安全、认证和角色管理

image

FastAPI的兼容性

  • 所有的关系型数据库,支持NoSQL数据库
  • 第三方的包和API
  • 认证和授权系统
  • 响应数据注入系统

FastAPI依赖

1.创建、导入和声明依赖

"""Dependencies 创建、导入和声明依赖"""


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


@app05.get('dependency02')
def dependency02(commons: dict = Depends(common_parameters)):
    return commons


"可以在async def 中调用def依赖,也可以在def中导入async def依赖 即异步函数中可以调用同步的依赖,同步函数中也可以调用异步的依赖"

2.类作为依赖项

"""Classes as Dependencies 类作为依赖项"""
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Lem"}]  # 数据库查询结果


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('/class_as_dependencies')
# async def class_as_dependencies(commons:CommonQueryParams=Depends(CommonQueryParams)):pass
# async def class_as_dependencies(commons:CommonQueryParams=Depends()):pass
async def class_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


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)):
    """use_cache默认是True, 表示当多个依赖有一个共同的子依赖时,每次request请求只会调用子依赖一次,多次调用将从缓存中取"""
    return {"sub_dependency": final_query}

3.路径操作装饰器中的多依赖

"""Dependencies in path operation decorators 路径操作装饰器中的多依赖"""


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')
    return x_token


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


@app05.get('/dependency_in_path_operation', dependencies=[Depends(verify_token), Depends(verify_key)])  # 这时候不是在函数参数中调用
async def dependency_in_path_operation():
    return [{"user": "user1"}, {"user": "user2"}]

4.全局依赖

"""Global Dependencies 全局依赖"""

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

# 或者在run.py中定义全局
app = FastAPI(
    title='FastAPI Tutorial and Coronavirus Tracker API Docs',
    description="FastAPI Study",
    version='1.0.0',
    docs_url='/docs',
    redoc_url='/redocs',
    # dependencies=[Depends(verify_token),Depends(verify_key)]
)

5.带yield的依赖

"""Dependencies with yield 带yield的依赖"""


# 这个需要Python3.7才支持,Python3.6需要 pip install async-exit-stack async-generator
# 以下是伪代码

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")  # dep_a.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)  # dep_b.close(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)  # dep_c.close(dep_b)
posted @ 2021-04-27 19:18  橘丶阳菜  阅读(169)  评论(0编辑  收藏  举报