Python 資料驗證神器:Pydantic 與 FastAPI (第 37 章)

站主自己的課程,請大家支持
揭秘站長的架站心法:如何利用 Hugo × AI 打造高質感個人品牌網站? 揭秘站長的架站心法:如何利用 Hugo × AI 打造高質感個人品牌網站?
  • Post by
  • Jan 20, 2024
post-thumb

在寫 Web API 時,大半時間都在處理「驗證」:

  • 這欄位是必填嗎?
  • 這是不是合法的 Email?
  • 密碼長度夠不夠?

傳統做法可能是寫一堆 if-elsePydantic 是 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}

發生了什麼事?

  1. FastAPI讀取 HTTP Request Body。
  2. 將 JSON 轉換為 Pydantic 的 Item 模型。
  3. 如果欄位型別不對,直接回傳 422 Unprocessable Entity 給前端,並附上錯誤細節。
  4. 如果正確,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) 的標準寫法!


延伸閱讀

LATEST POST
TAG