【FastAPI 學習筆記 EP.10】依賴注入 (Dependency Injection)

更新 發佈閱讀 8 分鐘

這篇文章將教你如何使用 FastAPI 的「依賴注入 (Dependency Injection)」,學會依賴注入後,你不再需要重複複製貼上相同的檢查邏輯,或是手動建立資料庫連線。

什麼是依賴注入 (Dependency Injection)?

依賴注入是一種設計模式,意指「程式運作所需的資源(如資料庫連線、當前使用者),不由函式自己建立,而是由外部框架自動傳遞進來」。這就像去餐廳點餐。你只需要跟服務生說「我要 A 套餐」,廚房(FastAPI)就會自動準備好漢堡、薯條和可樂(依賴項)送到你桌上,你不需要親自走進廚房去煎肉排或裝飲料。

依賴注入基礎概念

1. 定義依賴項 (Dependency)

依賴項本質上只是一個普通的 Python 函式 (Function) 或 類別 (Class)。這個函式負責處理共用的邏輯,例如接收查詢參數或建立資料庫連線。

# 這裡定義一個負責處理分頁邏輯的函式
async def common_pagination(skip: int = 0, limit: int = 10):
    # 回傳一個字典,包含分頁資訊
    return {"skip": skip, "limit": limit}

此函式 common_pagination 獨立於路徑操作之外,定義了預設的分頁參數。

2. 注入依賴 (Depends)

在路徑操作函式中,透過 Depends 關鍵字宣告該函式需要使用上述的共用邏輯。FastAPI 會自動執行依賴函式,並將回傳值指派給參數。

from fastapi import Depends, FastAPI

app = FastAPI()

async def common_pagination(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}

# 在參數中宣告依賴關係
@app.get("/items/")
async def read_items(pagination: dict = Depends(common_pagination)):
    # pagination 變數現在持有 common_pagination 的回傳值
    return pagination

當使用者存取 /items/?skip=20 時,FastAPI 會自動解析參數並傳入 common_pagination,再將結果傳給 read_items

3. 使用 Annotated

使用 typing.Annotated 來標註依賴項,這能讓型別提示 (Type Hints) 更清晰,且便於重複使用。

from fastapi import Depends, FastAPI
from typing import Annotated

app = FastAPI()

async def common_pagination(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}

# 宣告一個型別別名,將依賴邏輯封裝起來
PaginationDep = Annotated[dict, Depends(common_pagination)]

@app.get("/users/")
async def read_items(pagination: PaginationDep):
    return pagination

這種寫法將「參數型別」與「依賴邏輯」結合,提升程式碼可讀性。

依賴注入實作範例

以下範例模擬一個「資料庫連線」的情境,使用 yield 關鍵字可以模擬連線開啟與關閉的生命週期(Context Manager),這是業界處理資料庫 session 的標準寫法。

from typing import Annotated
from fastapi import FastAPI, Depends, HTTPException

app = FastAPI()

# 1. 模擬資料庫連線生成器
async def get_database():
    db_connection = "Fake_DB_Connection_Opened"
    print("--- 資料庫連線已建立 ---")
    try:
        yield db_connection  # 將連線物件交給路徑函式
    finally:
        # 當路徑函式執行完畢後,會回頭執行這裡的程式碼
        print("--- 資料庫連線已關閉 ---")


# 2. 定義依賴型別
DatabaseDep = Annotated[str, Depends(get_database)]

# 3. 實作 API
@app.get("/users/{user_id}")
async def get_user(user_id: int, db: DatabaseDep):
    # 這裡的 db 就是 get_database yield 出來的字串
    if user_id == 0:
        raise HTTPException(status_code=400, detail="無效的使用者 ID")
    return {
        "user_id": user_id,
        "status": "active",
        "db_status": db  # 證明依賴已注入
    }

當請求進入 /users/1 時,FastAPI 會先執行 get_database 直到 yield,將連線物件傳給 get_user。待 get_user 回傳結果後,FastAPI 會自動執行 finally 區塊內的程式碼,確保資源被正確釋放,防止記憶體洩漏。

