跳转至

使用数据类

🌐 由 AI 与人类协作翻译

本翻译由人类引导的 AI 生成。🤝

可能存在误解原意或不够自然等问题。🤖

你可以通过帮助我们更好地引导 AI LLM来改进此翻译。

英文版本

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

这仍然得益于 Pydantic,因为它对 dataclasses 的内置支持

因此,即便上面的代码没有显式使用 Pydantic,FastAPI 也会使用 Pydantic 将那些标准数据类转换为 Pydantic 风格的 dataclasses。

并且,它仍然支持以下功能:

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

这与使用 Pydantic 模型时的工作方式相同。而且底层实际上也是借助 Pydantic 实现的。

信息

请注意,数据类不能完成 Pydantic 模型能做的所有事情。

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

但如果你已有一堆数据类,这个技巧可以让它们很好地为使用 FastAPI 的 Web API 所用。🤓

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"],
    }

该数据类会被自动转换为 Pydantic 的数据类。

这样,它的模式会显示在 API 文档界面中:

在嵌套数据结构中使用数据类

你也可以把 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",
                },
            ],
        },
    ]
  1. 我们仍然从标准库的 dataclasses 导入 field
  2. pydantic.dataclassesdataclasses 的可直接替换版本。
  3. Author 数据类包含一个由 Item 数据类组成的列表。
  4. Author 数据类被用作 response_model 参数。
  5. 你可以将其它标准类型注解与数据类一起用作请求体。

在本例中,它是一个 Item 数据类列表。 6. 这里我们返回一个字典,里面的 items 是一个数据类列表。

FastAPI 仍然能够将数据序列化为 JSON。 7. 这里的 response_model 使用了 “Author 数据类列表” 的类型注解。

同样,你可以将 dataclasses 与标准类型注解组合使用。 8. 注意,这个 路径操作函数 使用的是常规的 def 而不是 async def

一如既往,在 FastAPI 中你可以按需组合 defasync def

如果需要回顾何时用哪一个,请查看关于 asyncawait 的文档中的 “急不可待?” 一节。 9. 这个 路径操作函数 返回的不是数据类(当然也可以返回数据类),而是包含内部数据的字典列表。

FastAPI 会使用(包含数据类的)response_model 参数来转换响应。

你可以将 dataclasses 与其它类型注解以多种不同方式组合,来构建复杂的数据结构。

更多细节请参考上面代码中的内联注释提示。

深入学习

你还可以把 dataclasses 与其它 Pydantic 模型组合、从它们继承、把它们包含到你自己的模型中等。

想了解更多,请查看 Pydantic 关于 dataclasses 的文档

版本

自 FastAPI 版本 0.67.0 起可用。🔖