FastAPI依赖注入
FastAPI 的依赖注入(Dependency Injection)系统是其核心功能之一,允许你在构建 API 时管理和复用复杂的逻辑、参数和服务。依赖注入可以用于共享数据库连接、缓存、配置、用户认证等。以下是 FastAPI 依赖注入的详细介绍。
1. 依赖注入的基础
1.1 定义依赖函数
一个依赖函数是一个普通的 Python 函数,可以执行任意逻辑并返回一个值。依赖函数通常用于封装和复用常用逻辑。
from fastapi import FastAPI, Depends
app = FastAPI()
def common_parameters(q: str = None, skip: int = 0, limit: int = 10):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
在上述例子中,common_parameters
是一个依赖函数,Depends
用于将其注入到路径操作函数 read_items
中。
2. 高级依赖注入
2.1 类作为依赖项
依赖项可以是一个类实例,通过创建类方法和属性,可以更好地组织和管理依赖项的逻辑。
from fastapi import FastAPI, Depends
app = FastAPI()
class CommonQueryParams:
def __init__(self, q: str = None, skip: int = 0, limit: int = 10):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
return {"q": commons.q, "skip": commons.skip, "limit": commons.limit}
在上述例子中,CommonQueryParams
类封装了查询参数的逻辑,并作为依赖项注入到路径操作函数中。
2.2 依赖项的依赖
依赖函数可以有自己的依赖项,形成依赖链。这使得你可以构建复杂的依赖关系。
from fastapi import FastAPI, Depends
app = FastAPI()
def query_extractor(q: str = None):
return q
def query_or_cookie_extractor(
q: str = Depends(query_extractor), last_query: str = 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}
在上述例子中,query_or_cookie_extractor
依赖于 query_extractor
,形成了一个依赖链。
3. 全局依赖项
3.1 应用级别的依赖项
可以在应用启动时添加全局依赖项,这样所有请求都会自动包含这些依赖项。
from fastapi import FastAPI, Depends
app = FastAPI()
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
app.dependency_overrides[verify_token] = verify_token
@app.get("/items/")
async def read_items(token: str = Depends(verify_token)):
return {"token": token}
在上述例子中,verify_token
是一个全局依赖项,每个请求都会自动验证 X-Token
头。
4. 依赖项中的状态管理
4.1 共享状态
依赖项可以用于管理共享状态,如数据库连接、缓存等。
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from database import SessionLocal, engine, Base
app = FastAPI()
# 创建数据库表
Base.metadata.create_all(bind=engine)
# 数据库依赖项
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/items/")
async def read_items(db: Session = Depends(get_db)):
items = db.query(Item).all()
return items
在上述例子中,get_db
是一个依赖函数,用于管理数据库会话的生命周期。
5. 依赖项的参数化
5.1 动态传递参数
可以使用函数或类参数化依赖项,动态地传递参数。
from fastapi import FastAPI, Depends
app = FastAPI()
def query_extractor(q: str = None):
return q
def query_or_default_extractor(
q: str = Depends(query_extractor), default_q: str = "default"
):
return q or default_q
@app.get("/items/")
async def read_items(query_or_default: str = Depends(query_or_default_extractor)):
return {"q": query_or_default}
在上述例子中,query_or_default_extractor
动态地从 query_extractor
或默认值 default_q
中获取参数。
6. 依赖项的作用域
6.1 单次请求作用域
默认情况下,依赖项在每个请求中执行一次。
from fastapi import FastAPI, Depends
app = FastAPI()
async def log_request_id(request_id: str = Header(...)):
print(f"Request ID: {request_id}")
@app.get("/items/")
async def read_items(log: None = Depends(log_request_id)):
return {"message": "Logging request ID"}
在上述例子中,每次请求都会执行 log_request_id
,记录请求 ID。
6.2 单次请求内的共享依赖
使用 Depends
可以在单次请求内共享同一个依赖实例。
from fastapi import FastAPI, Depends
app = FastAPI()
def dependency_a():
return "A"
def dependency_b(dep_a: str = Depends(dependency_a)):
return dep_a + "B"
@app.get("/items/")
async def read_items(result: str = Depends(dependency_b)):
return {"result": result}
在上述例子中,dependency_a
的结果在请求内被 dependency_b
共享。
7. 异常处理中的依赖
7.1 依赖项中的异常处理
可以在依赖函数中引发和处理异常,以实现复杂的错误处理逻辑。
from fastapi import FastAPI, Depends, HTTPException
app = FastAPI()
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
@app.get("/items/")
async def read_items(token: str = Depends(verify_token)):
return {"token": token}
在上述例子中,verify_token
依赖函数中引发的异常将自动被路径操作处理。
8. 总结
FastAPI 的依赖注入系统提供了强大而灵活的机制,帮助开发者管理复杂的依赖关系和共享状态。通过依赖函数、类依赖、全局依赖、动态参数化和作用域控制,开发者可以轻松构建和维护高效、模块化的 API。同时,依赖注入还支持异常处理和请求级别的状态管理,使得 API 的开发更加健壮和灵活。