FastAPI多可选路径参数返回404 'detail not found'问题求助
FastAPI可选路径参数需全输入否则返回404的问题
问题描述
我创建了一个包含三个可选路径参数的FastAPI应用,但发现必须输入全部三个参数,否则会返回404 'detail not found'错误。
原代码如下:
import json from datetime import date from typing import Optional @app.get("/order/{country}/{menu}/{dt}") async def ppp(country: Optional[str] = None, menu: Optional[str] = None, dt: Optional[date] = None): a = {} if country is not None: a["a"] = country else: return "nothing inside" if menu is not None: a["b"] = menu else: return a if dt is not None: a["c"] = dt return a
预期与实际差异
- 正常情况:访问
http://127.0.0.1:8000/order/usa/vegan/2023-01-01时,输出{"a":"usa","b":"vegan","c":"2023-01-01"}(此情况符合预期) - 异常情况:
- 访问
http://127.0.0.1:8000/order/usa/vegan/时,返回{"detail":"Not Found"},预期输出{"a":"usa","b":"vegan"} - 访问
http://127.0.0.1:8000/order/usa/时,返回{"detail":"Not Found"},预期输出{"a":"usa"} - 访问
http://127.0.0.1:8000/order/时,返回{"detail":"Not Found"},预期输出"nothing inside"
- 访问
问题原因
FastAPI中,/order/{country}/{menu}/{dt}的路径写法属于必填路径段,即便参数类型设为Optional也无法改变路由匹配规则——缺少后续路径段时,系统找不到对应的路由,直接返回404。要实现可选路径参数,需要为不同的参数组合定义匹配路由,或使用FastAPI支持的可选路径段语法。
解决方案
通过定义多个路由覆盖不同的路径组合,同时明确路径参数的默认值,确保各路径都能匹配到处理函数:
from datetime import date from typing import Optional from fastapi import FastAPI, Path app = FastAPI() @app.get("/order/{country}/{menu}/{dt}/") @app.get("/order/{country}/{menu}/") @app.get("/order/{country}/") @app.get("/order/") async def ppp( country: Optional[str] = Path(default=None), menu: Optional[str] = Path(default=None), dt: Optional[date] = Path(default=None) ): a = {} if country is None: return "nothing inside" a["a"] = country if menu is not None: a["b"] = menu if dt is not None: a["c"] = dt.isoformat() # 将date对象转为字符串,避免序列化问题 return a
代码说明
- 多个
@app.get装饰器对应不同的路径组合,覆盖从无参数到全参数的所有情况 - 使用
Path(default=None)明确路径参数的默认值,避免FastAPI将其识别为查询参数 - 将
date类型的dt转为字符串返回,解决FastAPI自动序列化date对象的问题
验证结果
- 访问
http://127.0.0.1:8000/order/→ 返回"nothing inside" - 访问
http://127.0.0.1:8000/order/usa/→ 返回{"a":"usa"} - 访问
http://127.0.0.1:8000/order/usa/vegan/→ 返回{"a":"usa","b":"vegan"} - 访问
http://127.0.0.1:8000/order/usa/vegan/2023-01-01/→ 返回{"a":"usa","b":"vegan","c":"2023-01-01"}
内容的提问来源于stack exchange,提问作者beavis11111
相关产品推荐
相关产品推荐