常見錯誤與解決方法

  1. 誤用函式呼叫:在 Depends 中直接呼叫函式(加上括號),導致依賴項只執行一次或行為不符合預期。
  2. 忽略型別提示:未正確標註型別,導致編輯器無法提供自動補全。
  3. 全域變數汙染:試圖在全域變數中儲存請求特定的資料。
from fastapi import Depends

async def get_token():
    return "fake-token"

# 錯誤寫法
# 不要加括號 (),除非該函式回傳的是一個可呼叫物件 (Callable)
# def route_bad(token = Depends(get_token())): ...

# 正確寫法
# 直接傳遞函式名稱
@app.get(...)
async def route_good(token: str = Depends(get_token)):
    print(token)
    return {"token": token}

結語

FastAPI 的依賴注入系統能有效解耦程式邏輯,讓資料庫連線、驗證機制與業務邏輯分離,能讓你的程式碼保持乾淨、好維護。記住三個關鍵重點:抽取邏輯(把重複程式碼變成函式)、Depends(使用這個關鍵字注入)、自動解析參數傳遞(FastAPI 會幫你處理參數傳遞)。

留言
avatar-img
留言分享你的想法!
avatar-img
梧笙 WuSheng 的沙龍
65會員
10內容數
⛰️ 梧笙,意即「吾生」,我是一個平凡的理工宅男。 生活離不開 Code 與 Game,這裡主要紀錄與分享: 📖 學習筆記|紀錄我學習過的電腦技能與知識。 💻 科技新知|整理實用工具與科技領域的資訊。 🎮 電玩娛樂|聊聊遊戲動漫與實況直播的話題。 目前更新頻率不固定,有興趣歡迎追蹤。
2025/12/19
這篇文章將教你如何在 FastAPI 專案中,使用 SQLAlchemy 來連接 SQLite 資料庫。透過這套組合,你無需安裝額外的資料庫軟體,就能以 Python 物件的方式輕鬆進行資料的新增、讀取、更新與刪除。
Thumbnail
2025/12/19
這篇文章將教你如何在 FastAPI 專案中,使用 SQLAlchemy 來連接 SQLite 資料庫。透過這套組合,你無需安裝額外的資料庫軟體,就能以 Python 物件的方式輕鬆進行資料的新增、讀取、更新與刪除。
Thumbnail
2025/12/16
這篇文章將教你如何使用 FastAPI 的 APIRouter 將龐大的 API 專案拆分成獨立、好管理的模組。學會 APIRouter 能讓你避免將成百上千行的程式碼全部擠在 main.py 中,這是開發中大型後端系統的必備技能。
2025/12/16
這篇文章將教你如何使用 FastAPI 的 APIRouter 將龐大的 API 專案拆分成獨立、好管理的模組。學會 APIRouter 能讓你避免將成百上千行的程式碼全部擠在 main.py 中,這是開發中大型後端系統的必備技能。
2025/12/14
這篇文章將教你如何使用 FastAPI 框架,快速建立一個具備新增、讀取、更新、刪除功能的待辦事項 API。
Thumbnail
2025/12/14
這篇文章將教你如何使用 FastAPI 框架,快速建立一個具備新增、讀取、更新、刪除功能的待辦事項 API。
Thumbnail
看更多
你可能也想看
Thumbnail
不是每個人都適合自己操盤,懂得利用「專業」,才是績效拉開差距的開始
Thumbnail
不是每個人都適合自己操盤,懂得利用「專業」,才是績效拉開差距的開始
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」稍微帶大家認識了FastAPI這個框架, 它讓我們快速的架設一個API服務, 並提供了許多標準化功能, 只要照著規範走就能快速的開發出來, 但開發出來之後, 我們會希望開放給一般使用者使用, 而一般使用者較能夠操作的媒介
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」稍微帶大家認識了FastAPI這個框架, 它讓我們快速的架設一個API服務, 並提供了許多標準化功能, 只要照著規範走就能快速的開發出來, 但開發出來之後, 我們會希望開放給一般使用者使用, 而一般使用者較能夠操作的媒介
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」稍微帶大家認識了FastAPI這個框架, 它讓我們快速的架設一個API服務, 並提供了許多標準化功能, 只要照著規範走就能快速的開發出來, 但我們除了能開發出應用之外, 也要設計的更人性化一點, API最重要的就是路由了
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」稍微帶大家認識了FastAPI這個框架, 它讓我們快速的架設一個API服務, 並提供了許多標準化功能, 只要照著規範走就能快速的開發出來, 但我們除了能開發出應用之外, 也要設計的更人性化一點, API最重要的就是路由了
Thumbnail
API是我們與其他系統介接的標準化規格, 那一份好的規格勢必要能夠達到引導與驗證的作用, 避免對方介接錯誤, 引發後續的災難性損失, 因此這一章節就是要教我們如何定義每個API的欄位怎麼填? 資料型態是什麼? 以及如何生成API文件。 我們在「【🔒 Python API框架篇 - Fas
Thumbnail
API是我們與其他系統介接的標準化規格, 那一份好的規格勢必要能夠達到引導與驗證的作用, 避免對方介接錯誤, 引發後續的災難性損失, 因此這一章節就是要教我們如何定義每個API的欄位怎麼填? 資料型態是什麼? 以及如何生成API文件。 我們在「【🔒 Python API框架篇 - Fas
Thumbnail
要如何使用unicorn啟動多個FastAPI服務, 歡迎參考我們的「【💊 Python的解憂錦囊 - FastAPI】如何啟動多個Workers」。 當我們試著設計帶入模組化時… 我們在「【💊 Python的解憂錦囊 - FastAPI】使用 lifespan 來共享資料與管理生命週期
Thumbnail
要如何使用unicorn啟動多個FastAPI服務, 歡迎參考我們的「【💊 Python的解憂錦囊 - FastAPI】如何啟動多個Workers」。 當我們試著設計帶入模組化時… 我們在「【💊 Python的解憂錦囊 - FastAPI】使用 lifespan 來共享資料與管理生命週期
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有說明如何使用uvicorn來啟動FastAPI服務, 假設今天我們的API是一個CPU密集型的運算服務時, 通常我們會希望開啟多個行程來幫忙處理, 那麼大致上的撰寫方式會像這樣: app = FastAPI( ti
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有說明如何使用uvicorn來啟動FastAPI服務, 假設今天我們的API是一個CPU密集型的運算服務時, 通常我們會希望開啟多個行程來幫忙處理, 那麼大致上的撰寫方式會像這樣: app = FastAPI( ti
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有分享 FastAPI 這套API框架, 那麼當我們想要在應用程式剛執行時就註冊一些事件或者共享GPU運算模型、變數…等,當整個應用程式關閉時也進行釋放作業, 這樣的一個週期循環就是所謂的生命週期, 而在FastAPI這
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有分享 FastAPI 這套API框架, 那麼當我們想要在應用程式剛執行時就註冊一些事件或者共享GPU運算模型、變數…等,當整個應用程式關閉時也進行釋放作業, 這樣的一個週期循環就是所謂的生命週期, 而在FastAPI這
Thumbnail
當我們在開發一個AI應用服務時, 常常會需要載入大模型, But… 我們總不可能每一次的請求就載入一次模型吧! 這樣太沒有效率了, 也非常的浪費資源, 因此我們通常會希望應用程式啟動時就能夠載入模型, 之後每一次的請求只要讓模型進行運算即可, 那麼在FastAPI的框架中究竟要如何使用呢? 首
Thumbnail
當我們在開發一個AI應用服務時, 常常會需要載入大模型, But… 我們總不可能每一次的請求就載入一次模型吧! 這樣太沒有效率了, 也非常的浪費資源, 因此我們通常會希望應用程式啟動時就能夠載入模型, 之後每一次的請求只要讓模型進行運算即可, 那麼在FastAPI的框架中究竟要如何使用呢? 首
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News