FastAPI Request 路徑參數 (Path Parameters)
本章介紹如何在 URL 中宣告「路徑參數」(Path Parameters),例如取得特定使用者的資料 /users/5。
基本用法
路徑參數的語法與 Python 的 f-string 相同,使用大括號 {} 包裹參數名稱:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
當你存取 http://127.0.0.1:8000/items/foo 時,item_id 的值就會是 "foo"。
回傳結果:
{ "item_id": "foo" }
有型別的路徑參數
你可以使用標準的 Python 型別提示 (Type Hints) 來宣告路徑參數的型別。例如,如果你希望 item_id 是一個整數 (int):
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
資料轉換 (Data Conversion)
宣告型別後,FastAPI 會自動幫你做「資料轉換」。
如果你存取 http://127.0.0.1:8000/items/3:
- FastAPI 會將字串
"3"轉換為整數3。 - 函數接收到的
item_id會是int型別。
資料驗證 (Data Validation)
如果使用者輸入了無法轉換為整數的值,例如 http://127.0.0.1:8000/items/foo:
FastAPI 會自動回傳一個清晰的錯誤訊息 (HTTP 422 Unprocessable Entity),告訴使用者輸入格式錯誤。
{
"detail": [
{
"loc": ["path", "item_id"],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
順序問題
定義路徑操作時,順序很重要。
假設你有兩個路徑:
/users/me:取得當前使用者資料。/users/{user_id}:取得特定 ID 的使用者資料。
因為路徑是由上往下匹配的,你必須將固定路徑 (/users/me) 放在變動路徑 (/users/{user_id}) 之前。
@app.get("/users/me")
async def read_user_me():
return {"user_id": "current_user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
Annotated 語法來宣告參數,這在接下來的進階驗證中會非常有用。如果你把 /users/{user_id} 放在前面,當你請求 /users/me 時,FastAPI 會認為 "me" 是 user_id 的參數值,導致邏輯錯誤。
預定義值 (Enum)
如果你希望路徑參數只能是特定的幾個值,可以使用 Python 標準的 Enum (列舉)。
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
好處:
- 驗證:使用者只能輸入
alexnet,resnet,lenet其中之一。輸入其他值會報錯。 - 文件:Swagger UI 會自動列出下拉式選單供選擇。
包含路徑的路徑參數
一般來說,路徑參數不能包含斜線 /。但如果你需要參數本身就是一個路徑(例如檔案路徑 /files/home/user/data.txt),可以在參數宣告中使用 :path。
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
請求 http://127.0.0.1:8000/files/home/johndoe/myfile.txt:
file_path的值會是home/johndoe/myfile.txt。
總結
- 使用
{param}語法定義路徑參數。 - 使用 Python Type Hints (
: int) 來啟用自動轉換和驗證。 - 注意路徑定義的順序 (固定路徑優先)。
- 使用
Enum來限制參數的可選值。