当前位置: 首页 > news >正文

Python FastApi(7):请求体

1 多个参数

1.1 混合使用 PathQuery 和请求体参数

        首先,毫无疑问地,你可以随意地混合使用 PathQuery 和请求体参数声明,FastAPI 会知道该如何处理。你还可以通过将默认值设置为 None 来将请求体参数声明为可选参数:

from typing import Annotated

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: Annotated[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

        请注意,在这种情况下,将从请求体获取的 item 是可选的。因为它的默认值为 None

1.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"
    }
}

        FastAPI 将自动对请求中的数据进行转换,因此 item 参数将接收指定的内容,user 参数也是如此。它将执行对复合数据的校验,并且像现在这样为 OpenAPI 模式和自动化文档对其进行记录。

1.3 请求体中的单一值

        与使用 Query 和 Path 为查询参数和路径参数定义额外数据的方式相同,FastAPI 提供了一个同等的 Body。例如,为了扩展先前的模型,你可能决定除了 item 和 user 之外,还想在同一请求体中具有另一个键 importance

        如果你就按原样声明它,因为它是一个单一值,FastAPI 将假定它是一个查询参数。但是你可以使用 Body 指示 FastAPI 将其作为请求体的另一个键进行处理。

from typing import Annotated

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: Annotated[int, Body()]
):
    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
}

        同样的,它将转换数据类型,校验,生成文档等。

1.4 多个请求体参数和查询参数

        当然,除了请求体参数外,你还可以在任何需要的时候声明额外的查询参数。由于默认情况下单一值被解释为查询参数,因此你不必显式地添加 Query,你可以仅执行以下操作:

q: str = None
@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int,
    item: Item,
    user: User,
    importance: Annotated[int, Body(gt=0)],
    q: str | None = None,
):

   Body 同样具有与 QueryPath 以及其他后面将看到的类完全相同的额外校验和元数据参数。 

1.5 嵌入单个请求体参数

        假设你只有一个来自 Pydantic 模型 Item 的请求体参数 item。默认情况下,FastAPI 将直接期望这样的请求体。但是,如果你希望它期望一个拥有 item 键并在值中包含模型内容的 JSON,就像在声明额外的请求体参数时所做的那样,则可以使用一个特殊的 Body 参数 embed

item: Item = Body(embed=True)
from typing import Annotated

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: Annotated[Item, Body(embed=True)]):
    results = {"item_id": item_id, "item": item}
    return results

        在这种情况下,FastAPI 将期望像这样的请求体:

{
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    }
}

        而不是:

{
    "name": "Foo",
    "description": "The pretender",
    "price": 42.0,
    "tax": 3.2
}

2 字段

        与在路径操作函数中使用 QueryPath 、Body 声明校验与元数据的方式一样,可以使用 Pydantic 的 Field 在 Pydantic 模型内部声明校验和元数据。首先,从 Pydantic 中导入 Field

from typing import Annotated

from fastapi import Body, FastAPI
from pydantic import BaseModel, Field

        然后,使用 Field 定义模型的属性:

class Item(BaseModel):
    name: str
    description: str | None = Field(
        default=None, title="The description of the item", max_length=300
    )
    price: float = Field(gt=0, description="The price must be greater than zero")
    tax: float | None = None


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
    results = {"item_id": item_id, "item": item}
    return results

   模型属性的类型、默认值及 Field 的代码结构与路径操作函数的参数相同,只不过是用 Field 替换了PathQueryBody

3 嵌套模型

        使用 FastAPI,你可以定义、校验、记录文档并使用任意深度嵌套的模型(归功于Pydantic)。

3.1 List 字段

        你可以将一个属性定义为拥有子元素的类型。例如 Python list

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None
    tags: list = []

        这将使 tags 成为一个由元素组成的列表。不过它没有声明每个元素的类型。Python 有一种特定的方法来声明具有子类型的列表:

from typing import List, Union

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None
    tags: List[str] = []

        这完全是用于类型声明的标准 Python 语法。对具有子类型的模型属性也使用相同的标准语法。因此,在我们的示例中,我们可以将 tags 明确地指定为一个「字符串列表」。

3.2 Set 类型

        Python 具有一种特殊的数据类型来保存一组唯一的元素,即 set。然后我们可以导入 Set 并将 tag 声明为一个由 str 组成的 set

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None
    tags: set[str] = set()

        这样,即使你收到带有重复数据的请求,这些数据也会被转换为一组唯一项。而且,每当你输出该数据时,即使源数据有重复,它们也将作为一组唯一项输出。并且还会被相应地标注 / 记录文档。

3.3 嵌套模型

        Pydantic 模型的每个属性都具有类型。但是这个类型本身可以是另一个 Pydantic 模型。因此,你可以声明拥有特定属性名称、类型和校验的深度嵌套的 JSON 对象。上述这些都可以任意的嵌套。例如,我们可以定义一个 Image 模型:

