FastAPI 查询参数与字符串校验详解:类型、校验规则与元数据设置
本文详细介绍了 FastAPI 中查询参数的设置与校验方法,涵盖了可选参数、默认值、必要参数和参数列表的处理方式。通过使用 Query
类,开发者可以为查询参数添加额外的校验规则,如最小长度、最大长度、正则表达式匹配等,从而增强 API 数据的准确性。文中还讲解了如何为参数添加元数据信息,包括标题、摘要、描述等,以便在 Swagger UI 中更清晰地展示 API 信息,帮助用户构建严谨且具备良好文档支持的 API 接口。
文章目录
示例中使用的 Python 版本为 Python 3.10.15
,FastAPI 版本为 0.115.4
。
一 可选查询参数
from typing import Union, List
from fastapi import FastAPI, Query
from pydantic.v1 import Required
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
在上述示例中,查询参数 q
的类型为 str
,默认值为 None
,因此它是可选的。可运行代码文件 chapter05.py 来启动应用:
$ uvicorn chapter05:app --reload
在 SwaggerUI 中可以查看在线文档:http://127.0.0.1:8000/docs
。
二 参数的额外校验
@app.get("/items02/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
给查询参数 q
增加约束条件,该参数 max_length=50
即不能超过50个字符的长度:Query(default=None, max_length=50)
。 Query
用作查询参数的默认值,使用 Query(default=None)
替换默认值 None
。参数 q
为可选参数。
q: Union[str, None] = Query(default=None)
等同于:
q: str = None
完整的校验参数:
q: Union[str, None] = Query(default=None, max_length=50)
超过 50 字符长度,返回 422 错误码,错误信息如下:
{
"detail": [
{
"type": "string_too_long",
"loc": [
"query",
"q"
],
"msg": "String should have at most 50 characters",
"input": "超过50字符长的字符串",
"ctx": {
"max_length": 50
}
}
]
}
三 添加 min_length 校验
@app.get("/items03/")
async def read_items(
q: Union[str, None] = Query(default=None, min_length=3, max_length=50),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
四 添加正则表达式校验
@app.get("/items04/")
async def read_items(
q: Union[str, None] = Query(
default=None, min_length=3, max_length=50, pattern="^fixedquery$"
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
正则表达式 pattern="^fixedquery$"
用于限制 q
的值必须严格为 "fixedquery"
。这里的 ^
和 $
是正则表达式的锚点,分别表示字符串的开始和结束,确保除了 "fixedquery"
之外不接受任何其他字符。
五 添加默认值
可以向 Query
的第一个参数传入默认值,并将查询参数 q
的元数据 min_length
设置为 3
,默认值为 fixedquery
,例如:
@app.get("/items05/")
async def read_items(q: str = Query(default="fixedquery", min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
使用 Query 中的 default 设置默认值为 fixedquery
,具有默认值还会使该参数成为可选参数。
六 声明为必要参数
q
参数不声明任何默认值则它成为必要参数,例如:
q: str
1 使用 Query 声明
使用 Query
声明一个必要参数:
@app.get("/items06/")
async def read_items(q: str = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
2 使用 (…) 声明
显式的将默认参数的默认值设为 ...
:
@app.get("/items07/")
async def read_items(q: str = Query(default=..., min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
“...
” 是一个特殊的单独值,它是 Python 的一部分,被称为 Ellipsis(省略号),FastAPI 会识别此查询参数是必要的。
3 使用None
声明
声明None
是一个有效的类型,并仍然使用default=...
,这时查询参数仍然是一个必要参数:
@app.get("/items08/")
async def read_items(q: Union[str, None] = Query(default=..., min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Pydantic 文档中有关必要可选字段的信息。不习惯使用 ...
,也可以从 Pydantic 导入并使用 Required
:
@app.get("/items09/")
async def read_items(q: str = Query(default=Required, min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
一般情况下如果参数必须,那么省略 default
参数就好了。
七 查询参数列表 / 多个值
1 无默认值
使用 Query
显式地定义查询参数时,它可以接收多个值。
@app.get("/items10/")
async def read_items(q: Union[List[str], None] = Query(default=None)):
query_items = {"q": q}
return query_items
在路径操作函数的函数参数q
中,通过Python list
形式接收查询参数q
的多个值。当HTTP请求中查询参数q
出现多次时,该参数会以列表形式传入。输入如下网址:
http://localhost:8000/items10/?q=foo&q=bar
注:要声明类型为 list
的查询参数,如前例所示,你需要显式使用 Query
;否则,系统会将该参数解释为请求体。
2 有默认值
@app.get("/items11/")
async def read_items(q: List[str] = Query(default=["foo", "bar"])):
query_items = {"q": q}
return query_items
如果访问:
http://localhost:8000/items11/
响应会返回默认值。
3 使用 list 简写
使用 list
代替 List [str]
:
@app.get("/items12/")
async def read_items(q: list = Query(default=[])):
query_items = {"q": q}
return query_items
注:在这种情况下,FastAPI 不会验证列表内容,例如,使用 List[str]
时不会检查列表中的元素是否为字符串。
八 声明更多元数据
@app.get("/items13/")
async def read_items(
q: Union[str, None] = Query(
default=None,
alias="item-query",
summary="API 的简短摘要",
title="API 的标题",
description="API 的简短描述",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
参数列表
参数 | 类型 | 描述 |
---|---|---|
title | str | API 的标题。 |
summary | str | API 的简短摘要。 自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。. |
description | str | API 的简短描述。可以使用Markdown。 |
alias | str | 参数别名,该别名将用于在 URL 中查找查询参数值。 |
deprecated | str | deprecated=True 弃用参数,保留一段时间后弃用。 |
Swagger UI 文档展示
如图所示,元数据加载的信息较少,说明当前版本的 FastAPI 对 OpenAPI 的支持还不够完善。
九 完整代码示例
from typing import Union, List
from fastapi import FastAPI, Query
from pydantic.v1 import Required
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items02/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items03/")
async def read_items(
q: Union[str, None] = Query(default=None, min_length=3, max_length=50),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items04/")
async def read_items(
q: Union[str, None] = Query(
default=None, min_length=3, max_length=50, pattern="^fixedquery$"
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items05/")
async def read_items(q: str = Query(default="fixedquery", min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items06/")
async def read_items(q: str = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items07/")
async def read_items(q: str = Query(default=..., min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items08/")
async def read_items(q: Union[str, None] = Query(default=..., min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items09/")
async def read_items(q: str = Query(default=Required, min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
@app.get("/items10/")
async def read_items(q: Union[List[str], None] = Query(default=None)):
query_items = {"q": q}
return query_items
@app.get("/items11/")
async def read_items(q: List[str] = Query(default=["foo", "bar"])):
query_items = {"q": q}
return query_items
@app.get("/items12/")
async def read_items(q: list = Query(default=[])):
query_items = {"q": q}
return query_items
@app.get("/items13/")
async def read_items(
q: Union[str, None] = Query(
default=None,
alias="item-query",
summary="API 的简短摘要",
title="API 的标题",
description="API 的简短描述",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
十 源码地址
引用: FastAPI 文档
标签:None,items,校验,results,item,详解,FastAPI,Query,id From: https://blog.csdn.net/u014394049/article/details/143597748