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"
    }
  ]
}

順序問題

定義路徑操作時,順序很重要

假設你有兩個路徑:

  1. /users/me:取得當前使用者資料。
  2. /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}
如果你使用的是 FastAPI 0.95.0 以上版本,官方推薦使用 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"}

好處:

  1. 驗證:使用者只能輸入 alexnet, resnet, lenet 其中之一。輸入其他值會報錯。
  2. 文件:Swagger UI 會自動列出下拉式選單供選擇。

包含路徑的路徑參數

一般來說,路徑參數不能包含斜線 /。但如果你需要參數本身就是一個路徑(例如檔案路徑 /files/home/user/data.txt),可以在參數宣告中使用 :path

這不是標準 OpenAPI 的功能,但 Starlette/FastAPI 支援。請謹慎使用。
@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 來限制參數的可選值。