
在 fastapi 的 jinja2 模板中构建带多个查询参数的 url 时,必须使用单个 `?` 开头、后续参数用 `&` 连接,否则后端无法正确解析(如 `area2` 返回 `none`)。本文详解错误原因、标准格式及安全实践。
你在 FastAPI 路由中定义了两个可选查询参数 page 和 area2:
@router.get("/")
async def home(request: Request, db: Session = Depends(get_db), page: int = 1, area2: str = None):
print("Received:", page, area2) # 若 area2 为 None,说明前端 URL 构造有误
...而问题根源在于 Jinja2 模板中生成的 HTML 链接使用了多个 ?(例如 ?page=1?&area2={{area}}),这严重违反了 HTTP 查询字符串规范。浏览器和 Web 框架(包括 FastAPI)仅将第一个 ? 后的内容视为查询参数,其后的 ? 会被当作普通字符或导致参数截断,因此 area2 无法被识别。
✅ 正确写法:一个 ? 开头,参数间用 & 分隔
{% if page_obj.has_previous %}
« first
— previous
{% endif %}
⚠️ 注意事项:
- & 是分隔符,不是 &(Jinja2 在 href 属性中会自动转义,无需手动写 &;若手动写了,反而会导致 URL 解析失败);
- 确保 area 变量在模板上下文中已定义且非空(建议增加判空逻辑,避免生成 &area2= 空值);
- 更健壮的做法是复用当前所有查询参数(如保留 area2 并仅更新 page),可通过 FastAPI 的 request.url 或自定义辅助函数实现。
? 推荐进阶写法(保持其他参数不变):
{# 假设你已在路由中将 request 传入模板,并通过 request.query_params 获取原始参数 #}
« first
— previous此方式由 FastAPI 自动拼接完整、安全的 URL,避免手动拼接出错,也天然支持多参数保留。
总结:URL 查询字符串格式是 ?key1=value1&key2=value2,永远只有一个 ?,后续一律用 &。这是前后端协作的基础规范,务必严格遵守。










