跳到内容

使用 Dataclasses

FastAPI 构建在 Pydantic 之上,我一直在向您展示如何使用 Pydantic 模型来声明请求和响应。

但 FastAPI 也支持以相同的方式使用 dataclasses

from dataclasses import dataclass

from fastapi import FastAPI


@dataclass
class Item:
    name: str
    price: float
    description: str | None = None
    tax: float | None = None


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    return item
🤓 其他版本和变体
from dataclasses import dataclass
from typing import Union

from fastapi import FastAPI


@dataclass
class Item:
    name: str
    price: float
    description: Union[str, None] = None
    tax: Union[float, None] = None


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    return item

这仍然受 Pydantic 支持,因为它具有 dataclasses 的内部支持

因此,即使使用上面没有显式使用 Pydantic 的代码,FastAPI 也在使用 Pydantic 将这些标准 dataclasses 转换为 Pydantic 自有的 dataclass 类型。

当然,它也支持相同的

  • 数据验证
  • 数据序列化
  • 数据文档等。

这与 Pydantic 模型的工作方式相同。实际上,它在底层也是以相同的方式实现的,使用的是 Pydantic。

信息

请记住,dataclasses 无法做到 Pydantic 模型能做的一切。

因此,您可能仍然需要使用 Pydantic 模型。

但是,如果您身边有很多 dataclasses,这是一个很棒的技巧,可以使用它们来通过 FastAPI 驱动 Web API。 🤓

Dataclasses 在 response_model

您也可以在 response_model 参数中使用 dataclasses

from dataclasses import dataclass, field

from fastapi import FastAPI


@dataclass
class Item:
    name: str
    price: float
    tags: list[str] = field(default_factory=list)
    description: str | None = None
    tax: float | None = None


app = FastAPI()


@app.get("/items/next", response_model=Item)
async def read_next_item():
    return {
        "name": "Island In The Moon",
        "price": 12.99,
        "description": "A place to be playin' and havin' fun",
        "tags": ["breater"],
    }
🤓 其他版本和变体
from dataclasses import dataclass, field
from typing import Union

from fastapi import FastAPI


@dataclass
class Item:
    name: str
    price: float
    tags: list[str] = field(default_factory=list)
    description: Union[str, None] = None
    tax: Union[float, None] = None


app = FastAPI()


@app.get("/items/next", response_model=Item)
async def read_next_item():
    return {
        "name": "Island In The Moon",
        "price": 12.99,
        "description": "A place to be playin' and havin' fun",
        "tags": ["breater"],
    }

dataclass 将被自动转换为 Pydantic dataclass。

这样,其 schema 将显示在 API 文档用户界面中

Dataclasses 在嵌套数据结构中

您还可以将 dataclasses 与其他类型注释结合使用,以创建嵌套数据结构。

在某些情况下,您可能仍需要使用 Pydantic 的 dataclasses 版本。例如,如果自动生成的 API 文档出现错误。

在这种情况下,您可以简单地将标准的 dataclasses 替换为 pydantic.dataclasses,它是一个即插即用式替换项。

from dataclasses import field  # (1)

from fastapi import FastAPI
from pydantic.dataclasses import dataclass  # (2)


@dataclass
class Item:
    name: str
    description: str | None = None


@dataclass
class Author:
    name: str
    items: list[Item] = field(default_factory=list)  # (3)


app = FastAPI()


@app.post("/authors/{author_id}/items/", response_model=Author)  # (4)
async def create_author_items(author_id: str, items: list[Item]):  # (5)
    return {"name": author_id, "items": items}  # (6)


@app.get("/authors/", response_model=list[Author])  # (7)
def get_authors():  # (8)
    return [  # (9)
        {
            "name": "Breaters",
            "items": [
                {
                    "name": "Island In The Moon",
                    "description": "A place to be playin' and havin' fun",
                },
                {"name": "Holy Buddies"},
            ],
        },
        {
            "name": "System of an Up",
            "items": [
                {
                    "name": "Salt",
                    "description": "The kombucha mushroom people's favorite",
                },
                {"name": "Pad Thai"},
                {
                    "name": "Lonely Night",
                    "description": "The mostests lonliest nightiest of allest",
                },
            ],
        },
    ]
🤓 其他版本和变体
from dataclasses import field  # (1)
from typing import Union

from fastapi import FastAPI
from pydantic.dataclasses import dataclass  # (2)


@dataclass
class Item:
    name: str
    description: Union[str, None] = None


@dataclass
class Author:
    name: str
    items: list[Item] = field(default_factory=list)  # (3)


app = FastAPI()


@app.post("/authors/{author_id}/items/", response_model=Author)  # (4)
async def create_author_items(author_id: str, items: list[Item]):  # (5)
    return {"name": author_id, "items": items}  # (6)


@app.get("/authors/", response_model=list[Author])  # (7)
def get_authors():  # (8)
    return [  # (9)
        {
            "name": "Breaters",
            "items": [
                {
                    "name": "Island In The Moon",
                    "description": "A place to be playin' and havin' fun",
                },
                {"name": "Holy Buddies"},
            ],
        },
        {
            "name": "System of an Up",
            "items": [
                {
                    "name": "Salt",
                    "description": "The kombucha mushroom people's favorite",
                },
                {"name": "Pad Thai"},
                {
                    "name": "Lonely Night",
                    "description": "The mostests lonliest nightiest of allest",
                },
            ],
        },
    ]
  1. 我们仍然从标准的 dataclasses 中导入 field

  2. pydantic.dataclassesdataclasses 的一个即插即用式替换项。

  3. Author dataclass 包含一个 Item dataclasses 列表。

  4. Author dataclass 用作 response_model 参数。

  5. 您可以使用其他标准类型注释与 dataclasses 结合作为请求体。

    在这种情况下,这是一个 Item dataclasses 的列表。

  6. 这里我们返回一个包含 items 的字典,其中 items 是一个 dataclasses 列表。

    FastAPI 仍然能够 序列化 数据到 JSON。

  7. 这里 response_model 使用类型注释为 Author dataclasses 的列表。

    同样,您可以将 dataclasses 与标准类型注释结合使用。

  8. 请注意,此路径操作函数使用常规的 def 而不是 async def

    一如既往,在 FastAPI 中,您可以根据需要组合 defasync def

    如果您需要回顾何时使用哪种,请查看文档中关于 asyncawait 的“赶时间吗?”部分。

  9. 路径操作函数未返回 dataclasses(尽管它可以),而是返回一个包含内部数据的字典列表。

    FastAPI 将使用 response_model 参数(包括 dataclasses)来转换响应。

您可以将 dataclasses 与其他类型注释以多种不同组合结合使用,以形成复杂的数据结构。

请查看上面的代码内注释提示,了解更具体的细节。

了解更多

您还可以将 dataclasses 与其他 Pydantic 模型结合使用,继承它们,将它们包含在您自己的模型中,等等。

要了解更多信息,请查看 Pydantic 关于 dataclasses 的文档

版本

这从 FastAPI 版本 0.67.0 开始可用。 🔖