FastAPI Request 查詢參數驗證 (Query parameters validation)
在前面的章節中,我們學會了如何宣告簡單的查詢參數。但有時候我們需要更嚴格的限制,例如:參數必須是 50 個字元以內,或者必須符合特定的 Email 格式。
FastAPI 提供了 Query 類別來幫助我們達成這些需求。
使用 Query 增加額外驗證
首先,你需要從 fastapi 導入 Query。
from typing import Optional
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
if q:
results.update({"q": q})
return results
使用 Annotated (推薦)
在現代 FastAPI 中,建議使用 Annotated 搭配 Query 類別:
from typing import Annotated, Optional
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[Optional[str], Query(max_length=50)] = None
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
這段程式碼的意思是:
q是一個選填的字串 (Optional[str])。- 預設值為
None(由Query(None, ...)的第一個參數決定)。 max_length=50:限制最大長度為 50 個字元。
如果使用者傳送的 q 超過 50 個字元,FastAPI 會自動回傳 422 錯誤。
其他驗證參數
除了 max_length,Query 還支援許多參數:
min_length:最小長度。regex:使用正規表達式 (Regular Expression) 驗證。
例如,限制 q 必須是長度 3 到 50,且只能包含固定查詢字串:
@app.get("/items/")
async def read_items(
q: Optional[str] = Query(None, min_length=3, max_length=50, regex="^fixedquery$")
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
必填欄位 (Required)
當你使用 Query 時,如何宣告必填?
使用 ...:
在 Python 中,你不能直接寫 Query(max_length=50) 而不給第一個與預設值相關的參數。
FastAPI 支援使用 Ellipsis (...) 來明確表示「此欄位為必填」。
@app.get("/items/")
async def read_items(q: str = Query(..., min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
如果請求中沒有 q,FastAPI 會報錯。
參數列表 (List) / 多個值
如果你想要接收一個參數列表,例如 ?q=foo&q=bar,可以明確定義型別為 List[str]。
from typing import List
@app.get("/items/")
async def read_items(q: Optional[List[str]] = Query(None)):
query_items = {"q": q}
return query_items
請求 URL:http://localhost:8000/items/?q=foo&q=bar
回應 Body:
{
"q": ["foo", "bar"]
}
你也可以替列表設定預設值:
@app.get("/items/")
async def read_items(q: List[str] = Query(["foo", "bar"])):
query_items = {"q": q}
return query_items
添加元數據 (Metadata)
你可以利用 title, description 等參數,為 Swagger UI 文件添加更多說明資訊。
@app.get("/items/")
async def read_items(
q: Optional[str] = Query(
None,
title="Query string",
description="應用於搜尋項目的查詢字串,限制長度為 3 單位以上。",
min_length=3
)
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
別名 (Alias)
假設你想讓 URL 參數名稱是 item-query (帶有連字線),但在 Python 中變數不能有連字線。你可以使用 alias。
@app.get("/items/")
async def read_items(q: Optional[str] = Query(None, alias="item-query")):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
請求 URL:http://127.0.0.1:8000/items/?item-query=foobar (注意參數名是 item-query)。
但在 Python 程式碼中,你依然使用 q 來存取它。
棄用參數 (Deprecated)
如果你想保留舊的參數但不希望新使用者使用,可以標記為 deprecated=True。
@app.get("/items/")
async def read_items(
q: Optional[str] = Query(
None,
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
regex="^fixedquery$",
deprecated=True,
)
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
在 Swagger UI 中,這個參數會被畫上一條刪除線,提示使用者該參數已棄用。
總結
- 使用
Query可以對查詢參數進行更細緻的控管。 - 常見驗證:
max_length,min_length,pattern(取代舊有的regex)。 - 必填參數使用
...。 - 支援接收列表參數 (
List[str])。 alias用於處理不符合 Python 變數命名規則的 URL 參數。- 記得善用
title和description來豐富你的 API 文件。