请求体¶
当您需要从客户端(例如浏览器)向您的 API 发送数据时,您将其作为 **请求体** 发送。
**请求** 体是由客户端发送到您的 API 的数据。**响应** 体是您的 API 发送到客户端的数据。
您的 API 几乎总是必须发送 **响应** 体。但是,客户端并不总是需要发送 **请求** 体,有时他们只请求路径,也许带有一些查询参数,但没有发送主体。
要声明 **请求** 体,您可以使用 Pydantic 模型及其所有功能和优势。
信息
要发送数据,您应该使用以下方法之一: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
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
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
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 Schema 将成为您生成的 OpenAPI Schema 的一部分,并将在交互式 API 文档中显示。
它还会在每个需要它们的路径操作的 API 文档中使用。
编辑器支持¶
在您的编辑器中,在您的函数内部,您将在任何地方获得类型提示和代码补全(如果您收到的是 dict
而不是 Pydantic 模型,这将不会发生)。
您还会获得对不正确的类型操作的错误检查。
这并非偶然,整个框架都是围绕该设计构建的。
并在设计阶段(在任何实现之前)经过了彻底测试,以确保它能够与所有编辑器一起使用。
甚至对 Pydantic 本身进行了一些更改来支持此功能。
之前的屏幕截图是在 Visual Studio Code 中拍摄的。
但是您将在 PyCharm 和大多数其他 Python 编辑器中获得相同的编辑器支持。
提示
如果您使用 PyCharm 作为您的编辑器,您可以使用 Pydantic PyCharm 插件。
它通过以下方式改善了 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:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
return item_dict
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:
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.dict()}
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
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 模型类型,则将被解释为请求主体。
注意
FastAPI 将知道 q
的值不是必需的,因为它的默认值为 = None
。
str | None
(Python 3.10+)或 Union
在 Union[str, None]
(Python 3.8+)中不会被 FastAPI 用于确定该值不是必需的,它将知道它不是必需的,因为它有一个默认值 = None
。
但添加类型注释将允许您的编辑器为您提供更好的支持和检测错误。
没有 Pydantic¶
如果您不想使用 Pydantic 模型,您也可以使用Body 参数。有关 Body - 多个参数:主体中的单一值,请参阅文档。