【FastAPI 學習筆記 EP.7】CRUD 待辦事項 API

更新 發佈閱讀 9 分鐘

這篇文章將教你如何使用 FastAPI 框架,快速建立一個具備新增、讀取、更新、刪除功能的待辦事項 API。

什麼是 CRUD?

CRUD 代表 Create(新增)、Read(讀取)、Update(更新)與 Delete(刪除),是操作資料最基本的四個動作,對應到 HTTP 方法分別是 POST、GET、PUT、DELETE。

CRUD 實作範例

以下是一個完整的單一檔案範例,實作待辦事項的 CRUD 功能。資料暫時儲存在一個 Python List 變數中,伺服器重啟後資料會重置。

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

# ----------------------
# 1. Pydantic 模型定義
# ----------------------

# 基礎模型:新增時使用 (title 為必填)
class TodoCreate(BaseModel):
    title: str
    description: str | None = None
    is_completed: bool = False

# 回傳模型:繼承基礎模型,但多加了 ID (由後端產生)
class TodoResponse(TodoCreate):
    id: int

# ----------------------
# 2. 模擬資料庫
# ----------------------

fake_db: list[TodoResponse] = []

current_id_counter = 0

# ----------------------
# 3. API 路由實作
# ----------------------

# 1. Create (新增)
@app.post("/todos/", response_model=TodoResponse)
def create_todo(todo_in: TodoCreate):
    global current_id_counter
    current_id_counter += 1
    new_todo = TodoResponse(id=current_id_counter, **todo_in.model_dump())
    fake_db.append(new_todo)
    return new_todo

# 2. Read (讀取所有)
@app.get("/todos/", response_model=list[TodoResponse])
def read_todos():
    return fake_db

# 3. Read (讀取單一)
@app.get("/todos/{todo_id}", response_model=TodoResponse)
def read_todo(todo_id: int):
    for item in fake_db:
        if item.id == todo_id:
            return item
    raise HTTPException(status_code=404, detail="待辦事項不存在")

# 4. Update (更新):使用 PUT (整筆替換)
@app.put("/todos/{todo_id}", response_model=TodoResponse)
def update_todo(todo_id: int, todo_in: TodoCreate):
    for index, item in enumerate(fake_db):
        if item.id == todo_id:
            updated_item = TodoResponse(id=todo_id, **todo_in.model_dump())
            fake_db[index] = updated_item
            return updated_item         
    raise HTTPException(status_code=404, detail="待辦事項不存在")

# 5. Delete (刪除)
@app.delete("/todos/{todo_id}")
def delete_todo(todo_id: int):
    for index, item in enumerate(fake_db):
        if item.id == todo_id:
            del fake_db[index]
            return {"message": "刪除成功"}           
    raise HTTPException(status_code=404, detail="待辦事項不存在")

這段程式碼建立了一個 API 服務,透過 fake_db 列表來模擬資料庫行為。create_todo 負責將資料加入列表,read_todos 回傳整個列表。update_tododelete_todo 則透過迴圈尋找對應 ID 的項目進行修改或移除,若找不到 ID 則回傳 404 錯誤。

常見錯誤與解決方法

1. HTTP 方法使用錯誤

誤用 GET 來傳送敏感或新增的資料,或者用 POST 來獲取資料。這不僅不符合 RESTful 規範,也可能導致預期外的行為。

# 錯誤寫法:試圖用 GET 來新增資料 (不符合規範且不安全)
@app.get("/create_todo/")
def create_wrong(item: TodoCreate):
    fake_db.append(item)

# 正確寫法:新增資料應該使用 POST
@app.post("/todos/")
def create_right(item: TodoCreate):
    fake_db.append(item)

2. 未處理資料不存在的情況

在更新或刪除時,直接操作資料而未檢查 ID 是否存在,這不會導致程式崩潰(如果邏輯寫得好),但會給前端錯誤的回應狀態(例如回傳 200 OK 但什麼都沒做)。

# 錯誤寫法:找不到 ID 時回傳 None 或空值,讓前端困惑
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
    for i, item in enumerate(fake_db):
        if item.id == item_id:
            del fake_db[i]
    # 這裡如果不寫 return,預設回傳 null,狀態碼 200

# 正確寫法:找不到時明確拋出 404
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
    for i, item in enumerate(fake_db):
        if item.id == item_id:
            del fake_db[i]
            return {"msg": "Deleted"}
    raise HTTPException(status_code=404, detail="Item not found")

結語

CRUD 的重點在於正確對應 HTTP 方法、利用 Pydantic 進行嚴格的資料驗證,以及妥善處理資料不存在時的異常狀況。掌握這些基礎邏輯後,你已經準備好正式連接資料庫了。

留言
avatar-img
留言分享你的想法!
avatar-img
梧笙 WuSheng 的沙龍
65會員
10內容數
⛰️ 梧笙,意即「吾生」,我是一個平凡的理工宅男。 生活離不開 Code 與 Game,這裡主要紀錄與分享: 📖 學習筆記|紀錄我學習過的電腦技能與知識。 💻 科技新知|整理實用工具與科技領域的資訊。 🎮 電玩娛樂|聊聊遊戲動漫與實況直播的話題。 目前更新頻率不固定,有興趣歡迎追蹤。
2025/12/11
這篇文章將教你如何在 FastAPI 中正確攔截並處理錯誤,確保 API 在遇到異常時回傳標準化的 HTTP 狀態碼 (Status Code) 與清晰的錯誤訊息,避免程式無預警崩潰,並讓前端開發者能根據狀態碼精準判斷錯誤類型。
Thumbnail
2025/12/11
這篇文章將教你如何在 FastAPI 中正確攔截並處理錯誤,確保 API 在遇到異常時回傳標準化的 HTTP 狀態碼 (Status Code) 與清晰的錯誤訊息,避免程式無預警崩潰,並讓前端開發者能根據狀態碼精準判斷錯誤類型。
Thumbnail
2025/12/09
這篇文章將教你如何使用 FastAPI 的 Query 與 Path 函式,對 API 的輸入參數進行嚴格的格式驗證,並且為 API 文件添加描述資訊。
Thumbnail
2025/12/09
這篇文章將教你如何使用 FastAPI 的 Query 與 Path 函式,對 API 的輸入參數進行嚴格的格式驗證,並且為 API 文件添加描述資訊。
Thumbnail
2025/12/07
這篇文章將教你如何在 FastAPI 中定義與接收請求主體 (Request Body),當客戶端需要傳送 JSON 格式的詳細資料給伺服器(例如註冊表單或新增商品)時,就必須使用請求主體 (Request Body)。
Thumbnail
2025/12/07
這篇文章將教你如何在 FastAPI 中定義與接收請求主體 (Request Body),當客戶端需要傳送 JSON 格式的詳細資料給伺服器(例如註冊表單或新增商品)時,就必須使用請求主體 (Request Body)。
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