请求体¶
当你需要将数据从客户端(例如浏览器)发送到 API 时,你可以将其作为请求体发送。
请求体是客户端发送到 API 的数据。响应体是 API 发送到客户端的数据。
你的 API 几乎总是需要发送一个响应体。但客户端并不总是需要发送请求体,有时它们只请求一个路径,可能带有一些查询参数,但不发送请求体。
要声明一个请求体,你可以使用 Pydantic 模型,并利用其所有功能和优势。
Info
要发送数据,你应该使用以下方法之一:POST(更常见)、PUT、DELETE 或 PATCH。
在规范中,使用 GET 请求发送请求体的行为是未定义的,但 FastAPI 支持它,仅适用于非常复杂/极端的用例。
由于不鼓励这样做,使用 Swagger UI 的交互式文档在使用 GET 时不会显示请求体的文档,并且中间的代理可能不支持它。
导入 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
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[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
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[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
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[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 模式将成为生成的 OpenAPI 模式的一部分,并显示在交互式 API 文档中:

并且还将在每个需要它们的路径操作的 API 文档中使用:

编辑器支持¶
在你的编辑器中,在函数内部你将在各处获得类型提示和自动完成(如果你接收的是 dict 而不是 Pydantic 模型,则不会发生这种情况):

你还会获得对不正确类型操作的错误检查:

这不是偶然的,整个框架都是围绕该设计构建的。
并且在设计阶段进行了全面测试,确保它能与所有编辑器一起工作,然后才进行实现。
甚至对 Pydantic 本身进行了一些更改以支持此功能。
之前的截图是使用 Visual Studio Code 拍摄的。
但你在 PyCharm 和大多数其他 Python 编辑器中也会获得相同的编辑器支持:

Tip
如果你使用 PyCharm 作为编辑器,你可以使用 Pydantic PyCharm Plugin。
它通过以下方式改进了对 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.post("/items/")
async def create_item(item: Item):
item_dict = item.dict()
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
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
item_dict = item.dict()
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
Info
在 Pydantic v1 中,该方法称为 .dict(),在 Pydantic v2 中已弃用(但仍受支持),并重命名为 .model_dump()。
此处的示例使用 .dict() 以与 Pydantic v1 兼容,但如果你可以使用 Pydantic v2,则应使用 .model_dump()。
请求体 + 路径参数¶
你可以同时声明路径参数和请求体。
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.dict()}
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[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.dict()}
请求体 + 路径 + 查询参数¶
你还可以同时声明请求体、路径和查询参数。
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.dict()}
if q:
result.update({"q": q})
return result
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: Union[str, None] = None):
result = {"item_id": item_id, **item.dict()}
if q:
result.update({"q": q})
return result
函数参数将被识别如下:
- 如果参数也在路径中声明,它将被用作路径参数。
- 如果参数是单一类型(如
int、float、str、bool等),它将被解释为查询参数。 - 如果参数被声明为Pydantic 模型的类型,它将被解释为请求体。
Note
FastAPI 将知道 q 的值不是必需的,因为默认值为 = None。
str | None(Python 3.10+)或 Union 中的 Union[str, None](Python 3.8+)不被 FastAPI 用于确定该值不是必需的,它将知道它不是必需的,因为它具有默认值 = None。
但添加类型注释将使你的编辑器能够提供更好的支持并检测错误。
不使用 Pydantic¶
如果你不想使用 Pydantic 模型,你也可以使用 Body 参数。请参阅 Body - Multiple Parameters: Singular values in body 的文档。