
在 Web 開發中,90% 的功能都離不開 CRUD:
- Create (新增) -> POST
- Read (讀取) -> GET
- Update (更新) -> PUT / PATCH
- Delete (刪除) -> DELETE
本章我們將實作一個簡單的「待辦事項 (Todo)」API。為了簡化,我們先用內存 List 當資料庫。
1. 資料模型
我們需要兩個 Pydantic 模型:一個用於請求 (Request),一個用於回應 (Response)。
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
class TodoCreate(BaseModel):
title: str
is_completed: bool = False
class Todo(TodoCreate):
id: int # 回應時多一個 ID
# 模擬資料庫
db: list[Todo] = []
current_id = 0
2. Create (新增)
使用 POST 方法。回傳狀態碼通常是 201 Created。
@app.post("/todos/", response_model=Todo, status_code=201)
async def create_todo(todo: TodoCreate):
global current_id
current_id += 1
new_todo = Todo(id=current_id, **todo.dict())
db.append(new_todo)
return new_todo
3. Read (讀取)
# 讀取全部
@app.get("/todos/", response_model=list[Todo])
async def get_todos():
return db
# 讀取單筆 (需處理 404)
@app.get("/todos/{todo_id}", response_model=Todo)
async def get_todo(todo_id: int):
for todo in db:
if todo.id == todo_id:
return todo
raise HTTPException(status_code=404, detail="Todo not found")
4. Update (更新)
通常用 PUT (整筆替換) 或 PATCH (部分更新)。這裡用 PUT。
@app.put("/todos/{todo_id}", response_model=Todo)
async def update_todo(todo_id: int, updated_todo: TodoCreate):
for i, todo in enumerate(db):
if todo.id == todo_id:
# 更新資料但保留原本 ID
new_todo = Todo(id=todo_id, **updated_todo.dict())
db[i] = new_todo
return new_todo
raise HTTPException(status_code=404, detail="Todo not found")
5. Delete (刪除)
使用 DELETE 方法。通常回傳 204 No Content 或剛刪除的物件。
@app.delete("/todos/{todo_id}")
async def delete_todo(todo_id: int):
for i, todo in enumerate(db):
if todo.id == todo_id:
del db[i]
return {"message": "Deleted successfully"}
raise HTTPException(status_code=404, detail="Todo not found")
6. 總結
我們完成了一個符合 RESTful 風格的標準 API! FastAPI 幫我們處理了:
- 路由分發 (
@app.get…) - 資料驗證 (Pydantic)
- JSON 序列化 (自動轉 List/Dict)
- Swagger 文件 (自動生成)
但現在資料存在記憶體裡,重啟伺服器就不見了。下一章,我們將引入 SQLModel (SQLAlchemy 的現代化包裝),將資料存進真正的資料庫!
延伸閱讀: