news 2026/9/9 20:32:03

FastAPI 从 Pydantic v1 迁移到 Pydantic v2:兼容窗口、`pydantic.v1` 过渡方案与分步迁移实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FastAPI 从 Pydantic v1 迁移到 Pydantic v2:兼容窗口、`pydantic.v1` 过渡方案与分步迁移实践

FastAPI 从 Pydantic v1 迁移到 Pydantic v2:兼容窗口、pydantic.v1过渡方案与分步迁移实践

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

本指南以 FastAPI 官方文档《Pydantic v1 から Pydantic v2 へのマイグレーション》为骨架,系统讲解 FastAPI 从支持 Pydantic v1 到全面转向 Pydantic v2 的版本历程、依托pydantic.v1兼容子模块的渐进式迁移方案,以及bump-pydantic一键自动化迁移等实战要点。读完你将掌握:在旧版 FastAPI 中如何混用 v1/v2 模型平滑过渡、当前 FastAPI 版本对pydantic.v1的硬性限制(源码级证据),以及一套"先测试、后工具、再手动"的可靠升级路径。

版本演进:Pydantic v1 在 FastAPI 中是如何逐步退场的

要理解迁移,先要看清 FastAPI 与 Pydantic 版本关系的完整时间线。从仓库文档整理出的官方口径如下:

  • FastAPI 0.100.0:同时支持 Pydantic v1 或 v2,具体取决于运行环境实际安装的是哪一版本;
  • FastAPI 0.119.0:为降低迁移成本,开始在 Pydantic v2 内部部分兼容Pydantic v1(通过pydantic.v1子模块引入);
  • FastAPI 0.126.0:正式停止对"原生安装的 Pydantic v1"的支持,但pydantic.v1子模块仍可继续使用一段时间;
  • FastAPI 0.128.0:连pydantic.v1子模块支持也一并移除,此后 FastAPI 的所有版本都强制要求 Pydantic v2

这一结论在当前仓库中可以得到直接验证:本文所在仓库的 pyproject.toml 中,运行依赖明确写为"pydantic>=2.9.0"(第 46 行)以及"pydantic >=2.9.0,<3.0.0"(第 154 行),也就是从依赖声明层面就排除了 Pydantic v1。

[!WARNING] Pydantic 团队已宣布:从Python 3.14起,最新版 Python 上不再支持 Pydantic v1,这同样覆盖pydantic.v1兼容子模块。因此若想使用 Python 3.14 及更新特性,请务必确认代码库中没有任何 Pydantic v1(含pydantic.v1)调用点。

迁移第一步:先阅读官方指南并保证测试覆盖

官方迁移指南

Pydantic 官方维护了一份 v1 到 v2 的正式迁移指南,其中系统说明了"哪些行为发生了变化、为什么 v2 的校验更精确也更严格、以及升级时可能踩到的坑"。在动手改代码前通读该指南,能帮助你理解改动背后的原因,而不是机械替换。

先把测试跑起来

在开始升级之前,务必确认应用已有 测试 并且测试能在持续集成(CI)中稳定运行。文档原文特别强调:这能确保你在一步步升级的过程中,随时验证"一切仍然按预期工作"。

[!TIP] 迁移的最小闭环是:先改 Pydantic 版本 → 跑测试 → 看失败 → 修代码 → 再跑测试。没有测试护航的迁移等于盲改。

自动化迁移:试试bump-pydantic

如果你的模型大多是"没有深度定制"的普通 Pydantic 模型,那么大量迁移工作其实可以交给自动化工具完成。

Pydantic 官方团队提供了bump-pydantic工具,它能够自动改写绝大多数需要变更的代码。使用流程很简单:

  1. 在代码库上运行bump-pydantic,让它批量改写 import、API 调用等差异点;
  2. 运行你的测试套件;
  3. 若全部通过,迁移即告完成。

文档对此的表述相当乐观:"跑完测试如果一切正常,那就结束了 😎"。当然前提是你的用法足够标准、没有触碰 v1/v2 行为差异巨大的边界特性(详见后文"校验行为差异"的提示)。

pydantic.v1:藏在 Pydantic v2 里的 v1 兼容子模块

为什么会有pydantic.v1

Pydantic v2 将 Pydantic v1 的全部内容以子模块pydantic.v1的形式内置。这意味着:只要你安装了较新的 Pydantic v2,就能从pydantic.v1中 import 旧的 v1 组件,效果等同于"仍然装着 Pydantic v1"——前提是你的 Python 版本不高于 3.13。

在代码层面,二者可以这样切换:

from pydantic.v1 import BaseModel class Item(BaseModel): name: str description: str | None = None size: float

(完整示例见 docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py,这段代码把BaseModel的 import 从pydantic换成了pydantic.v1,模型定义本身与 v1 时代完全一致。)

