這篇文章教你如何使用 FastAPI 的 Query 與 Path 函式,對 API 的輸入參數進行嚴格的格式驗證,並且為 API 文件添加描述資訊。
什麼是進階驗證?
進階驗證 (Query & Path Validation) 是指在接收 HTTP 請求時,對 URL 中的查詢參數 (Query Parameters) 與路徑參數 (Path Parameters) 設定更嚴格的規則。不符合規定的資料(例如長度不足、數值範圍錯誤)會直接被擋下,並且回傳 HTTP 422 錯誤。
Metadata 則是用於描述這些參數的額外資訊(例如:參數的標題、描述、範例),這些資訊不影響程式運作,但會直接顯示在 Swagger UI 文件上,讓前端開發者更容易看懂。Query、Path 基礎概念
1. 查詢參數驗證 (Query Parameters)
使用 Query 類別來限制 URL 中 ? 之後的查詢參數 (Query String),常用的驗證參數包括 min_length(最小長度)、max_length(最大長度)和 pattern(正規表達式)。
from fast
api import FastAPI, Query
from typing import Annotated
app = FastAPI()
@app.get("/items/")
# 驗證 keyword:選填,只能包含英文字母,長度需介於 3 到 50 之間
def read_items(
keyword: Annotated[
str | None,
Query(min_length=3, max_length=50, pattern="^[a-zA-Z]+$")
] = None
):
return {"keyword": keyword}
在此範例中,限制 keyword 從頭到尾僅能包含英文字母。如果使用者輸入 ?keyword=123,就會觸發驗證錯誤。
2. 路徑參數驗證 (Path Parameters)
使用 Path 類別來限制 URL 路徑中的變數,常用參數為 gt (大於)、ge (大於等於)、lt (小於)、le (小於等於)。
from fastapi import FastAPI, Path
from typing import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
# 驗證 item_id:必須是大於等於 1 的整數,並添加文件標題
def read_item(
item_id: Annotated[int, Path(title="The ID of the item", ge=1)]
):
return {"item_id": item_id}
在此範例中,Path 確保了 ID 不會是負數或 0。
3. 添加 Metadata
為了讓 API 文件更友善,我們可以在 Query 或 Path 中加入 title(參數標題)、description(詳細說明)以及 example(範例值)。
from fastapi import FastAPI, Query
from typing import Annotated
app = FastAPI()
@app.get("/search/")
def search(
keyword: Annotated[
str | None,
Query(
title="搜尋關鍵字",
description="請輸入產品名稱,支援模糊搜尋",
example="iPhone 15" # 在文件上顯示的預設範例值
)
] = None
):
return {"keyword": keyword}
實作範例
以下範例展示一個「進入某個商品分類(如:3C 家電、服飾)」後,再進行關鍵字搜尋的功能。
from fastapi import FastAPI, Path, Query
from typing import Annotated
app = FastAPI()
@app.get("/categories/{category_id}/products")
def search_products_by_category(
# 路徑參數:鎖定分類 ID
category_id: Annotated[
int,
Path(
title="分類 ID",
description="商品分類的唯一識別碼 (1: 3C, 2: 服飾, 3: 食品...)",
ge=1, # ID 必須大於等於 1
le=100, # 假設系統目前只有 100 個分類
example=1 # 文件上的範例 ID
)
],
# 查詢參數:分類內的關鍵字搜尋
keyword: Annotated[
str | None,
Query(
title="搜尋關鍵字",
description="搜尋該分類內的產品名稱",
min_length=2,
max_length=30,
example="無線耳機" # 文件上的輸入框預設值
)
] = None,
# 查詢參數:分頁限制
limit: Annotated[
int,
Query(
title="每頁筆數",
description="限制回傳的資料筆數",
ge=1,
le=50,
example=20
)
] = 10
):
"""
獲取指定「分類」下的產品列表,並支援關鍵字過濾
"""
result = {
"category_id": category_id,
"result_limit": limit,
"items": []
}
if keyword:
result.update({
"filter_by": keyword,
"message": f"正在搜尋分類ID({category_id})中包含'{keyword}'名稱的商品"
})
else:
result.update({
"message": f"列出分類ID({category_id})中的所有商品"
})
return result
常見錯誤與解決方法
1. 搞混「必填欄位」與「預設值」的設定
在宣告 Path 參數時,賦予預設值 None,但路徑參數在 URL 結構中本質上就是「必填」的,邏輯上會產生衝突。
from fastapi import FastAPI, Path
from typing import Annotated
# 錯誤寫法:Path 是必填的,不該有預設值 None
# def bad_example(item_id: Annotated[int, Path(title="ID")] = None):
# pass
# 正確寫法:路徑參數本身就是必填,不需要賦予預設值
def good_example(item_id: Annotated[int, Path(title="ID")]):
pass
2. 驗證參數與資料型態不匹配
這是使用進階驗證時最容易發生的崩潰錯誤。我們必須清楚區分「字串驗證參數」與「數值驗證參數」,不能混用。
# 錯誤範例 1:對「整數」使用「長度」驗證
# Python 的 int 沒有 len(),這會導致程式錯誤
# item_id: Annotated[int, Path(min_length=3)]
# 錯誤範例 2:對「字串」使用「大小」驗證
# 字串雖然可以比大小,但在 API 邏輯中通常不合理
# keyword: Annotated[str, Query(ge=5)]
# 正確觀念:
# Query 跟 Path 都能使用字串跟數值驗證參數
# int, float 用 ge, le, gt, lt
# str 用 min_length, max_length
結語
掌握 Query 與 Path 的驗證功能,你就能控制 API 的輸入規則,為後端阻擋錯誤數據。同時,妥善運用 title、description 與 example 等 Metadata,能讓你的 API 文件具備良好的可讀性,降低前後端的溝通成本。











