首页
/ FastAPI 查询参数(Query Parameters)完全指南:默认值、可选与必填、布尔转换一网打尽

FastAPI 查询参数(Query Parameters)完全指南:默认值、可选与必填、布尔转换一网打尽

2026-09-07 22:20:03作者:温艾琴Wonderful

本篇指南基于仓库内 docs/de/docs/tutorial/query-params.md(对应英文版 query-params.md)及配套可运行示例编写,系统讲解 FastAPI 中查询参数(Query Parameters)的声明方式、URL 解析规则、默认值/可选性/必填性三态模型以及 bool 类型转换行为。读完你既能用普通函数参数写出分页、过滤等典型查询参数接口,也能从源码与测试层面理解 FastAPI 是如何自动区分路径参数与查询参数的。

一、什么是查询参数:URL 中 ? 之后的键值对

HTTP 请求的 URL 中可以携带一组查询参数(Query,也叫 query string)。它由 ? 之后、以 & 分隔的多个"键=值"对组成。例如在 URL:

http://127.0.0.1:8000/items/?skip=0&limit=10

中就包含了两个查询参数:

  • skip:值为 0
  • limit:值为 10

查询参数是 URL 的一部分,因此它们在"本性"上是字符串——无论你写入 0 还是 10,到达服务端时最初都是字符串 "0""10"

但 FastAPI 的强大之处在于:当你在路径操作函数中把这些参数用 Python 类型标注声明(例如标注为 int)时,FastAPI 会自动把它们转换(parse/convert)成对应类型,并按该类型校验。它与路径参数享受同一套完整流程:

  • 编辑器支持(IDE 补全、类型提示)
  • 数据"解析"——把来自 HTTP 请求的字符串转换为 Python 数据
  • 数据校验
  • 自动生成交互式 API 文档

二、极速上手:把非路径参数变成查询参数

FastAPI 的约定非常简洁:凡是函数里声明了、又不是路径参数的其他参数,一律被自动当作查询参数。

配套示例 tutorial001_py310.py 演示了最经典的分页场景:

from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]

这段代码声明了两个查询参数:

  • skip: int = 0:切片起点,默认 0
  • limit: int = 10:切片条数,默认 10

通过 fake_items_db[skip : skip + limit] 实现数据库"假分页"。将本文件保存为 main.py 后,在仓库环境执行 fastapi dev main.py(或 uvicorn main:app --reload)即可启动:

  • 访问 http://127.0.0.1:8000/items/?skip=0&limit=10,函数收到的就是 skip=0limit=10,返回三条数据;
  • 交互式文档位于 http://127.0.0.1:8000/docs,此时你能在 Swagger UI 上看到自动生成的 skiplimit 两个查询参数输入框——这就是"自动文档"特性的直观体现。

三、默认值:查询参数天然"可选"

由于查询参数不是路径的固定组成部分,它们天然可以是可选的,并且可以有默认值

接续上面的例子:skip 默认 0limit 默认 10。于是访问不带任何查询字符串的:

http://127.0.0.1:8000/items/

等价于访问:

http://127.0.0.1:8000/items/?skip=0&limit=10

而如果你显式提供部分参数,例如:

http://127.0.0.1:8000/items/?skip=20

那么函数收到的实际参数值为:

  • skip = 20:因为你已在 URL 中显式设置;
  • limit = 10:因为未提供,回落至默认值。

注意这里"默认值 = 未在 URL 中出现"的回退语义,是后续理解必填/可选参数的关键前提。

四、可选参数:把默认值设为 None

想让某个查询参数完全可选(可以不出现在 URL 中)时,只需把它的默认值设为 None。示例 tutorial002_py310.py

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}

这里函数参数 q 被声明为 str | None = None,因此它成为可选查询参数,请求未携带 q 时其值就是 None,函数只返回 {"item_id": item_id};携带 q 时则额外返回其值。

细心的读者会发现:同一个函数里同时出现了 `item_id`(出现在路径 `/items/{item_id}` 中)和 `q`。**FastAPI 足够智能**:`item_id` 因出现在路径模板中而被识别为路径参数,而 `q` 不在路径里,自然就被归类为查询参数——无需你做任何额外标记。

这种"按名称与位置自动区分"的能力,正是本指南第五节到第八节所有写法的基石。

五、类型转换:bool 查询参数怎么"真"

