FastAPI 依赖注入全解:从函数到全局作用域|附实战代码

简介: FastAPI依赖注入(DI)是其核心机制:你声明所需资源(如用户认证、数据库会话),框架自动注入。支持函数/类依赖、多级作用域(接口/路由/全局)和类型安全,实现DRY、解耦与自动文档。一句话:`Depends()` 是你的“自动工具管理员”。

🧠 什么是依赖注入(DI)?FastAPI 为何离不开它?

“你声明需要什么,框架自动准备好。”

在 FastAPI 中,依赖(Dependency) 是一段可复用的逻辑单元,例如:

  • 用户身份校验
  • 数据库会话获取
  • 请求限流/日志记录
  • 配置读取

依赖注入(Dependency Injection, DI) 就是 FastAPI 自动执行这些逻辑,并将结果(或副作用)传递给你的接口函数的过程。

优势

  • 遵循 DRY:避免每个接口重复写 if not token: raise ...
  • 解耦业务与横切关注点(cross-cutting concerns)
  • 支持多级作用域(单接口 → 路由组 → 全局)
  • 类型安全 + 自动文档生成(Swagger 自动带上依赖参数)

🎯 一句话总结:
Depends() 是 FastAPI 的“自动工具管理员”——你要锤子?它递给你;你要扳手?它也备好了。


🛠️ 实战准备:项目结构 & 环境搭建

mkdir fastapi-di-demo && cd fastapi-di-demo
python -m venv .venv
source .venv/bin/activate  # Linux/macOS;Windows 用 `.venv\Scripts\activate`
pip install 'fastapi[all]'

目录结构:

fastapi-di-demo/
├── .venv/
├── main.py              # 主应用入口(全局依赖)
├── deps.py              # 所有依赖定义(函数/类)
├── users.py             # 用户路由(演示路径/路由级依赖)
└── requirements.txt

🧩 1. 函数依赖:最常用、最直观

场景:校验用户凭据(用户名+密码)

