3_查询参数
查询参数(query parameters) 指 URL 中跟在路径参数后,以?
未开始,使用&
分割(如果有多个)的键值对形式的参数。
如果我们在路径参数函数的形参中定义了不属于路径参数的形参,那么它们将被自动解释为"查询字符串"参数。
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]
在上面的代码中,路径为/items/
,没有路径参数,所以函数中定义的skip
和limit
就会被认为是查询参数。
对应的URL可以是:http://127.0.0.1:8000/items/?skip=2&limit=15
此时查询参数为:skip = 2, limit=15
。
因为查询参数是URL的一部分,所以他们的原始类型是字符串
,不过在函数中,我们声明了他们的类型为 int
, 所以这两个值会自动转换为 int
类型并进行校验。
应用于路径参数的所有相同过程也适用于查询参数:
- 编辑器支持
- 数据解析
- 数据校验
- 自动生成文档
- 也可以使用
Enum
类型进行参数类型声明 - …
1. 默认值:
因为查询参数不是 URL 路径中的固定部分,所以他们是可选的,并且可以有默认值。
在上面的示例中,两个参数的默认值分别为skip=0
和limit=10
。
因此,当我们访问 URL:http://127.0.0.1:8000/items/
时,等同于访问 URL: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: 使用默认值
2. 可选参数:
我们也可以通过将一个查询参数的默认值设置为None
来声明这是一个可选的查询参数。
与普通查询参数的区别就是,普通查询参数在URL中不传递时它将使用默认值(不为None),可选查询参数在URL中不传递时它将为None。(好像是一句废话-_-||)
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None):
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
这里我们将查询参数q
的默认值设为了None
,则它就是一个可选查询参数。
FastAPI足够聪明,能分辨出item_id
是路径参数而q
不是,因此q
是一个查询参数。
3. 查询参数类型转换:
如果我们在函数的参数中将一个形参设置为 bool 类型,当URL中指定了该查询参数时,它将会被自动转换。
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[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
参数都会正确接收bool
值True
。False
同理。
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
...
4. 多个路径和查询参数:
在同一个URL 路径中我们可以声明多个路径参数和查询参数,FastAPI能够识别它们。
而且不需要以特定的顺序来声明对应的函数形参,FastAPI会通过名称区分参数。
from typing import Union
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: Union[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
和item_id
。在read_user_item
函数中指定了两个对应的形参。这两个形参可以不考虑顺序,即写为下面这样也是可以的。
@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
item_id: str, user_id: int, q: Union[str, None] = None, short: bool = False
):
...
5. 必需查询参数:
当我们为非路径参数声明了默认值时(目前,我们所知道的仅有查询参数),则该参数不是必需的。
如果不是想要添加一个特定的值,而只是想使该参数成为可选值,则将其默认值设置为None
即可。
但如果我们想要一个查询参数成为必需的,那么可以不对其设置默认值。
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
的必需查询参数。
如果你在浏览器中打开一个像下面的 URL:http://127.0.0.1:8000/items/foo-item
则会看到因为没有添加必需查询参数而导致的报错:
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
由于 needy 是必需参数,因此你需要在 URL 中设置它的值:http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
这样就正常了:
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
当然,我们也可以定义一部分参数是必需的,一部分是有默认值的,另一些是可选的, 一切按照自己API的需求而定:
from typing import Union
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: Union[int, None] = None
):
item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
return item
在这个例子中,有3个查询参数:
-
needy
:一个必需的str
类型参数。 -
skip
:一个默认值为0
的int
类型参数。 -
limit
:一个可选的int
类型参数。