🆙

Pydantic v1→v2にアップデートしました(FastAPI)

2025/01/25に公開

概要

現在のFastAPIでのPJではPydantic v1が使用されておりました。
PJ配属一発目のタスクとして、v2アップデートを任命され遂行しましたので、内容をまとめてみます。

参考記事

基本的には以下の記事に沿ってアップデート対応を行いました。
https://zenn.dev/tk_resilie/articles/fastapi0100_pydanticv2

https://docs.pydantic.dev/latest/migration/

対応内容

Pydantic v2のインストール

まずは、新たにPydanticをインストール!と思いましたが早速躓きました。

poetry add pydantic

なにやら依存しているemail-validatorのバージョンが低すぎるとのこと。
email-validatorも最新にアップデートしてから試すと上手くアップデートできました。

poetry remove email-validator
poetry add email-validator
poetry add pydantic

尚、この時点でテストが落ちまくっており、震えました、、。

validator → field_validator / root_validator → model_validator

validatorをfield_validatorに、root_validatorをmodel_validatorに置き換えました。
pre=Trueはmode="before"に、pre=Falseはmode="after"に変えます。
v1のpreのデフォルト値はFalseです。

- @validator("interval_date")
+ @field_validator("interval_date")
  def validate_interval_date(cls, v):

- @root_validator(pre=True)
+ @model_validator(mode="before")
  def validate_values(cls, values: dict):

class Config → model_config = ConfigDict() / orm_mode → from_attributes

class Configを使用している箇所を、 model_config = ConfigDict()に置き換えました。
orm_modeもfrom_attributesに変えました。

- class Config:
-     orm_mode = True

+ model_config = ConfigDict(from_attributes=True)

from_orm → model_validate

from_ormを使用している箇所を、 model_validateに置き換えました。

- Schema.from_orm(message)
+ Schema.model_validate(message)

dict → model_dump

dictを使用している箇所を、 model_dumpに置き換えました。

- value.dict()
+ value.model_dump()

EmailStr.validate → validate_email

EmailStr.validateを使用している箇所を、 validate_emailに置き換えました。

- EmailStr.validate(mail)
+ validate_email(mail)

オプショナルなスキーマにはデフォルト値Noneを定義

オプショナルなスキーマには全てデフォルト値Noneを定義しました。
v1ではデフォルト値Noneを定義しなくてもい暗黙的にNoneになっていたようですが、v2では= Noneの設定が必須になったようです。
これを対応しないと多数のバグが発生すると思われます。

- type: str | None
+ type: str | None = None

スキーマをカスタムデータタイプでタイプアノテーションしていた箇所を改修

Custom Data Types

スキーマをカスタムデータタイプでタイプアノテーションしていた箇所が、openapi.jsonに読み込まれなくなったので調整しました。

- domain: Domain
+ domain: Annotated[str, BeforeValidator(lambda v: Domain.validate(v))]

v1とv2のopenapi.jsonのスキーマ名の差異をなくす

同じPydanticModelをリクエストやレスポンスで使いまわしていると、v2ではopenapi.jsonのスキーマ名の末尾に-Input-Outputが付くようになっていました。
これをFastapiの以下のコードにて削除するようにしました。

main.py
app = FastAPI(separate_input_output_schemas=False)

参考

Decimalの型がnumber→stringに変更

openapi.jsonに生成されるDecimalの型がnumber→stringに変更されます。
伴ってフロントの型もString()等で変換する必要があります。

Discussion