532 字
3 分钟
依赖注入
2025-01-05

什么是依赖注入#

依赖注入是申明代码运行所需的,或要使用的依赖的一种方式,让后有系统负责执行任意需要的逻辑,为代码提供这些依赖,常用与

  • 共享业务逻辑
  • 共享链接
  • 实现安全/角色权限/验证 可以让代码重复最小化
from typing import Union

from fastapi import Depends, FastAPI

app = FastAPI()

async def common_parameters(
    q: Union[str, None] = None, skip: int = 0, limit: int = 100
):
    return {"q": q, "skip": skip, "limit": limit}

@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
    return commons

@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
    return commons

本例中的依赖项预期接收如下参数:

  • 类型为 str 的可选查询参数 q
  • 类型为 int 的可选查询参数 skip,默认值是 0
  • 类型为 int 的可选查询参数 limit,默认值是 100

然后,依赖项函数返回包含这些值的 dict

类作为依赖项#

fastapi 的依赖项只要是可调用对象就都可以

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
    
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
    return {"q": q, "skip": skip, "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

commons: CommonQueryParams = Depends() 这样可以快捷的写 ()

子依赖项#

Fastapi 支持创建包含子依赖的依赖项

from typing import Union

from fastapi import Cookie, Depends, FastAPI

app = FastAPI()

def query_extractor(q: Union[str, None] = None):
    return q

def query_or_cookie_extractor(
    q: str = Depends(query_extractor),
    last_query: Union[str, None] = Cookie(default=None),
):
    if not q:
        return last_query
    return q

@app.get("/items/")
async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
    return {"q_or_cookie": query_or_default}

路径操作依赖项#

有时候我们并不需要在路径操作函数中使用依赖项的放回值,但是依然需要解析或执行该依赖项,我们就可以在路径操作装饰器中添加

from fastapi import Depends, FastAPI, Header, HTTPException

app = FastAPI()

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

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