FastAPI 子依賴 (Sub-dependencies)

FastAPI 的依賴注入系統非常強大,它支援建立「依賴關係圖 (Dependency Graph)」。這意味著,一個依賴項本身也可以有其他的依賴項

FastAPI 會自動解析這些層層疊疊的關係,找出正確的執行順序。

建立子依賴

假設我們有以下需求:

  1. 有一個 query_extractor 依賴,負責解析查詢參數 q
  2. 有一個 query_or_cookie_extractor 依賴,它需要用到 query_extractor 的結果,並且可能還會讀取 Cookie。
from typing import Annotated

app = FastAPI()

# 第一層依賴
def query_extractor(q: str | None = None):
    return q

# 第二層依賴:它依賴於 query_extractor
def query_or_cookie_extractor(
    q: Annotated[str, Depends(query_extractor)], # 這裡注入了第一層依賴
    last_query: Annotated[str | None, Cookie()] = None,
):
    if not q:
        return last_query
    return q

# 路徑操作:它依賴於第二層依賴
@app.get("/items/")
async def read_query(query_or_default: Annotated[str, Depends(query_or_cookie_extractor)]):
    return {"q_or_cookie": query_or_default}

執行流程

當使用者請求 /items/ 時,FastAPI 會:

  1. 發現 read_query 需要 query_or_cookie_extractor
  2. 檢查 query_or_cookie_extractor,發現它需要 query_extractor
  3. 執行 query_extractor:從 URL 解析 q 參數。
  4. 執行 query_or_cookie_extractor:將 query_extractor 的回傳值傳給它,並同時解析 Cookie。
  5. 執行 read_query:將 query_or_cookie_extractor 的回傳值傳給它。

這個過程就像剝洋蔥一樣,從最外層(或最底層)的依賴開始執行,一層層往上傳遞。

多次使用同一個依賴

如果你的依賴關係圖很複雜,同一個依賴項可能會被多個其他依賴項所使用。

例如:

  • Dependency A 需要 Dependency Common
  • Dependency B 需要 Dependency Common
  • Path Operation 需要 Dependency A 和 Dependency B

在同一個 Request 中,FastAPI 預設只會執行 Dependency Common 一次。它會將第一次執行的結果快取起來,然後傳給 A 和 B。

這非常重要,例如當你的 Dependency Common 是「連接資料庫」時,你絕不希望每個依賴都去重新連線一次資料庫。

如果你真的希望每次依賴被注入時都重新執行該函數 (不使用快取),可以在 Depends 中設定 use_cache=False。 例如:Depends(common_parameters, use_cache=False)

總結

  • 依賴項可以依賴其他的依賴項 (子依賴)。
  • FastAPI 能夠自動解析任意深度的依賴樹。
  • 在同一次請求中,相同的依賴預設只會執行一次 (結果會被快取與共用)。