这是一个非常实用的"时间机器":升级 Pydantic 本身不再等于必须立刻重写所有模型,v1 语义的代码可以继续跑在 v2 的进程里。

FastAPI 对pydantic.v1的支持窗口(0.119.0 ~ 0.128.0)

[!WARNING] FastAPI 对pydantic.v1模型的支持是FastAPI 0.119.0 加入、FastAPI 0.128.0 移除的,本质上是为"迁移到 Pydantic v2"而设计的临时辅助能力。当前版本(本仓库为 0.141.1)的应用中若出现pydantic.v1模型会直接报错,本节后续描述仅适用于那段旧版本窗口。

在 0.119.0 起的过渡期,你只需要两步:

  1. 把 Pydantic 升级到最新的 v2;
  2. 把所有from pydantic import ...改成from pydantic.v1 import ...

多数场景下 FastAPI 就能继续正常工作:

from fastapi import FastAPI from pydantic.v1 import BaseModel class Item(BaseModel): name: str description: str | None = None size: float app = FastAPI() @app.post("/items/") async def create_item(item: Item) -> Item: return item

(完整示例见 docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py:路由的请求体解析、返回类型注解全部基于pydantic.v1.Item,FastAPI 在过渡版本中可正常完成校验与序列化。)

[!WARNING] 请注意 Pydantic 官方对 Python 3.14+ 停止支持 Pydantic v1 的公告同样作用于pydantic.v1。也就是说,即便你把 FastAPI 锁在 0.119.0~0.127.x,一旦升到 Python 3.14,这条路依然走不通。

为什么当前版本已彻底拒绝pydantic.v1

在当前仓库源码中,"拒绝 v1"是显式实现的,可以作为判断依据:

  • fastapi/exceptions.py 定义了专门异常类PydanticV1NotSupportedError,docstring 写明:"A pydantic.v1 model is used, which is no longer supported."
  • fastapi/utils.py 的create_model_field()在解析字段前调用annotation_is_pydantic_v1(type_)做前置检查,命中即抛出上述异常并提示 "Please update the response model";
  • fastapi/encoders.py 的jsonable_encoder()在序列化时若检测到pydantic.v1模型实例,同样直接抛PydanticV1NotSupportedError
  • 底层判定工具集中在 fastapi/_compat/shared.py:is_pydantic_v1_model_instanceis_pydantic_v1_model_classannotation_is_pydantic_v1三个函数会递归检查Union、序列等泛型注解内部是否混入了pydantic.v1类型。

从这套代码结构可以看出:当前 FastAPI 在请求体解析、参数校验、响应编码全链路都设了 v1 检测关卡——这正是 0.128.0 之后"硬切 v2"的技术落实。

同一应用内混用 v1 与 v2 模型的边界

不支持的用法:模型互相嵌套

Pydantic 官方不支持在 v2 模型的字段里定义 v1 模型,反之亦然:

这会造成字段级校验语义的混乱,属于架构层面的禁区,不要试图混用。

支持的用法:模型隔离共存

Pydantic v1 与 v2 可以共存于同一个应用,前提是两者保持独立、各自闭环:

在过渡期的 FastAPI 中,甚至可以在同一个路径处理函数里同时使用 v1 与 v2:一个模型负责入参校验,另一个负责出参序列化。

from fastapi import FastAPI from pydantic import BaseModel as BaseModelV2 from pydantic.v1 import BaseModel class Item(BaseModel): name: str description: str | None = None size: float class ItemV2(BaseModelV2): name: str description: str | None = None size: float app = FastAPI() @app.post("/items/", response_model=ItemV2) async def create_item(item: Item): return item

(完整示例见 docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py。此例中:请求体item: Itemv1 模型负责接收与校验,response_model=ItemV2v2 模型负责响应序列化,输入输出各司其职。)

这种"输入 v1、输出 v2"(或按业务模块切分)的组合,正是渐进迁移能够按组推进的基础。

Pydantic v1 参数:fastapi.temp_pydantic_v1_params

过渡期内,如果你的 v1 模型还需要配合BodyQueryForm等 FastAPI 专用参数工具使用,应从临时兼容模块 import,而不是从fastapi顶层 import:

from typing import Annotated from fastapi import FastAPI from fastapi.temp_pydantic_v1_params import Body from pydantic.v1 import BaseModel class Item(BaseModel): name: str description: str | None = None size: float app = FastAPI() @app.post("/items/") async def create_item(item: Annotated[Item, Body(embed=True)]) -> Item: return item

(完整示例见 docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py,其中用Annotated+Body(embed=True)把 v1 模型作为内嵌 body 参数传入。)

[!WARNING]fastapi.temp_pydantic_v1_params仅是临时桥接模块,随 v1 支持的移除一并消失——不要在面向未来的新代码中依赖它。本文仓库版本中已搜索不到该模块,印证了它属于已被清除的历史窗口产物。

推荐路径:按步骤、分组、渐进迁移

[!WARNING] 下述"同一应用中同时保留 v1 与 v2 模型"的渐进迁移方案,仅在 FastAPI 0.119.0 ~ 0.127.x 之间有效,FastAPI 0.128.0 起被移除,新版只接受纯 Pydantic v2 模型。若你已处于新版,请直接采用"全量改写"路径,不再有过渡期可用。

[!TIP] 再次强调:先跑bump-pydantic。如果测试通过、运行正常,一条命令就结束了 ✨。只有工具不适合你的使用场景时,才需要下面的手工渐进方案。

渐进迁移操作步骤

  1. 升级 Pydantic 到最新 v2。把全部from pydantic import ...改为from pydantic.v1 import ...,让整个应用先"跑在 v2 的 v1 兼容层上",行为与迁移前保持一致;
  2. 逐个模型组迁移到原生 v2。按模块或按业务边界,把模型从pydantic.v1.BaseModel改回pydantic.BaseModel,并同步处理 v2 的 API 差异;
  3. 每组迁移后立即跑测试。利用 v1/v2 同窗共存的能力,把"一次爆炸式重写"拆成多次小步提交,每步都可回滚、可验证。

手工迁移时的高频差异自查清单

以下差异虽不来自本仓库文档正文,但属于 v1→v2 迁移中最常见的拦路虎,供你在逐组改写时对照检查(建议结合官方迁移指南逐条核对):

  • 校验更严格:v2 会拒绝 v1 时代宽容接受的脏数据(如错误类型强制转换),原本"侥幸通过"的请求可能开始报 422;
  • validatorfield_validator/model_validator:装饰器名称与签名都变了,且默认不再自动pre=True
  • Config类 →model_config = ConfigDict(...):如orm_mode改名为from_attributes
  • .dict()/.json().model_dump()/.model_json_schema():序列化 API 全面更名;
  • parse_objmodel_validatefrom_ormmodel_validate(..., from_attributes=True)

遇到测试失败时,优先对照以上清单检查,多数 v1 风格代码都能机械改写成 v2 风格。

小结

从 FastAPI 的版本史可以看出 Pydantic 迁移的完整策略:pydantic.v1内置子模块争取迁移时间、用bump-pydantic处理机械改写、用 v1/v2 同窗机制支撑分步灰度,最终在 0.128.0 完成对 v1 的彻底告别。对仍在使用旧版 FastAPI + Pydantic v1 的项目,建议按本文顺序操作:先建好测试 → 跑bump-pydantic尝试一步到位 → 若不适用则升级 Pydantic 并在pydantic.v1兼容层上分模块渐进改写。而对于已经身处当前版本(FastAPI 0.141.1、强制pydantic>=2.9.0)的开发者,唯一正确姿势就是让代码库 100% 采用 Pydantic v2 语法——源码中遍布的PydanticV1NotSupportedError检查点会替你守护这条底线。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 20:30:27

Java集合实战:从零构建图书管理系统的完整复盘

开头先说明一下&#xff1a;这篇内容是我“day 11 练习”的完整复盘。练习内容是用 Java 集合写一个控制台版图书管理系统&#xff0c;重点围绕 ArrayList、HashMap、面向对象分层设计和输入校验展开。适合处于 Java 基础向面向对象过渡阶段的学习者参考&#xff0c;也适合想看…

作者头像 李华
网站建设 2026/9/9 20:28:27

docker compose unpause 使用指南:恢复暂停的 Compose 服务容器

docker compose unpause 使用指南&#xff1a;恢复暂停的 Compose 服务容器 【免费下载链接】compose Define and run multi-container applications with Docker 项目地址: https://gitcode.com/GitHub_Trending/compose/compose docker compose unpause 是 Docker Com…

作者头像 李华
网站建设 2026/9/9 20:26:30

彻底搞懂反向传播与自动求导:从矩阵微积分到PyTorch Autograd

先问大家一个可能被问过无数次的问题&#xff1a;训练神经网络的时候&#xff0c;那一行 loss.backward() 到底是在做什么&#xff1f;很多人的第一反应是“反向传播&#xff0c;算梯度”。但如果继续问“梯度具体是怎么沿着网络一层一层传回去的&#xff1f;”“为什么框架能…

作者头像 李华
网站建设 2026/9/9 20:24:25

0基础快速做出高质量PPT:工具推荐与实操指南

做PPT这件事&#xff0c;我真是被逼出来的。以前在学校当助教&#xff0c;每周都要帮导师做课件&#xff0c;后来自己做了教育博主&#xff0c;又得频繁出内容&#xff0c;加上一年里总要帮学生改几版答辩PPT&#xff0c;前前后后经手了不下几百套。见得多了就发现一个规律&…

作者头像 李华