FastAPI Request 查詢參數 (Query Parameters)

「查詢參數」(Query Parameters) 是指出現在 URL ? 之後的鍵值對 (Key-Value pairs),例如 http://example.com/items?skip=0&limit=10

宣告查詢參數

在 FastAPI 中,宣告查詢參數非常簡單:如果函數參數 不在 路徑參數 ( {} ) 中,FastAPI 就會自動將其視為「查詢參數」。

from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]

@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]

當你存取 http://127.0.0.1:8000/items/?skip=0&limit=10 時:

  • skip 的值為 0
  • limit 的值為 10

因為 skiplimit 都有預設值 (= 0, = 10),所以它們是選填的 (Optional)。 如果你存取 http://127.0.0.1:8000/items/,則會使用預設值。

使用 Annotated (推薦)

在現代 FastAPI 中,建議使用 Annotated 來宣告查詢參數:

from typing import Annotated
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
async def read_item(
    skip: Annotated[int, "跳過筆數"] = 0,
    limit: Annotated[int, "回傳限制"] = 10
):
    return {"skip": skip, "limit": limit}

預設值與選填參數

你可以設定參數為選填,並賦予 None (或其他預設值) 作為預設值。

from typing import Optional

@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Optional[str] = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}

在這個例子中:

  • item_id 是路徑參數 (因為在 {} 中)。
  • q 是查詢參數 (因為不在 {} 中)。
  • q 的預設值是 None,所以它是選填的。

請求範例:

  • /items/foo?q=helloworld -> {"item_id": "foo", "q": "helloworld"}
  • /items/foo -> {"item_id": "foo"}

必填查詢參數 (Required)

如果你想要讓查詢參數變成「必填」,只需要 不設定預設值 即可。

@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
    item = {"item_id": item_id, "needy": needy}
    return item

如果你存取 /items/foo 而沒有帶 needy 參數,FastAPI 會報錯:

{
  "detail": [
    {
      "loc": ["query", "needy"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

正確請求:/items/foo?needy=somestring

布林值轉換 (Bool Conversion)

查詢參數經常需要做 True/False 的判斷 (例如 ?short=1?short=true)。FastAPI 能夠聰明地處理布林值轉換。

@app.get("/items/{item_id}")
async def read_item(item_id: str, short: bool = False):
    item = {"item_id": item_id}
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

當宣告型別為 bool 時,以下參數值都會被視為 True

  • 1
  • true
  • True
  • on
  • yes

其他的(如 0, false, False, off, no)則會被視為 False

多個路徑參數與查詢參數

你可以同時混合使用多個路徑參數和查詢參數,FastAPI 會根據參數名稱自動對應,順序不影響。

@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: Optional[str] = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

總結

  • 函數參數不在路徑中宣告,即為 查詢參數
  • 提供預設值 (= default_value) 即可設為 選填 (Optional)
  • 不提供預設值即為 必填 (Required)
  • 支援 bool 等型別的自動靈活轉換。