请求体¶
当需要从客户端(例如浏览器)向 API 发送数据时,请将其作为请求体发送。
请求体是客户端发送给 API 的数据。响应体是 API 发送给客户端的数据。
API 几乎总是需要发送响应体。但客户端并不一定总是需要发送请求体;有时它们仅请求路径(可能带有查询参数),而不发送请求体。
要声明请求体,请使用 Pydantic 模型,以充分利用其强大的功能和优势。
信息
发送数据时,应使用以下方法之一:POST(最常用)、PUT、DELETE 或 PATCH。
在规范中,使用 GET 请求发送请求体的行为未定义。不过,FastAPI 仍然支持它,仅适用于非常复杂或极端的情况。
由于不推荐这样做,使用 GET 时,带有 Swagger UI 的交互式文档将不会显示请求体的文档,且中间代理可能不支持该行为。
导入 Pydantic 的 BaseModel¶
首先,你需要从 pydantic 导入 BaseModel
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
创建数据模型¶
然后,将数据模型声明为继承自 BaseModel 的类。
对所有属性使用标准 Python 类型
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
与声明查询参数时相同,如果模型属性具有默认值,则该属性不是必需的。否则,它是必需的。使用 None 可以使其变为可选。
例如,上面的模型声明了一个 JSON “object”(或 Python dict),如下所示:
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
...由于 description 和 tax 是可选的(默认值为 None),此 JSON “object” 也是有效的:
{
"name": "Foo",
"price": 45.2
}
声明为参数¶
要将其添加到路径操作中,请按照声明路径参数和查询参数的方式进行声明:
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
...并将其类型声明为你创建的模型 Item。
结果¶
只需这一行 Python 类型声明,FastAPI 就会:
- 将请求体读取为 JSON。
- 转换对应的类型(如果需要)。
- 校验数据。
- 如果数据无效,它将返回一个清晰明确的错误,指出错误数据的具体位置和原因。
- 在
item参数中提供接收到的数据。- 由于你在函数中将其声明为
Item类型,你还将获得针对所有属性及其类型的编辑器支持(自动补全等)。
- 由于你在函数中将其声明为
- 为你的模型生成 JSON Schema 定义;如果项目需要,你也可以在其他任何地方使用它们。
- 这些架构将成为生成的 OpenAPI 架构的一部分,并被自动文档 UI 使用。
自动文档¶
模型的 JSON Schema 将成为生成的 OpenAPI 架构的一部分,并显示在交互式 API 文档中。

并且也会用于每个需要它们的路径操作的 API 文档中。

编辑器支持¶
在编辑器中,你可以在函数内部随处获得类型提示和自动补全(如果接收的是 dict 而不是 Pydantic 模型,就不会有这些)。

你还可以针对错误的类型操作获得错误检查。

这不是偶然的,整个框架就是围绕这种设计构建的。
并且在设计阶段就进行了彻底测试,以确保它能与所有编辑器兼容。
甚至为了支持这一点,对 Pydantic 本身也进行了一些更改。
之前的截图是在 Visual Studio Code 中截取的。
但你在 PyCharm 和大多数其他 Python 编辑器中也能获得相同的编辑器支持。

使用模型¶
在函数内部,你可以直接访问模型对象的所有属性。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
item_dict = item.model_dump()
if item.tax is not None:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
return item_dict
请求体 + 路径参数¶
你可以同时声明路径参数和请求体。
FastAPI 将识别出与路径参数匹配的函数参数应从路径中获取,而声明为 Pydantic 模型的函数参数应从请求体中获取。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
return {"item_id": item_id, **item.model_dump()}
请求体 + 路径 + 查询参数¶
你也可以同时声明请求体、路径和查询参数。
FastAPI 将识别它们中的每一个,并从正确的地方获取数据。
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: str | None = None):
result = {"item_id": item_id, **item.model_dump()}
if q:
result.update({"q": q})
return result
函数参数将识别如下:
- 如果参数也在路径中声明,它将被用作路径参数。
- 如果参数是简单类型(如
int、float、str、bool等),它将被解释为查询参数。 - 如果参数声明为 Pydantic 模型类型,它将被解释为请求体。
注意
FastAPI 会知道 q 的值不是必需的,因为有默认值 = None。
str | None 并不是 FastAPI 判断值是否必需的依据,它知道不是必需的,是因为它有默认值 = None。
但添加类型注解可以使你的编辑器提供更好的支持并检测错误。
不使用 Pydantic¶
如果你不想使用 Pydantic 模型,也可以使用 Body 参数。请参阅 Body - 多参数:请求体中的简单值 的文档。