✅ 步骤 1:定义依赖函数(deps.py

# deps.py
from fastapi import HTTPException

# 模拟用户数据库(生产环境请用 DB)
FAKE_USERS = {
   
    "alice": "pass123",
    "bob": "secret456",
}

def verify_user(name: str, password: str) -> dict:
    """✅ 函数依赖:校验用户,返回用户信息"""
    if name in FAKE_USERS and FAKE_USERS[name] == password:
        return {
   "username": name, "is_valid": True}
    raise HTTPException(status_code=401, detail="Unauthorized")

✅ 步骤 2:注入到接口(users.py

# users.py
from fastapi import APIRouter, Depends
from deps import verify_user

router = APIRouter(prefix="/users", tags=["Users"])

@router.get("/profile")
def get_profile(current_user: dict = Depends(verify_user)):
    # current_user ← verify_user() 的返回值!
    return {
   
        "message": f"Hello, {current_user['username']}!",
        "data": {
   "theme": "dark", "lang": "zh-CN"}
    }

✅ 测试(main.py 注册路由)

# main.py
from fastapi import FastAPI
from users import router as user_router

app = FastAPI()
app.include_router(user_router)

# 启动:uvicorn main:app --reload

访问:
GET /users/profile?name=alice&password=pass123
200 OK + 用户数据
GET /users/profile?name=alice&password=wrong
401 Unauthorized

💡 关键点:依赖函数的参数(name, password)会自动从请求中解析(query/form/header/path 均支持)。


🏗️ 2. 类依赖:面向对象 + 状态管理

当依赖需要配置参数维护状态时,类更合适。

场景:带自定义消息的认证器

# deps.py(追加)
from fastapi import HTTPException

class AuthGuard:
    def __init__(self, realm: str = "api"):
        self.realm = realm  # 可配置项!例如区分 admin/web/api

    def __call__(self, name: str, password: str) -> str:
        """__call__ 使实例可调用 → FastAPI 视为依赖函数"""
        if name in FAKE_USERS and FAKE_USERS[name] == password:
            return name  # 返回用户名(轻量)
        raise HTTPException(
            status_code=401,
            detail="Invalid credentials",
            headers={
   "WWW-Authenticate": f'Bearer realm="{self.realm}"'}
        )

注入使用:

# users.py(追加)
from deps import AuthGuard

# 固定 realm="protected"
guard = AuthGuard(realm="protected")

@router.get("/dashboard")
def dashboard(username: str = Depends(guard)):
    return {
   "welcome": username, "role": "user"}

✅ 优势:

  • 同一依赖可创建多个实例(如 admin_guard = AuthGuard("admin")
  • 支持 __init__ 注入配置,__call__ 执行逻辑,职责分离清晰

🌐 3. 多级依赖作用域(Scope)

作用域 写法 适用场景
接口级(带返回值) param = Depends(dep) 参数注入 需要依赖结果(如 current_user
接口级(无返回值) dependencies=[Depends(dep)] 装饰器参数 仅做检查(鉴权/限流/日志)
路由级 APIRouter(..., dependencies=[Depends(dep)]) 整组接口共享逻辑(如 /admin/* 需管理员权限)
应用级(全局) FastAPI(dependencies=[Depends(dep)]) 全站生效(如全链路日志、全局 API Key 校验)

✅ 示例 1:装饰器依赖(无返回值)

# deps.py
def log_request(name: str, password: str):
    print(f"🔍 Request from {name} at {__import__('datetime').datetime.now()}")

# users.py
@router.get("/audit", dependencies=[Depends(log_request)])
def audit():
    return {
   "status": "logged"}  # 不接收 log_request 返回值(它没 return)

✅ 示例 2:路由级依赖(整组保护)

# users.py
from deps import AuthGuard

protected_router = APIRouter(
    prefix="/admin",
    tags=["Admin"],
    dependencies=[Depends(AuthGuard("admin"))]  # ✅ 整个 /admin/* 都要认证
)

@protected_router.get("/stats")
def stats():
    return {
   "users": 1000, "active": 42}

✅ 示例 3:应用级依赖(全局日志 + 认证)

# main.py
from deps import log_request, verify_user

app = FastAPI(
    dependencies=[
        Depends(log_request),      # 所有请求记录日志
        Depends(verify_user),      # 甚至 /docs 也要求登录!⚠️ 实际慎用
    ]
)

⚠️ 注意:全局依赖会影响 Swagger UI (/docs)!若需开放文档,建议:

  • /docs 单独排除
  • 或使用中间件替代部分全局依赖

🚀 常见实战场景 & 最佳实践

场景 推荐实现方式 说明
数据库会话(SQLAlchemy) @contextmanager + Depends 确保每个请求独立 session,自动 commit/rollback
JWT 认证 类依赖 + Security() 结合 oauth2_scheme = OAuth2PasswordBearer(...)
配置管理 @lru_cache() 依赖函数 缓存 .env 读取结果,避免重复 IO
分页参数 函数依赖(skip: int = 0, limit: int = 10 统一接口分页风格
限流(Rate Limit) 装饰器依赖 + Redis 无返回值,失败直接抛 429

✅ 小结:何时该用依赖注入?

场景 用 DI? 理由
每个接口都要查用户信息 避免重复 get_user(token)
仅一个接口需特殊校验 直接写在函数里更简单
多个服务需共享 DB 连接池 统一生命周期管理
简单字符串处理(如 .upper() 过度设计

🎯 黄金法则
“重复出现 ≥ 2 次的逻辑 → 提取为依赖”
“需要与请求生命周期绑定的资源 → 必须用依赖”


相关文章
|
Ubuntu Shell 开发工具
Ubuntu 20.04 安装nvm
Ubuntu 20.04 安装nvm
8505 0
|
测试技术
12 Mac 下MQTT免费测试工具MQTTBox
12 Mac 下MQTT免费测试工具MQTTBox
947 0
|
5月前
|
SQL 存储 自然语言处理
构建AI智能体:三十四、LangChain SQLDatabaseToolkit终极指南:架构、优势与最佳实践
SQLDatabaseToolkit 是 LangChain 框架中的一个核心组件,它不属于一个独立的软件,而是一个工具箱或工具集。它的核心目的是为大语言模型提供与 SQL 数据库进行交互的能力,将大模型的自然语言理解能力与数据库的精准数据存储和检索能力结合起来。它极大地降低了通过自然语言访问和操作 SQL 数据库的门槛,是构建基于 LLM 的数据驱动应用的关键组件之一。
783 10
|
9月前
|
监控 NoSQL 数据可视化
Django+Celery 进阶:Flower可视化监控与排错
本文介绍了Celery命令行工具与图形监控工具的使用,涵盖查看Worker状态、任务信息及集成至Django项目的方法,同时提供Redis监控与常见问题排错方案。
784 1
|
前端开发 Go API
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:数据脱敏和隐私保护
GoWind Admin基于Protobuf生态,集成protoc-gen-redact插件,实现开箱即用的数据脱敏与隐私保护。通过注解定义规则,自动生成脱敏代码,支持多语言、灵活配置,零侵入业务逻辑,适用于微服务、日志、前端等场景,保障数据安全合规。
293 0
|
机器学习/深度学习 设计模式 API
Python 高级编程与实战:构建微服务架构
本文深入探讨了 Python 中的微服务架构,介绍了 Flask、FastAPI 和 Nameko 三个常用框架,并通过实战项目帮助读者掌握这些技术。每个框架都提供了构建微服务的示例代码,包括简单的 API 接口实现。通过学习本文,读者将能够使用 Python 构建高效、独立的微服务。