FastAPI 查询参数:Web 页面的“筛选开关”与“控制旋钮”
想象一下你在逛淘宝。你搜索“T恤”看到了几千件商品。此时你肯定会点击页面顶部的筛选条件“价格从低到高”、“尺码L码”、“颜色白色”。当你点击这些选项时你会发现浏览器地址栏的 URL 发生了变化。原本是 taobao.com/search?qT恤变成了 taobao.com/search?qT恤sortprice_ascsizeLcolorwhite。URL 中 ? 后面的这一串 keyvalue就是 Web 世界里最常见的查询参数Query Parameters。在 FastAPI 后端开发中查询参数就是用来接收这些“用户筛选指令”的工具。它不像路径参数/user/123那样用于“指定具体拿哪个资源”而是用于“告诉服务器怎么拿、拿哪些、拿第几页”。本文将站在一个普通 Web 用户的视角拆解什么是查询参数、为什么需要它以及如何在 FastAPI 中优雅地处理它让你的 API 像淘宝筛选一样灵活好用。一、什么是查询参数超市导购员类比假设你去一家巨大的生鲜超市后端服务器想买水果数据资源。路径参数Path Parameter就像你直接告诉导购员“带我去 4号货架”/shelves/4。这是定位特定地点的硬性地址。查询参数Query Parameter就像你在入口的查询机上点击筛选按钮“我要 当季的、红色的、价格低于10元 的水果并且 只看第一页”/fruits?seasonspringcolorredprice_lt10page1。查询参数的本质就是附在 URL 末尾、用于对请求结果进行过滤、排序、分页的额外指令。在 FastAPI 中这些参数以键值对的形式出现在 ? 之后用 分隔非常直观。二、基本用法声明即接收在 FastAPI 中接收查询参数简单得令人发指只要路由函数里的参数既不在路径中如 {id}又不是请求体Body它就自动被识别为查询参数。来看一个最直观的例子。假设我们要做一个搜索书籍的 APIfrom fastapi import FastAPI app FastAPI() # 模拟书籍数据库 books [ {id: 1, title: 三体, category: 科幻}, {id: 2, title: 流浪地球, category: 科幻}, {id: 3, title: 活着, category: 文学} ] app.get(/books/) async def search_books(category: str None, skip: int 0, limit: int 10): # 逻辑如果传了分类就筛选没传就全返回 result books if category: result [b for b in books if b[category] category] return result[skip : skip limit]站在 Web 用户/前端的角度当调用这个接口时可以这样请求GET /books/ → 返回全部书籍走默认值。GET /books/?category科幻 → 只返回科幻类书籍。GET /books/?category科幻skip1limit1 → 跳过第1本只取1本实现翻页。后端开发者完全不用解析 ? 和 FastAPI 自动完成绑定。如果前端传了 categoryhistory函数里的 category 变量就是字符串 history如果没传就是默认的 None。三、查询参数的三大核心作用站在用户视角为什么 Web 应用几乎离不开查询参数因为用户和前端需要它来做三件最重要的事。1. 过滤Filtering—— 缩小范围用户通常不想要全部数据只想要符合特定条件的。场景电商网站选“品牌华为”、“价格区间3000-5000”。URL 体现/phones?brandHuaweiprice_min3000price_max5000。作用精准命中用户需求减少网络传输体积。2. 排序Sorting—— 改变顺序用户需要按某种规则查看数据比如“最新发布”、“销量最高”、“距离最近”。场景外卖软件点“距离最近”或“评分最高”。URL 体现/restaurants?sort_bydistanceorderasc。作用满足用户的决策偏好优化使用体验。3. 分页Pagination—— 分批加载没有哪个 Web 页面会把几十万条数据一次性全塞给用户。必须分页。场景抖音下滑刷新每次只加载 10 条新视频。URL 体现/videos?page2size10 或 /?offset10limit10。作用提升加载速度节省服务器带宽和数据库压力。四、查询参数 vs 路径参数我到底该用哪个这是刚接触 Web 开发时最容易混淆的地方。我们用一个快递包裹来区分黄金法则如果这个参数是用来“识别具体哪一个”的用路径参数如果这个参数是用来“描述这批数据怎么处理”的用查询参数。五、高级用法像搭积木一样丰富查询能力FastAPI 结合 Python 的类型提示让查询参数的能力远不止简单的字符串。1. 类型自动转换与验证前端传过来的查询参数默认全是字符串但 FastAPI 支持自动类型转换。app.get(/products/) async def get_products( price_min: float 0.0, # 自动将 9.9 转为浮点数 in_stock: bool True, # 自动将 true / 1 / on 转为布尔值 page: int 1 # 自动将 2 转为整数 ): return {min: price_min, stock: in_stock, page: page}前端请求 /products/?price_min9.9in_stockfalsepage2后端拿到的直接就是 float、bool、int免去了手写 int(request.query_params.get(page)) 的麻烦。2. 使用 Optional 和默认值保证鲁棒性查询参数一大特点就是“可有可无”。我们可以优雅地处理未传参的情况给予默认行为。from typing import Optional app.get(/search/) async def search(q: Optional[str] None): # 不传 q 就返回全部 if q: return {results: f搜索关键词: {q}} return {results: 展示默认热门内容}3. 使用 List 处理多值参数数组有时我们需要传多个相同的参数名比如勾选多个分类。FastAPI 可以用 Query 或类型注解轻松搞定。from fastapi import Query from typing import List app.get(/articles/) async def get_articles( tags: List[str] Query([]) # 没有定义默认值参数为可选默认空列表 ): # 请求 /articles/?tagspythontagsfastapitagsai # tags 自动变成 [python, fastapi, ai] return {selected_tags: tags}4. 使用 Depends 将查询参数封装成 Pydantic 模型如果查询参数太多比如十几个筛选条件写在函数参数里会显得非常臃肿。此时可以结合上一篇文章讲的依赖注入利用 Pydantic 模型统一接收查询参数。from pydantic import BaseModel class FilterParams(BaseModel): category: Optional[str] None min_price: float 0 max_price: float 10000 in_stock: bool True sort_by: str default app.get(/filter/) async def apply_filters(params: FilterParams Depends()): # 此时所有查询参数都封装在 params 对象里了 return params.dict()前端请求 /filter/?categoryphonemin_price500sort_byprice后端直接拿 params.min_price 就能用代码整洁度瞬间提升。六、典型的 Web 应用场景1. 全局搜索框搜索引擎用户在输入框打字搜索前端一般用查询参数 q 传给后端。GET /api/search?qFastAPI教程page12. 电商后台列表页运营人员查看订单列表需要根据状态、时间、金额筛选。GET /api/orders?statuspaiddate_start2025-01-01date_end2025-12-31page23. 内容推荐流Feed流抖音、小红书滑动时通过 offset 或 page 配合 size 拉取新数据。GET /api/feed?offset30limit104. 分析报表数据可视化前端图表配置时将维度、指标作为查询参数。GET /api/analytics?dimensionregionmetricsalestime_rangelast_7_days七、最佳实践与避坑指南1. 敏感信息不要放在查询参数里因为查询参数会完整保留在浏览器历史记录、服务器日志和 Referer 头中。密码、Token、身份证号等敏感信息应该放在请求体Body或请求头Header中。2. 合理使用默认值要让 API 在没有查询参数时也能正常返回结果比如默认返回第一页、默认按 ID 排序保证 API 的健壮性。3. 编码问题查询参数中如果有中文或特殊符号如 #、、空格前端需要做 encodeURIComponent 编码。在后端FastAPI 会自动帮你解码无需担心。4. 长度限制虽然理论上查询参数可以有长度但浏览器和服务器对 URL 长度有限制通常 2048 字符左右。如果要上传大量结构化数据请用 POST 请求的 Body。八、结语对于普通 Web 用户而言查询参数就是你指尖在电商 App 上点击“筛选”、“排序”、“加载更多”时浏览器悄悄在背后执行的“数字指令”。它让无数海量数据变得井井有条让你能在毫秒间从上亿条商品中找到想要的那一款。对于 FastAPI 开发者而言查询参数是框架给予我们最慷慨的礼物之一。你不需要像 PHP 或原生 Node.js 那样费力地解析 req.query只需要在路由函数的参数列表里写上变量名FastAPI 就会自动把 URL 中 ? 后面的世界整理成整齐的 Python 变量送到你手边。