首页 / FastAPI 入门教程 / 查询参数 Query Parameters

FastAPI 入门教程

查询参数 Query Parameters

本教程共 50 篇 · 第 8 篇 · 更新于 2026-08-12 · 约 7 分钟阅读

FastAPIFastAPI 入门教程查询参数Query Parameters可选参数必填参数

本节目标:搞懂 URL 里 ? 后面那些键值对怎么变成函数参数,以及「有没有默认值」如何决定参数必填还是可选。

路径参数写在 URL 的「路径」里,比如 /items/5。还有一类参数写在 ? 后面,多个之间用 & 连接,比如 /items/?skip=0&limit=10。这部分就叫查询参数(query parameters)。

8-1 声明一个查询参数

在 FastAPI 里,只要函数参数不是路径参数、也不是后面要学的请求体,它就被自动当成查询参数。你不用额外标注,写个类型加默认值就行:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/")
async def read_items(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}

访问 http://127.0.0.1:8000/items/?skip=0&limit=10,返回:

{"skip": 0, "limit": 10}

查询参数本来就是 URL 里的字符串,但因为你写了 int,FastAPI 会自动把它们转成整数,再做校验。编辑器补全、文档生成这些好处和路径参数一模一样。

8-2 有默认值就是可选

查询参数不在固定路径里,所以它天生可以「不传」。上面 skip=0limit=10 就是默认值。你不传它们也能正常访问:

  • 访问 /items/skip=0limit=10(都用默认)
  • 访问 /items/?skip=20skip=20limit=10(只传一个)
  • 访问 /items/?skip=20&limit=5 → 两个都传

所以判断一个查询参数是不是「可选」,看的就是它有没有默认值。有默认值 = 可选。

8-3 用 None 声明可选参数

如果你想让参数可选、但又不给它一个具体默认值,就把默认值写成 None,类型用 str | None 表示「字符串或者没有」:

from fastapi import FastAPI

app = FastAPI()


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

这里 item_id 是路径参数(在路径里),q 不是,所以 FastAPI 认出 q 是查询参数。访问 /items/5qNone,返回 {"item_id": 5};访问 /items/5?q=hello 时返回 {"item_id": 5, "q": "hello"}

Note

FastAPI 是靠「默认值 = None」判断参数可选的,不是靠 str | None 这个类型注解。类型注解主要帮你获得编辑器提示和错误检查,默认值才是关键。

8-4 类型转换:bool 也很聪明

查询参数能自动转成 bool。而且 FastAPI 接受多种写法来表示真:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, short: bool = False):
    if short:
        return {"item_id": item_id, "short": True}
    return {"item_id": item_id, "short": False}

下面这些 URL 里的 short 都会被当成 True

  • /items/foo?short=1
  • /items/foo?short=True
  • /items/foo?short=true
  • /items/foo?short=on
  • /items/foo?short=yes

大小写、首字母大写也认。不传时使用默认值 False;但如果传了无法识别为布尔的值(比如 ?short=abc),FastAPI 会返回 422 校验错误,而不是悄悄当作 False。这种宽容转换在开关类参数(比如「是否精简返回」)上很实用。

8-5 没有默认值就是必填

查询参数不一定都可选。只要你不给默认值,它就是必填参数。访问时没传,FastAPI 会直接报错:

from fastapi import FastAPI

app = FastAPI()


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

访问 /items/foo-item 会看到报错:

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

loc 里是 ["query", "needy"],明确告诉你缺的是查询参数 needy。必须访问 /items/foo-item?needy=sooooneedy 才正常返回。

8-6 必填、默认值、可选混在一起

同一个函数里可以既有必填、又有带默认值、还有完全可选的查询参数,也能混着路径参数一起用:

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,
):
    return {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}

这段代码的参数可以这样分类:

参数声明方式是否必填说明
item_iditem_id: str必填路径参数,在 URL 路径中
needyneedy: str必填查询参数,无默认值
skipskip: int = 0可选查询参数,默认 0
limitlimit: int | None = None可选查询参数,默认 None

8-7 多个路径与查询参数一起用

FastAPI 能同时认出多个路径参数和多个查询参数,而且顺序随便写,它靠「名字」匹配:

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 = {"user_id": user_id, "item_id": item_id}
    if q:
        item.update({"q": q})
    if not short:
        item.update({"description": "这是一段较长的描述文字"})
    return item

访问 /users/5/items/pen?q=red&short=true,FastAPI 会正确把 5user_idpenitem_idredqtrueshort。参数在函数里的先后顺序不影响识别。

Tip

路径参数必需、查询参数可选是通用规律,但查询参数也能设成必填(不写默认值即可)。设计接口时,把「一定有」的放路径,「可有可无」或「可选过滤条件」放查询。

8-8 在文档页面试查询参数

不用写前端也能验证查询参数。启动后打开 http://127.0.0.1:8000/docs,点开接口旁边的「Try it out」,在 skiplimitq 等框里填值,再点「Execute」,页面会直接拼出完整 URL 并展示返回的 JSON。这是调试查询参数最省事的办法,建议每次改完参数都去点一下确认效果。

如果你的参数带了 bool,文档里会显示下拉框,选 truefalse 即可,不必手敲字符串。fastapi dev 自带的热重载也会让你改完代码立刻生效,调试体验很顺。

还有一个细节值得留意:查询参数在 URL 里都是文本,所以中文或空格会被浏览器编码成 %E4%B8%AD 这类形式。你不用手动解码,FastAPI 会先还原成原始字符串,再按你声明的类型转换,函数里拿到的就是正常的中文。同理,同名参数出现多次时默认只取其中一个,若需要接收一组值,得把类型声明成列表,这属于下一章要讲的进阶校验范围。

8-9 小结

这一章的关键就一句话:函数里不在路径里、也不是请求体的参数,都是查询参数。有默认值 = 可选,无默认值 = 必填,默认值是 None 表示「可选但允许为空」。FastAPI 会自动把字符串转成你声明的类型,bool 还认 1/true/on/yes 等多种写法。多个参数可以和路径参数混用,名字对上就行。

下一章我们给查询参数加更细的校验,比如字符串最长多少字、必须匹配某个正则。