FastAPI 實戰秘籍:從零構建高性能 API-依賴注入
FastAPI 中,依賴注入是其核心特性與強大優勢。它并非復雜的設計模式,而是通過簡潔的 Depends() 函數,將路徑操作函數的共性需求(如數據庫會話、用戶認證、權限檢查)抽象為可復用的“依賴項”。開發者聲明函數所需的依賴,FastAPI 框架便會自動創建、注入并管理這些組件。

一、依賴注入基礎概念
1. 什么是依賴注入?
依賴注入是一種設計模式,用于實現控制反轉(IoC),讓類從外部接收依賴對象,而不是自己創建。
定義拆解:
- 依賴:當一個類A需要另一個類B才能正常工作時,我們就說A依賴于B。B就是A的依賴。
- 例如,一輛Car(汽車)需要一個Engine(引擎)才能運行。Car 依賴于 Engine。
- 注入:不是由Car自己在內部new Engine(),而是通過構造函數、方法或屬性,從外部將已經創建好的Engine對象“注入”或“傳遞”給Car。
所以,依賴注入的直白翻譯就是:“把依賴從外部注入進去”。
2. FastAPI 依賴注入
在 FastAPI 中,依賴注入是它的一個核心特性,使用起來非常簡單。
「定義一個依賴」任何可調用對象(如函數)都可以作為依賴。通常我們使用普通函數。
from fastapi import Depends, FastAPI
app = FastAPI()
# 1. 這是一個依賴函數
async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
# 它可能包含一些共享邏輯,比如數據庫會話、身份驗證等
return {"q": q, "skip": skip, "limit": limit}「在路徑操作中使用依賴」使用 Depends 來聲明一個參數來自于依賴注入。
# 2. 在路徑操作函數中聲明依賴
@app.get("/items")
async def read_items(commons: dict = Depends(common_parameters)):
# FastAPI 會調用 common_parameters 函數,將其返回值注入到 `commons` 參數中
return commons執行步驟:
- 執行訪問/items
- 發現read_items函數, 函數傳遞了參數commons
- 參數commons通過Depends聲明
- 執行 common_parameters 依賴函數,獲取其返回值。
- 將這個返回值傳遞給 read_items 函數的 commons 參數。
3. 依賴注入的優勢
- 代碼復用:共享業務邏輯
- 參數驗證:自動處理請求數據驗證
- 依賴管理:管理數據庫連接、認證等
- 測試友好:易于模擬依賴進行測試
二、基礎依賴使用
1. 簡單依賴函數
from fastapi import FastAPI, Depends
app = FastAPI()
# 基礎依賴函數
def common_parameters():
return {"message": "This is common data"}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons直接返回的是common_paramsters的函數的執行結果。
2. 多依賴項
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")
return x_token # 這個返回值不會被傳遞到 read_items
asyncdef 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 # 這個返回值不會被傳遞到 read_items
@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
asyncdef read_items():
# 這里無法訪問 verify_token 和 verify_key 的返回值
return [{"item": "Foo"}, {"item": "Bar"}]當使用 dependencies 參數添加多個依賴項時,這些依賴項的返回值不會被注入到路徑操作函數中。它們主要用于執行驗證、副作用等操作,而不需要將返回值傳遞給主函數。
3. 類依賴示例
from typing import Optional
class CommonQueryParams:
def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
@app.get("/items/")
asyncdef read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
response = {}
if commons.q:
response.update({"q": commons.q})
items = [{"item_id": "Foo"}, {"item_id": "Bar"}]
response.update({"items": items[commons.skip : commons.skip + commons.limit]})
return response類依賴項依賴注入后,在主函數中使用會直接實例化對象。
4. 可配置的類依賴
# 連接數據庫
engine = create_engine(
url="mysql+pymysql://root:123456@127.0.0.1:3306/zadmin",
echo=True,
pool_size=20
)
# 數據庫會話
session_local = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine)
# 依賴函數
def get_db():
with session_local() as session:
yield session
@app.post("/users", name="獲取用戶信息")
def api_list(db: Session = Depends(get_db)):
# 查詢所有用戶信息
return db.query(User).all()現在自動注入數據庫會話,能夠在主函數中進行數據的crud操作了。
三、常用應用場景
在Fastapi中,我們常用依賴注入做基礎的身份檢查、權限檢查,緩存處理, 接口限流等操作。
1. 身份認證
def get_current_user(
token: str = Depends(oauth2_scheme),
db: Session = Depends(get_db)
):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="需要身份認證",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, settings.jwt.secret_key, algorithms=[settings.jwt.algorithm])
uid: str = payload.get("id")
if uid isNone:
raise credentials_exception
except jwt.InvalidTokenError:
raise credentials_exception
user = db.query(User).get(uid)
if user isNone:
raise credentials_exception
return user
@app.post("/user/me", name="當前登錄用戶")
def api_list(db: Session = Depends(get_db), u:User = Depends(get_current_user)):
return u現在訪問接口/user/me, 需要用戶登錄后才能訪問。
2. 用戶權限檢查
def get_permission(required_permission: str):
"""
權限檢查依賴項工廠函數
"""
def check_user_permission(current_user: User = Depends(get_current_user)) -> User:
if required_permission notin current_user.permissions:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Require {required_permission} permission to access this resource"
)
return current_user
return check_user_permission
@app.post("/menus", name="菜單列表")
def api_list(db: Session = Depends(get_db),
u:User = Depends(get_permssion("system.menu.list")),
):
# 當前登錄用戶
return u我們很多項目都有各種角色用戶,每個角色權限不同。我們可以在每個接口增加訪問權限控制。 上面我們依賴的是get_permssion("system.menu.list"),它返回的是check_user_permission的函數執行結果。
四、總結
FastAPI 的依賴注入系統提供了強大而靈活的方式來管理應用程序的依賴關系。關鍵要點:
- 代碼復用:通過依賴共享通用邏輯
- 測試友好:易于模擬和替換依賴
- 類型安全:充分利用 Python 類型提示
- 靈活組合:可以創建復雜的依賴鏈
- 生命周期管理:支持同步和異步依賴
依賴注入是 FastAPI 的核心特性之一,大地降低了代碼耦合度,使業務邏輯更清晰、獨立。它同時帶來了卓越的可測試性,便于在單元測試中輕松替換模擬依賴。通過依賴注入,FastAPI 引導開發者構建出高度模塊化、易于維護和測試的現代化 API 應用,簡化了開發流程。

































