Pydantic 資料驗證與 OpenAPI

在上一章中,我們學會了如何建立一個簡單的 GET 路由。但是,在真實的商業應用中,我們最常處理的是客戶端傳送過來的 JSON 資料(例如:註冊表單、建立訂單、或是傳送一段文字給 AI 處理)。

這也就是 HTTP 的 POST 請求。

過去在 Flask 中處理 POST 請求,你必須手動從 request.json 中把欄位一個個拔出來,然後寫一堆又臭又長的 if / else 來檢查格式: 「名字有沒有填?」、「Email 格式對不對?」、「年齡是不是大於 0?」。

在 FastAPI 中,這些痛苦全都交給 Pydantic 來解決。

1. 什麼是 Pydantic?

Pydantic 是 Python 的一個資料驗證函式庫。它的核心概念是:使用 Python 原生的型別提示 (Type Hints) 來宣告資料結構

你只需要定義一個「模型 (Model)」,FastAPI 就會在背後幫你做好所有事:

  1. 自動驗證:如果傳來的資料不符合模型,自動回傳 422 錯誤(附帶詳細的錯誤訊息)。
  2. 自動轉換:如果傳來的是字串 "123",但模型規定是 int,它會自動幫你轉型。
  3. 自動產生文件:把這個模型同步到 Swagger UI 上,讓前端知道該傳什麼格式。

2. 建立你的第一個 Pydantic Model

讓我們來建立一個「新增會員」的 API。

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

# 1. 宣告 Pydantic 模型
class UserCreate(BaseModel):
    username: str
    email: str
    age: int
    is_active: bool = True  # 提供預設值

# 2. 在路由中使用這個模型作為參數
@app.post("/users/")
async def create_user(user: UserCreate):
    # 此時,傳進來的 user 已經是經過嚴格驗證的物件了!
    print(f"收到新用戶:{user.username}, 信箱:{user.email}")
    
    # 模擬寫入資料庫
    user_dict = user.model_dump() # 將模型轉換為字典
    user_dict["user_id"] = 9527
    
    return {"message": "會員建立成功", "data": user_dict}

測試這個 API

現在,打開你的 http://127.0.0.1:8000/docs。你會發現:

  1. 出現了一個新的 POST /users/ 路由。
  2. 點開它,裡面清楚地寫出了 Request Body 需要包含 username, email, age, 和 is_active
  3. 點擊 "Try it out",如果你故意不傳 age,或是把 age 設成字串 "twenty",API 會立刻擋下你,並回傳極度清晰的 JSON 錯誤訊息,告訴你哪個欄位出錯了。

這就是 FastAPI 開發速度可以這麼快的原因!你再也不需要寫防呆邏輯了!

3. 進階驗證:Field() 的使用

有時候,單純宣告型別 (例如 strint) 是不夠的。 我們希望密碼長度必須大於 8、年齡必須介於 18 到 100 歲之間、或是商品價格不能是負數。

這時候就可以匯入 Field 來進行深度驗證:

from pydantic import BaseModel, Field, EmailStr

class ProductCreate(BaseModel):
    name: str = Field(..., min_length=2, max_length=50, description="商品名稱")
    price: float = Field(..., gt=0, description="商品價格,必須大於 0")
    discount: float | None = Field(default=None, ge=0, le=1, description="折扣比例 (0.0 ~ 1.0)")
    tags: list[str] = Field(default_factory=list, max_items=5)

解析:

  • Field(...):裡面的 ... 代表這個欄位是必填的 (Required)。
  • gt=0:Greater Than,必須大於 0。
  • ge=0, le=1:Greater or Equal to 0, Less or Equal to 1 (用於 0% 到 100% 的折扣)。
  • description:這個描述會直接渲染在 Swagger API 文件中,讓前端工程師一目了然!

[!TIP] Email 驗證神器 如果你要驗證 Email 格式,不需要自己寫複雜的正則表達式 (Regex)。只要安裝 email-validator 套件 (pip install email-validator),然後把型別宣告為 EmailStr,Pydantic 就會自動幫你檢查格式是否正確!

4. 巢狀模型 (Nested Models)

在真實的 API 中,JSON 往往有很多層。Pydantic 處理這種情況超級簡單,只要把模型包進模型裡就好:

from pydantic import BaseModel

class Address(BaseModel):
    city: str
    zip_code: str

class UserProfile(BaseModel):
    name: str
    address: Address  # 直接使用另一個模型作為型別

@app.post("/profile/")
async def update_profile(profile: UserProfile):
    return {"city": profile.address.city}

5. 總結

Pydantic 就像是你後端 API 的「最強守門員」。所有骯髒、錯誤、惡意的資料,在進到你的業務邏輯之前,都會被 Pydantic 擋在門外。

確保了資料的純淨度後,下一步,我們就要把這些資料真正的「寫入硬碟」了。在下一章,我們將介紹 Python 最強大的 ORM 系統 —— SQLAlchemy,教你如何與 PostgreSQL 等關聯式資料庫完美對接!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!