
在寫 Web API 時,大半時間都在處理「驗證」:
- 這欄位是必填嗎?
- 這是不是合法的 Email?
- 密碼長度夠不夠?
傳統做法可能是寫一堆 if-else。Pydantic 是 Python 中最強大的資料解析與驗證庫,它讓驗證邏輯跟定義型別一樣簡單。
1. Pydantic 基礎:BaseModel
from pydantic import BaseModel, EmailStr, Field
# 定義一個 User 模型
class User(BaseModel):
id: int
name: str = "Anonymous" # 預設值
age: int = Field(ge=0, le=120) # 0 <= age <= 120
email: EmailStr # 需安裝 email-validator 套件
tags: list[str] = []
# 建立物件 (自動驗證)
user_data = {
"id": "123", # 這裡給字串 "123",Pydantic 會自動轉成 int 123
"age": 30,
"email": "test@example.com"
}
user = User(**user_data)
print(user.id) # 123 (int)
print(user.dict()) # 轉回 dict
如果驗證失敗 (例如 age 給了 200),Pydantic 會拋出詳細的錯誤,告訴你哪個欄位錯了。
2. 在 FastAPI 中使用 Pydantic
在 HTTP POST 請求中,我們通常會在 Body 傳送 JSON 資料。FastAPI 直接原生整合 Pydantic 來處理這件事。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
# 此時 item 已經是一個通過驗證的 Pydantic 物件
total_price = item.price + (item.tax if item.tax else 0)
return {"item_name": item.name, "total_price": total_price}
發生了什麼事?
- FastAPI讀取 HTTP Request Body。
- 將 JSON 轉換為 Pydantic 的
Item模型。 - 如果欄位型別不對,直接回傳
422 Unprocessable Entity給前端,並附上錯誤細節。 - 如果正確,
item參數就是一個 Python 物件,你可以直接用item.name取值。
3. 巢狀模型 (Nested Models)
如果 JSON 結構很複雜怎麼辦?只要模型裡面套模型就好。
class Image(BaseModel):
url: str
name: str
class Product(BaseModel):
name: str
images: list[Image] # 產品有多張圖片
@app.post("/products/")
async def create_product(product: Product):
image_url = product.images[0].url
return {"status": "ok"}
4. 總結
Pydantic 解決了兩大痛點:資料解析 (Parsing) 和 資料驗證 (Validation)。
它與 FastAPI 的結合是天作之合,讓你不需要寫任何一行的驗證程式碼,就能擁有堅固的 API 輸入檢查。
下一章,我們將學習完整的 API 互動——CRUD (Create, Read, Update, Delete) 的標準寫法!
延伸閱讀: