FastAPI 如何用 dataclasses 声明请求体与 response_model 响应模型?
2026/9/12 6:44:04 网站建设 项目流程

FastAPI 如何用 dataclasses 声明请求体与 response_model 响应模型?

【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi

如果你手上已经有一批 Python 标准库dataclass,不想先改写成 Pydantic 模型就要在 FastAPI 里用起来,这篇文章给出完整路径:用标准库dataclasses直接声明请求体,用response_model参数声明 dataclass 响应模型,并用 HTTP 请求、/docs界面和/openapi.json三种方式核对结果。该能力自 FastAPI0.67.0起可用,底层由 Pydantic 完成标准dataclass到 Pydantic dataclass 的转换,因此同样支持数据校验、序列化和文档生成(见 Using Dataclasses)。

用标准库 dataclass 声明请求体

把代码保存为main.pyItem就是一个普通@dataclass,没有任何 Pydantic 导入:

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

完整示例见 tutorial001_py310.py。在main.py所在目录运行(命令来自 First Steps):

uv run fastapi dev

启动后服务地址为http://127.0.0.1:8000。发送一条合法请求:

curl -X POST http://127.0.0.1:8000/items/ \ -H "Content-Type: application/json" \ -d '{"name": "Foo", "price": 3}'

仓库测试 test_tutorial001.py 断言该请求返回200,响应为:

{"name": "Foo", "price": 3, "description": null, "tax": null}

再验证校验是否生效:把price传成字符串"invalid price",同一个测试断言返回422,响应体(文档示例)为:

{ "detail": [ { "type": "float_parsing", "loc": ["body", "price"], "msg": "Input should be a valid number, unable to parse string as a number", "input": "invalid price" } ] }

loc指向body下的price字段,说明标准库 dataclass 请求体走的是和 Pydantic 模型同样的校验流程。

用 response_model 声明 dataclass 响应模型

response_model参数可以直接接收 dataclass 类,dataclass 会被自动转换成 Pydantic dataclass,其 schema 会出现在/docs的 API 文档界面中。示例(见 tutorial002_py310.py):

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

两个要点:

  • 路径操作函数返回的是普通字典,response_model负责按Item结构序列化和过滤响应;
  • field(default_factory=list)来自标准库dataclasses,用于可变默认值(如列表),这是标准库 dataclass 的常规写法。

验证方式(仓库测试 test_tutorial002.py 中的断言):

  1. GET http://127.0.0.1:8000/items/next返回200,响应为{"name": "Island In The Moon", "price": 12.99, "description": "A place to be playin' and havin' fun", "tags": ["breater"], "tax": null}——注意未提供的tax字段会补为null
  2. GET http://127.0.0.1:8000/openapi.json,确认/items/next200响应 schema 指向#/components/schemas/Item,且Itemrequired["name", "price"]tags被识别为字符串数组。
  3. 打开http://127.0.0.1:8000/docs,在 Swagger UI 中可以看到Item的 schema。

嵌套结构:dataclass 组合列表,必要时换用 pydantic.dataclasses

dataclass 可以和其他标准类型注解组合成嵌套结构:response_model可以是AuthorAuthor内含list[Item],请求体也可以是list[Item](见 tutorial003_py310.py):

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. field仍从标准库dataclasses导入。
  2. 当自动生成的 API 文档出现错误时,把标准dataclasses换成pydantic.dataclasses,它是 drop-in replacement(可直接替换)。
  3. Author内含一个Itemdataclass 列表。
  4. Author作为response_model参数使用。
  5. 请求体用了普通类型注解list[Item],即 dataclass 也可以配合list等注解作请求体。
  6. 函数返回的字典里items是 dataclass 列表,FastAPI 能把它序列化为 JSON。
  7. response_model用了list[Author]这种类型注解。
  8. 该路径操作函数用普通def而非async def,两者可按需混用。
  9. 该函数返回的是字典列表而非 dataclass,FastAPI 会用response_model里的 dataclass 定义去转换响应。

验证方式(仓库测试 test_tutorial003.py 中的断言):

  1. POST http://127.0.0.1:8000/authors/foo/items/,请求体json=[{"name": "Bar"}, {"name": "Baz", "description": "Drop the Baz"}],返回200,响应为{"name": "foo", "items": [{"name": "Bar", "description": null}, {"name": "Baz", "description": "Drop the Baz"}]}——缺省的descriptionresponse_model补为null
  2. GET http://127.0.0.1:8000/authors/返回200和两个Author的列表。
  3. 检查/openapi.jsonAuthorrequired["name"]items是引用Item的数组;POST请求体的 schema 是items指向Item的数组,requiredTrue

限制与版本

  • dataclass 不能覆盖 Pydantic 模型的全部能力,文档明确提示:复杂场景下你可能仍需要使用 Pydantic 模型;pydantic.dataclasses只是在 API 文档生成出错时的替换方案。
  • 该功能自 FastAPI 版本0.67.0起可用。
  • 代码示例使用str | None这类联合类型写法,与docs_src*_py310示例文件对应(对应 Python 3.10 风格,仓库测试通过needs_py310标记运行)。

完成上述三步后,如果你的/docs中 schema 正确、/openapi.json$ref指向对应 dataclass、合法与非法请求分别返回200422,说明 dataclass 请求体和response_model均已按预期工作。更多 dataclass 与 Pydantic 模型混用的细节,见 Using Dataclasses 文档的 Learn More 一节。

【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询