从 Pydantic v1 迁移到 Pydantic v2¶
如果你的 FastAPI 应用比较老旧,可能还在使用 Pydantic 第 1 版。
FastAPI 0.100.0 版本支持 Pydantic v1 或 v2。它会根据你安装的版本自动适配。
FastAPI 0.119.0 版本引入了对 Pydantic v2 中 Pydantic v1(即 pydantic.v1)的局部支持,以促进向 v2 的迁移。
FastAPI 0.126.0 版本取消了对 Pydantic v1 的支持,但在短期内仍支持 pydantic.v1。
警告
从 Python 3.14 开始,Pydantic 团队停止了在最新 Python 版本中对 Pydantic v1 的支持。
这包括 pydantic.v1,它在 Python 3.14 及以上版本中不再受支持。
如果你想使用 Python 的最新特性,则必须确保使用 Pydantic v2。
如果你的老旧 FastAPI 应用仍在使用 Pydantic v1,这里我将向你展示如何将其迁移到 Pydantic v2,以及 FastAPI 0.119.0 中的特性如何帮助你进行渐进式迁移。
官方指南¶
Pydantic 官方提供了从 v1 迁移到 v2 的 迁移指南。
指南涵盖了变更内容、如何使验证变得更正确和严格、潜在的注意事项等。
你可以通过阅读它来更好地理解变更点。
测试¶
请确保你的应用有 测试,并在持续集成(CI)中运行它们。
这样,你可以在升级的同时确保一切仍按预期工作。
bump-pydantic¶
在许多情况下,如果你使用的是没有自定义的常规 Pydantic 模型,你将能够自动完成大部分从 Pydantic v1 到 v2 的迁移过程。
你可以使用 Pydantic 团队提供的 bump-pydantic。
该工具将帮助你自动修改大部分需要更改的代码。
之后,你可以运行测试并检查一切是否正常。如果运行成功,那就大功告成了。😎
Pydantic v1 in v2¶
Pydantic v2 将 Pydantic v1 的所有内容作为子模块 pydantic.v1 包含在内。但此功能在 Python 3.13 以上版本中不再受支持。
这意味着你可以安装最新的 Pydantic v2,并像安装了旧版 Pydantic v1 一样,通过该子模块导入并使用旧的 Pydantic v1 组件。
from pydantic.v1 import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
size: float
FastAPI 对 Pydantic v1 in v2 的支持¶
自 FastAPI 0.119.0 起,为了方便向 v2 迁移,框架还增加了对 Pydantic v2 内部 Pydantic v1 的局部支持。
因此,你可以将 Pydantic 升级到最新的 v2 版本,将导入方式改为使用 pydantic.v1 子模块,在很多情况下代码可以直接运行。
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
警告
请记住,由于 Pydantic 团队在较新的 Python 版本(从 Python 3.14 开始)中不再支持 Pydantic v1,因此在 Python 3.14 及以上版本中使用 pydantic.v1 也不再受支持。
在同一个应用中同时使用 Pydantic v1 和 v2¶
Pydantic 不支持在一个 Pydantic v2 模型中将其字段定义为 Pydantic v1 模型,反之亦然。
graph TB
subgraph "❌ Not Supported"
direction TB
subgraph V2["Pydantic v2 Model"]
V1Field["Pydantic v1 Model"]
end
subgraph V1["Pydantic v1 Model"]
V2Field["Pydantic v2 Model"]
end
end
style V2 fill:#f9fff3
style V1 fill:#fff6f0
style V1Field fill:#fff6f0
style V2Field fill:#f9fff3
……但是,你可以在同一个应用中分开使用 Pydantic v1 和 v2 模型。
graph TB
subgraph "✅ Supported"
direction TB
subgraph V2["Pydantic v2 Model"]
V2Field["Pydantic v2 Model"]
end
subgraph V1["Pydantic v1 Model"]
V1Field["Pydantic v1 Model"]
end
end
style V2 fill:#f9fff3
style V1 fill:#fff6f0
style V1Field fill:#fff6f0
style V2Field fill:#f9fff3
在某些情况下,甚至可以在同一个 FastAPI 应用的路径操作中同时使用 Pydantic 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
在上述示例中,输入模型是一个 Pydantic v1 模型,而输出模型(在 response_model=ItemV2 中定义)是一个 Pydantic v2 模型。
Pydantic v1 参数¶
如果你需要在 Pydantic v1 模型中使用 FastAPI 的特定参数工具(如 Body、Query、Form 等),可以在迁移到 Pydantic v2 的过渡期内,从 fastapi.temp_pydantic_v1_params 导入它们。
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
分步迁移¶
提示
首先尝试使用 bump-pydantic,如果测试通过且工作正常,那么只需一条命令即可完成。✨
如果 bump-pydantic 不适用于你的用例,你可以利用在同一应用中同时支持 Pydantic v1 和 v2 模型的功能,逐步完成向 Pydantic v2 的迁移。
你可以先将 Pydantic 升级到最新的 v2 版本,并将所有模型的导入改为使用 pydantic.v1。
然后,你可以开始分批、分步骤地将模型从 Pydantic v1 迁移到 v2。🚶