在使用FastAPI開發接口時,路徑參數(Path Parameters)是一種非常靈活的傳參方式,比如/users/{user_id}中的user_id。但FastAPI的路徑參數遠不止基礎用法,它們支持動態路由和參數校驗,讓接口更靈活、更健壯。
一、回顧基礎路徑參數¶
首先,我們先快速回顧一下路徑參數的基礎用法。比如,定義一個根據用戶ID返回用戶信息的接口:
from fastapi import FastAPI
app = FastAPI()
# 基礎路徑參數:user_id是路徑參數,默認類型爲str
@app.get("/users/{user_id}")
async def get_user(user_id: str):
return {"user_id": user_id, "message": f"獲取用戶 {user_id} 的信息"}
當訪問/users/123時,user_id會被自動識別爲字符串"123"。但FastAPI允許我們顯式指定參數類型(如int、float),讓參數自動轉換和校驗。
二、動態路由進階:讓路徑參數更靈活¶
動態路由指的是路徑參數可以根據實際需求“動態變化”,支持多種參數組合或特殊格式。
1. 路徑參數類型自動轉換¶
FastAPI會自動嘗試將路徑參數轉換爲指定類型(如int、float)。例如,即使URL中傳的是字符串"123",只要我們定義user_id: int,FastAPI會自動將其轉爲整數:
@app.get("/users/{user_id}")
async def get_user(user_id: int): # 自動轉換爲int類型
return {"user_id": user_id, "type": type(user_id)} # 輸出:{"user_id": 123, "type": <class 'int'>}
如果參數類型轉換失敗(如/users/abc中傳"abc"給int類型的user_id),FastAPI會直接返回422 Validation Error,避免非法數據進入接口。
2. 可選路徑參數¶
有時路徑參數可能不是必須的,比如/items/{item_id}/details/{sub_id},其中sub_id可能是可選的。這時可以用Optional類型+默認值:
from typing import Optional
@app.get("/items/{item_id}/details/{sub_id}")
async def get_item_details(
item_id: int, # 必須參數
sub_id: Optional[int] = None # 可選參數,默認None
):
result = {"item_id": item_id}
if sub_id:
result["sub_id"] = sub_id
return result
訪問/items/123/details/456會返回{"item_id": 123, "sub_id": 456},而訪問/items/123(不帶sub_id)會返回{"item_id": 123}。
3. 路徑參數的正則表達式限制¶
如果需要嚴格限制路徑參數的格式(如只能是字母、數字組合),可以用Path的pattern參數配合正則表達式:
from fastapi import Path
@app.get("/orders/{order_code}")
async def get_order(order_code: str = Path(..., pattern="^[A-Z0-9]{8}$")):
# order_code必須是8位大寫字母或數字(如"ABC12345")
return {"order_code": order_code}
這裏pattern="^[A-Z0-9]{8}$"表示:
- ^和$:匹配字符串開頭和結尾
- [A-Z0-9]:允許大寫字母或數字
- {8}:必須連續出現8次
三、參數校驗進階:讓接口更安全¶
光有動態路由還不夠,FastAPI支持對路徑參數進行嚴格校驗(如範圍、枚舉值等),確保傳入的數據合法。
1. 用Path限制參數範圍¶
使用Path函數可以給路徑參數設置最小值、最大值、是否必須等規則。例如,定義商品ID必須在1到100之間:
@app.get("/products/{item_id}")
async def get_product(
item_id: int = Path(
..., # 必傳參數(...表示必填)
ge=1, # ge=1:大於等於1
le=100, # le=100:小於等於100
description="商品ID必須是1-100之間的整數"
)
):
return {"item_id": item_id, "message": f"獲取商品 {item_id} 的詳情"}
ge(greater than or equal):最小值le(less than or equal):最大值- 若傳入不合法參數(如
/products/0或/products/101),FastAPI會直接返回422錯誤,並提示“商品ID必須是1-100之間的整數”。
2. 枚舉類型路徑參數¶
如果參數只能是特定枚舉值(如商品分類只能是"book"、"electronics"、"clothes"),可以用Enum或Literal實現:
from enum import Enum
class Category(str, Enum):
BOOK = "book"
ELECTRONICS = "electronics"
CLOTHES = "clothes"
@app.get("/products/{category}/{item_id}")
async def get_product_by_category(
category: Category, # 枚舉類型,只能傳預定義值
item_id: int = Path(ge=1, le=100)
):
return {
"category": category.value,
"item_id": item_id,
"message": f"獲取 {category.value} 分類下的商品 {item_id}"
}
此時訪問/products/electronics/123會返回正確結果,但訪問/products/music/123會報錯(music不是枚舉值)。
四、動態路由+參數校驗的實際應用¶
結合動態路由和參數校驗,可以構建更通用、更安全的接口。例如:
from fastapi import FastAPI, Path, Query
from typing import Optional
app = FastAPI()
# 動態生成路由:根據用戶ID和訂單類型返回訂單
@app.get("/users/{user_id}/orders/{order_type}")
async def get_orders(
user_id: int = Path(ge=1, description="用戶ID必須是正整數"),
order_type: str = Path(
...,
pattern="^(pending|completed|cancelled)$", # 訂單狀態只能是這三種
description="訂單類型必須是pending/completed/cancelled"
),
page: int = Query(1, ge=1, le=10, description="頁碼必須是1-10") # 注意:Query用於查詢參數,這裏僅作示例
):
return {
"user_id": user_id,
"order_type": order_type,
"page": page,
"message": f"獲取用戶 {user_id} 的 {order_type} 訂單,第 {page} 頁"
}
- 動態路由:
/users/{user_id}/orders/{order_type}支持任意用戶ID和訂單類型(只要符合規則)。 - 參數校驗:
user_id必須是正整數,order_type必須是預定義狀態,page必須是1-10的整數。
五、總結¶
FastAPI的路徑參數進階特性讓我們能:
1. 動態路由:通過靈活的路徑參數組合,支持多種業務場景(如多維度查詢、層級化接口)。
2. 參數校驗:自動轉換類型、限制範圍、枚舉值校驗,避免非法數據進入接口,提升接口健壯性。
這些特性讓接口開發更簡單,同時減少了手動校驗參數的代碼量。如果你正在開發需要靈活路徑和嚴格數據校驗的API,FastAPI的路徑參數進階用法會是你的得力助手!
小提示:訪問FastAPI自動生成的Swagger文檔(/docs),可以直觀看到參數校驗規則,方便測試和調試。