查询参数不仅能转成 int,同样能声明为 bool 并自动完成字符串→布尔值转换。示例 tutorial003_py310.py

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None, short: bool = False):
    item = {"item_id": item_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

访问下面的任意 URL,函数收到的 short 参数值都会是 True

http://127.0.0.1:8000/items/foo?short=1
http://127.0.0.1:8000/items/foo?short=True
http://127.0.0.1:8000/items/foo?short=true
http://127.0.0.1:8000/items/foo?short=on
http://127.0.0.1:8000/items/foo?short=yes

以及其他任何大小写变体(全大写、首字母大写……如 ONYesTRUE),都会把 short 解析为布尔值 True;否则为 False。换句话说,bool 转换是对大小写不敏感的。

在实际接口中,这种写法非常适用于"是否返回完整描述""是否包含明细"等开关型参数——上例中 short=False(默认)时返回详细 descriptionshort=True 时只返回精简字段。上述五个 URL 与对应行为的断言,可以在仓库测试 test_query_params/test_tutorial003.py 中逐条找到。

六、混合声明:多个路径参数 + 多个查询参数

你完全可以在同一个函数里同时声明多个路径参数和多个查询参数,FastAPI 总能分清谁是谁——关键在于按参数名识别,而不是按声明顺序。示例 tutorial004_py310.py

from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
    user_id: int, item_id: str, q: str | None = None, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

这个接口包含:

参数 位置类型 类型 默认值
user_id 路径参数 int 无(必填)
item_id 路径参数 str 无(必填)
q 查询参数 str | None None(可选)
short 查询参数 bool False

即便把参数顺序任意打乱(例如把 q 写在 user_id 前面),FastAPI 依然能通过路径模板与类型标注精确判定各自归属。这也印证了该教程的设计哲学:"路径模板决定路径参数,其余全部归属查询"。运行测试见 test_query_params/test_tutorial004.py

七、必填查询参数:不给默认值即可

前文规则可总结为:对非路径参数声明了默认值,它就不是必填的;而如果只是想让它"可选且默认无值",把默认值设成 None

那么想让查询参数必填怎么办?答案很简单——不声明任何默认值。示例 tutorial005_py310.py

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
    item = {"item_id": item_id, "needy": needy}
    return item

此处查询参数 needy 是一个必填的 str。若在浏览器中直接访问:

http://127.0.0.1:8000/items/foo-item

即 URL 中没有携带必需的 needy,FastAPI 会返回类似如下的校验错误 JSON:

{
  "detail": [
    {
      "type": "missing",
      "loc": [
        "query",
        "needy"
      ],
      "msg": "Field required",
      "input": null
    }
  ]
}

可以看到 loc 字段明确指出了出错位置:"query" 作用域下名为 "needy" 的参数缺失,type"missing"。这是 FastAPI 内置校验器(底层由 Pydantic 驱动)产出的标准结构,HTTP 响应码为默认的校验失败状态(细节可参考 handling-errors.md)。

补上该参数即可正常访问:

http://127.0.0.1:8000/items/foo-item?needy=sooooneedy

返回:

{
    "item_id": "foo-item",
    "needy": "sooooneedy"
}

八、三态齐备:必填 + 带默认值 + 完全可选

真实业务中常常需要同一接口内混合三种参数形态。示例 tutorial006_py310.py 给出了最终形态:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(
    item_id: str, needy: str, skip: int = 0, limit: int | None = None
):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item

这个接口里共存着 3 个查询参数:

  • needy必填str,没有默认值,缺失即报 missing 错误;
  • skipint带默认值 0,可省略;
  • limit可选int,声明为 int | None = None,可省略且省略时为 None

注意 needyskiplimit 的区别:skip 省略时会有确定值 0,而 limit 省略时是 None(表示"调用方未指定上限"),这为业务逻辑区分"未传"与"传了 0"提供了依据。对应测试见 test_query_params/test_tutorial006.py

进阶用法:查询参数同样可以使用 `Enum` 枚举类型,限定其只能取若干预定义值——用法与[路径参数中的预定义值](https://gitcode.com/GitHub_Trending/fa/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/docs/de/docs/tutorial/path-params.md?utm_source=gitcode_repo_files#predefined-values)完全一致。而更丰富的声明能力(`Query` 显式声明、长度/数值校验等)见后续教程 [query-params-str-validations.md](https://gitcode.com/GitHub_Trending/fa/fastapi/blob/50113da16fec53b66b80d75e80a89296de4fa5a5/docs/en/docs/tutorial/query-params-str-validations.md?utm_source=gitcode_repo_files)。

九、源码佐证:FastAPI 究竟如何识别查询参数

上述"魔法"在框架源码中有着清晰的落点。在 fastapi/params.py 中可以看到查询参数描述符的定义:

class Query(Param):  # type: ignore[misc]
    in_ = ParamTypes.query

    def __init__(
        self,
        default: Any = Undefined,
        *,
        default_factory: Callable[[], Any] | None = _Unset,
        ...
    ):
  • ParamTypes.query 标记了该类参数所属的请求位置(query string),这正是 FastAPI 内部把"非路径参数"归属到查询参数位置的组织方式;
  • default: Any = Undefined 与默认值机制直接相关:你在函数签名里写的 = 10= None 会进入该默认值解析路径,而没有默认值的 needy 会保持"必填"语义;
  • 声明了默认值的简单写法(如 skip: int = 0)会被 FastAPI 在路由注册时自动包装成 Query(...) 描述符,因此教程正文没有出现任何额外的 Query import——这是"尽量简单"设计的体现。

配合类型注解,FastAPI 在路由构建阶段便能确定:

  1. 参数是否出现在路径模板中(是 → 路径参数,且不允许有默认值);
  2. 否则即为查询参数,并根据 Python 类型(int/bool/str/None)确定解析与校验规则;
  3. 生成的 OpenAPI 中为每个查询参数生成 schema 条目,进而在 /docs 自动文档中渲染出输入框与必填标记。

仓库 tests/test_tutorial/test_query_params/ 下与 tutorial001tutorial006 一一对应的测试文件,覆盖了默认值、可选、必填、布尔转换等全部行为,可作为行为规格直接查阅。

十、小结与下一步

小结本节学到的查询参数核心规则:

声明方式 参数性质 缺省行为
skip: int = 0 有默认值的查询参数 取默认值
q: str | None = None 可选查询参数 None
needy: str(无默认值) 必填查询参数 返回校验错误
short: bool = False 布尔查询参数 1/true/on/yes/True(任意大小写)→ True

掌握这些之后,你已能独立写出带分页、可选过滤与布尔开关的真实接口。更进一步的约束能力——例如给查询参数加最小/最大长度、正则校验、显式标题与描述等——请继续阅读 查询参数与字符串校验,并在交互式文档中实时观察每一项约束对 OpenAPI 描述的影响。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388