FastAPI-依赖注入

一、什么是依赖注入

依赖注入(Dependency Injection)是一种设计模式,用于管理组件之间的依赖关系。在 FastAPI 中,它用于:

  • 共享数据库连接
  • 强制执行安全性和认证
  • 参数验证
  • 代码复用

二、基础依赖

复制代码
from fastapi import Depends, FastAPI

app = FastAPI()

# 简单依赖函数
def common_parameters(q: str = 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

三、类作为依赖

复制代码
from fastapi import Depends

class CommonQueryParams:
    def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit

@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends()):
    # 自动推断依赖类型
    return {
        "q": commons.q,
        "skip": commons.skip,
        "limit": commons.limit
    }

四、多层依赖

复制代码
from fastapi import Depends, HTTPException, status

# 第一层:获取 token
def get_token(token: str = Header()):
    return token

# 第二层:验证 token,依赖第一层
def verify_token(token: str = Depends(get_token)):
    if token != "secret-token":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token"
        )
    return token

# 第三层:获取当前用户,依赖第二层
async def get_current_user(
    token: str = Depends(verify_token),
    db: AsyncSession = Depends(get_db)
):
    # 根据 token 查询用户
    user = await get_user_by_token(db, token)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user

# 路由使用最终依赖
@app.get("/users/me")
async def read_current_user(current_user = Depends(get_current_user)):
    return current_user

五、 全局依赖

复制代码
# 应用级依赖(所有路由都会执行)
app = FastAPI(dependencies=[Depends(verify_token)])

# 路由级依赖(某个路由组的所有端点)
router = APIRouter(
    prefix="/admin",
    dependencies=[Depends(verify_admin)]
)

六、yield 依赖

复制代码
async def get_db():
    db = AsyncSessionLocal()
    try:
        yield db  # 使用 yield 而非 return
    finally:
        await db.close()  # 请求完成后自动清理

@app.get("/users/")
async def get_users(db: AsyncSession = Depends(get_db)):
    # db 使用完毕后会自动关闭
    return await get_all_users(db)

七、依赖缓存

复制代码
from fastapi import Depends

# 默认情况下,同一个请求中多次调用同一依赖,会被缓存
async def expensive_operation():
    # 昂贵的计算
    return "result"

@app.get("/test")
async def test_endpoint(
    # 两次调用,但只执行一次
    result1 = Depends(expensive_operation),
    result2 = Depends(expensive_operation)
):
    return {"result1": result1, "result2": result2}

# 禁用缓存
@app.get("/test2")
async def test_endpoint2(
    result = Depends(expensive_operation, use_cache=False)
):
    return {"result": result}
相关推荐
q5431470872 小时前
Window下Redis的安装和部署详细图文教程(Redis的安装和可视化工具的使用)
数据库·redis·缓存
2301_776508722 小时前
使用PyQt5创建现代化的桌面应用程序
jvm·数据库·python
悲伤小伞2 小时前
10-MySQL_事务管理
linux·数据库·c++·mysql·centos
umeelove352 小时前
【Flask】四、flask连接并操作数据库
数据库·python·flask
2501_945424802 小时前
持续集成/持续部署(CI/CD) for Python
jvm·数据库·python
qq_283720052 小时前
MySQL技巧(六):忘记密码的7种自救方案与深度解析
数据库·mysql
njidf2 小时前
Python上下文管理器(with语句)的原理与实践
jvm·数据库·python
F1FJJ3 小时前
Shield CLI v0.3.0:插件系统上线,首发 MySQL Web 管理
网络·数据库·网络协议·mysql·容器·golang
波波七3 小时前
maven导入spring框架
数据库·spring·maven