路徑參數和查詢參數同名?這個坑 FastAPI 里你得避!
在使用 FastAPI 編寫接口時,你有沒有遇到過這樣的需求:
接口路徑中帶有 item_id,但前端也傳了一個同名的查詢參數 item_id?
例如,請求是這樣的:
GET /items/123?item_id=abc
乍一看沒啥問題,路徑參數是 123,查詢參數是 abc,看著分工明確,但你一寫代碼就報錯了!
典型錯誤寫法
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, item_id: str = Query(...)):
return {"item_id": item_id}
運行后 FastAPI 報錯:
SyntaxError: duplicate argument 'item_id' in function definition
原因很簡單:Python 函數參數不能重復命名。
正確寫法一:使用別名 alias 來區分
FastAPI 提供了 alias 參數來幫你實現“查詢參數的字段名和接收變量名不同”的功能。
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(
item_id: str, # 路徑參數
q: str = Query(None, alias="item_id") # 查詢參數:仍叫 item_id,但接收為 q
):
return {
"path_param": item_id,
"query_param": q
}
測試訪問:
GET /items/123?item_id=abc
返回結果:
{
"path_param": "123",
"query_param": "abc"
}
完美分離!
正確寫法二:直接改查詢參數名
如果你對參數命名沒有執念,可以直接改掉查詢參數的名字。
@app.get("/items/{item_id}")
async def read_item(item_id: str, filter_id: str = Query(None)):
return {
"path_id": item_id,
"query_filter_id": filter_id
}
然后前端傳參:
GET /items/123?filter_id=abc
這樣也可以避免沖突。
實戰建議
(1) 路徑參數優先遵循 REST 設計,保持不變
如 /users/{user_id}/posts/{post_id} 是很常見的路徑設計
(2) 查詢參數可以靈活重命名
使用 alias 保持兼容性,又能避免變量名沖突
(3) 注意 Path / Query / Body 等參數的接收優先級不同
為什么這個細節值得說?
通過掌握 alias 的用法,你可以:
- 兼容前后端已有設計
- 避免內部變量名沖突
- 寫出結構清晰、功能明確的接口邏輯