7_请求体-多个参数
本章介绍请求体声明的高级用法。
1. 混合使用 Path、Query和请求体参数:
首先,毫无疑问,我们可以混合使用 Path
、 Query
和 请求体参数
声明, FastAPI会知道如何处理它们。
同样的,我们可以将请求体参数的默认值设置为 None
来将其声明为是可选的:
from fastapi import FastAPI, Path
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
q: str | None = None,
item: Item | None = None, # 将请求体设置为可选参数
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
if item:
results.update({"item": item})
return results
2. 多个请求体参数:
在上面的示例中,路径操作希望有一个具有 Item
的属性的JSON请求体,就像:
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
但是我们也可以声明多个请求体参数,例如 item 和 user:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
class User(BaseModel):
username: str
full_name: str | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User): # 添加多个请求体参数
results = {"item_id": item_id, "item": item, "user": user}
return results
在这种情况下,FastAPI将注意到该函数中有多个请求体参数(两个Pydantic 模型参数)。
因此,它将使用参数名称作为请求体中的键(字段名称),并期望一个类似于下面内容的请求体:
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
}
}
注意:即使
item
在函数中的声明方式与之前相同,但现在它被期望通过 JSON 对象中的item
键内嵌在请求体中。
FastAPI 将自动对请求中的数据进行转换,因此 item
参数将接收指定的内容,user
参数也是如此。
它将执行复合数据的验证,并将其作为OpenAPI模式和自动文档的文档内容。
3. 请求体中的单一值(singular value):
与使用 Query
和 Path
为查询参数和路径参数定义额外数据的方式相同。FastAPI同样为请求体提供了一个 Body
类。
Body
具有和 Query
、Path
相同的额外校验和元数据功能。
假如为了扩展之前的模型,我们决定除了 item
和 user
之外,还想在同一个请求体内加另外一个int
类型的键 importance
。
如果我们按照原样声明它,因为他是一个单一值,FastAPI会将其视为一个查询参数。
这时,就需要使用 Body
来指明它是一个请求体参数,FastAPI才会将其作为请求体的另一个键处理。
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
class User(BaseModel):
username: str
full_name: str | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User, importance: int = Body()): # 使用Body指明importance是请求体中的一个键
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
return results
在这种情况下, FastAPI 希望的请求体将像下面这样:
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
},
"importance": 5
}
同样的,他将转换数据类型,校验,生成文档等。
4. 多个请求体参数和查询参数:
除了请求体参数,我们还可以在任何需要的时候声明额外的查询参数。
由于默认情况下单一值会被视为查询参数,因此我们不必显式地加 Query
,仅需q: str = None
操作。
如:
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
class User(BaseModel):
username: str
full_name: str | None = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int, # 路径参数
item: Item, # 请求体参数
user: User, # 请求体参数
importance: int = Body(gt=0), # 请求体参数
q: str | None = None # 查询参数
):
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
if q:
results.update({"q": q})
return results
5. 嵌入单个请求体参数:
加入我们只有一个来自 Pydantic 的模型 Item 的请求体参数 item。
默认情况下,FastAPI将直接期望得到 item
对象的值:
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
但是,如果我们希望FastAPI期望一个拥有 item
键并在值中包含Item
模型内容的 JSON 请求体,则可以使用一个特殊的 Body
参数 embed
,就像在声明额外的请求体参数时所做的那样:item: Item = Body(embed=True)
。
如:
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item = Body(embed=True)): # 声明item作为键内嵌在请求体中
results = {"item_id": item_id, "item": item}
return results
这是,FatAPI期望的请求体将像下面这样:
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
}
总结:
你可以添加多个请求体参数到路径操作函数中,即使一个请求只能有一个请求体。
FastAPI 会处理它,在函数中为你提供正确的数据,并在路径操作中校验并记录正确的模式。
可以使用Body
声明将所接收的单一值作为请求体的一部分。
最后,还可以指示 FastAPI 在仅声明了一个请求体参数的情况下,将原本的请求体嵌入到一个键中。