11.8 依赖注入容器进阶使用
FastAPI依赖注入容器进阶使用教程 | 深入解析
本教程详细讲解FastAPI中依赖注入容器的进阶使用方法,包括自定义依赖类、依赖缓存和生命周期管理、嵌套依赖组合、使用Pydantic模型、异步依赖、测试技巧及最佳实践。内容简洁易懂,适合新手学习和提升开发效率。
FastAPI依赖注入容器进阶使用教程
简介
依赖注入(Dependency Injection, DI)是FastAPI的核心特性之一,它通过将依赖关系外部化,使代码更加模块化、可测试和维护。在基础使用中,您可能已经通过Depends()函数在路径操作函数中注入依赖。本教程将深入探讨依赖注入容器的进阶使用,帮助您构建更复杂的应用。
1. 自定义依赖类
除了简单函数依赖,您可以创建自定义类来实现更复杂逻辑,如管理数据库连接或业务规则。
示例:创建数据库连接依赖类
from fastapi import Depends, FastAPI
from typing import Dict, Any
class Database:
def __init__(self, connection_string: str):
self.conn = self.connect(connection_string)
def connect(self, conn_str: str):
# 模拟数据库连接逻辑
return {"status": "connected to " + conn_str}
def query(self):
return self.conn
app = FastAPI()
def get_db() -> Database:
# 返回一个Database实例,连接字符串可以配置化
return Database("sqlite:///example.db")
@app.get("/items/")
def read_items(db: Database = Depends(get_db)):
return {"data": db.query()}
此示例展示了如何将数据库连接封装为类,并通过依赖注入复用。
2. 依赖缓存和生命周期管理
默认情况下,FastAPI为每个请求创建一个新依赖实例。您可以使用use_cache参数来控制缓存,优化性能。
示例:缓存配置依赖
from fastapi import Depends
def get_settings() -> dict:
# 假设设置是静态的,可以缓存以避免重复计算
return {"api_key": "secret_key", "timeout": 30}
@app.get("/settings/")
def read_settings(settings: dict = Depends(get_settings, use_cache=True)):
return settings
设置use_cache=True后,依赖函数在单次请求中只调用一次,适合只读资源。
3. 依赖注入的嵌套和组合
依赖可以嵌套使用,形成一个依赖链,让代码更灵活。
示例:嵌套依赖链
from fastapi import Depends
def get_user_id() -> str:
# 模拟从请求头或数据库获取用户ID
return "user_001"
def get_user_info(user_id: str = Depends(get_user_id)) -> dict:
# 依赖于get_user_id,获取更多用户信息
return {"id": user_id, "name": "Alice", "role": "admin"}
@app.get("/user/")
def read_user(user_info: dict = Depends(get_user_info)):
return user_info
这样,get_user_info依赖get_user_id,简化了逻辑分层。
4. 使用Pydantic模型作为依赖
Pydantic模型不仅可以验证请求数据,还可以作为依赖注入,提高数据一致性。
示例:验证和注入请求模型
from pydantic import BaseModel
from fastapi import Depends
class Item(BaseModel):
name: str
price: float
description: str | None = None
def get_default_item() -> Item:
# 提供默认值或动态生成模型
return Item(name="Default Item", price=0.0)
@app.post("/items/")
def create_item(item: Item = Depends(get_default_item)):
# 依赖注入Item模型,可以用于修改或验证
return {"message": "Item created", "data": item.dict()}
这确保了请求数据符合模型结构,并可以注入默认值。
5. 异步依赖
对于I/O密集型操作,如数据库查询或外部API调用,可以使用异步依赖提高性能。
示例:异步数据库查询依赖
import asyncio
from fastapi import Depends
async def fetch_data_from_db() -> dict:
# 模拟异步数据库操作
await asyncio.sleep(0.5) # 模拟延迟
return {"result": "data from async database"}
@app.get("/async-data/")
async def read_async_data(data: dict = Depends(fetch_data_from_db)):
return data
确保依赖函数是async,以支持异步操作。
6. 测试依赖注入
编写测试时,可以覆盖依赖来模拟真实场景,确保测试独立性。
示例:使用pytest测试覆盖依赖
import pytest
from fastapi.testclient import TestClient
from your_app import app, get_db
client = TestClient(app)
def test_read_items_with_mock():
# 覆盖get_db依赖为模拟数据
app.dependency_overrides[get_db] = lambda: {"mocked_data": "test_value"}
response = client.get("/items/")
assert response.status_code == 200
assert response.json() == {"data": {"mocked_data": "test_value"}}
# 清理覆盖,避免影响其他测试
app.dependency_overrides.clear()
这允许您在测试中灵活控制依赖行为。
7. 进阶配置和最佳实践
- 共享资源管理:使用依赖注入管理数据库连接池或缓存客户端,确保资源高效复用。
- 避免副作用:尽量减少依赖中的副作用操作,如写入日志或修改全局状态,以提高可测试性。
- 依赖文档化:通过FastAPI的自动文档功能,描述依赖用途,帮助团队协作。
- 性能考量:评估依赖的复杂度,避免在依赖中执行耗时任务,除非必要。
总结
通过进阶使用FastAPI的依赖注入容器,您可以构建更模块化、可测试和可维护的应用。本教程涵盖了自定义类、缓存、嵌套组合、Pydantic模型、异步依赖和测试等关键主题。实践这些技巧将帮助您充分利用FastAPI的强大功能。
进一步学习,可以参考FastAPI官方文档获取更多示例和高级功能。