class Image(BaseModel):
    url: str
    name: str

        然后我们可以将其用作一个属性的类型:

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None
    tags: set[str] = set()
    image: Image | None = None

        这意味着 FastAPI 将期望类似于以下内容的请求体:

{
    "name": "Foo",
    "description": "The pretender",
    "price": 42.0,
    "tax": 3.2,
    "tags": ["rock", "metal", "bar"],
    "image": {
        "url": "http://example.com/baz.jpg",
        "name": "The Foo live"
    }
}

        再一次,仅仅进行这样的声明,你将通过 FastAPI 获得:

  • 对被嵌入的模型也适用的编辑器支持(自动补全等)
  • 数据转换
  • 数据校验
  • 自动生成文档

3.4 特殊的类型和校验

        除了普通的单一值类型(如 strintfloat 等)外,你还可以使用从 str 继承的更复杂的单一值类型。例如,在 Image 模型中我们有一个 url 字段,我们可以把它声明为 Pydantic 的 HttpUrl,而不是 str

from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl

app = FastAPI()


class Image(BaseModel):
    url: HttpUrl
    name: str

        该字符串将被检查是否为有效的 URL,并在 JSON Schema / OpenAPI 文档中进行记录。

3.5 带有一组子模型的属性

        你还可以将 Pydantic 模型用作 listset 等的子类型:

class Image(BaseModel):
    url: HttpUrl
    name: str


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None
    tags: set[str] = set()
    images: list[Image] | None = None

        这将期望(转换,校验,记录文档等)下面这样的 JSON 请求体:

{
    "name": "Foo",
    "description": "The pretender",
    "price": 42.0,
    "tax": 3.2,
    "tags": [
        "rock",
        "metal",
        "bar"
    ],
    "images": [
        {
            "url": "http://example.com/baz.jpg",
            "name": "The Foo live"
        },
        {
            "url": "http://example.com/dave.jpg",
            "name": "The Baz"
        }
    ]
}

3.6 深度嵌套模型

        你可以定义任意深度的嵌套模型:

class Image(BaseModel):
    url: HttpUrl
    name: str


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None
    tags: set[str] = set()
    images: list[Image] | None = None


class Offer(BaseModel):
    name: str
    description: str | None = None
    price: float
    items: list[Item]

3.7 纯列表请求体

        如果你期望的 JSON 请求体的最外层是一个 JSON array(即 Python list),则可以在路径操作函数的参数中声明此类型,就像声明 Pydantic 模型一样:

images: List[Image]
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl

app = FastAPI()


class Image(BaseModel):
    url: HttpUrl
    name: str


@app.post("/images/multiple/")
async def create_multiple_images(images: list[Image]):
    return images

相关文章:

  • 在win11 环境下 新安装 WSL ubuntu + 换国内镜像源 + ssh + 桌面环境 + Pyhton 环境 + vim 设置插件安装
  • 私有化部署dify + DeepSeek-R1-Distill-Qwen-32B + bge-m3
  • Razer macOS v0.4.10快速安装
  • 【21期获取股票数据API接口】如何用Python、Java等五种主流语言实例演示获取股票行情api接口之沪深A股阶段主力动向数据及接口API说明文档
  • 【Linux】System V信号量与IPC资源管理简易讲解
  • Dubbo 通信流程 - 服务的调用
  • TCP可靠传输与慢启动机制
  • 项目上传github——SSH连接配置文档
  • 无参数读文件RCE
  • STRUCTBERT:将语言结构融入预训练以提升深度语言理解
  • AWS Aurora存算分离架构
  • Java可变参数:灵活的函数调用方式
  • 前端Material-UI面试题及参考答案
  • 洛谷题单1-P1001 A+B Problem-python-流程图重构
  • 初识 spring ai 之rag、mcp、tools calling使用
  • 存储效能驱动业务价值:星飞全闪关键业务场景性能实测报告
  • 解释 Webpack 中的模块打包机制,如何配置 Webpack 进行项目构建?
  • 调用deepseek大模型时智能嵌入函数
  • 使用 Spring AI Aliabab Module RAG 构建 Web Search 应用
  • 中药材图像分类,解锁小样本高精度建模秘籍-MATLAB赋能科研:基于AlexNet的迁移学习
  • 外贸做网站的好处/2345网址导航浏览器
  • 织梦做中英文企业网站/seo搜索优化排名
  • 商丘企业网站建设公司/推手平台哪个靠谱
  • 哪家网站建设公司比较好/百度搜索风云榜总榜
  • 网站设计培训班老师/seo排名赚挂机
  • 淘宝客做网站推广赚钱吗/网店代运营哪个好