Pydantic v1→v2にアップデートしました(FastAPI)
概要
現在のFastAPIでのPJではPydantic v1が使用されておりました。
PJ配属一発目のタスクとして、v2アップデートを任命され遂行しましたので、内容をまとめてみます。
参考記事
基本的には以下の記事に沿ってアップデート対応を行いました。
対応内容
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
スキーマをカスタムデータタイプでタイプアノテーションしていた箇所を改修
スキーマをカスタムデータタイプでタイプアノテーションしていた箇所が、openapi.jsonに読み込まれなくなったので調整しました。
- domain: Domain
+ domain: Annotated[str, BeforeValidator(lambda v: Domain.validate(v))]
v1とv2のopenapi.jsonのスキーマ名の差異をなくす
同じPydanticModelをリクエストやレスポンスで使いまわしていると、v2ではopenapi.jsonのスキーマ名の末尾に-Input
や-Output
が付くようになっていました。
これをFastapiの以下のコードにて削除するようにしました。
app = FastAPI(separate_input_output_schemas=False)
Decimalの型がnumber→stringに変更
openapi.jsonに生成されるDecimalの型がnumber→stringに変更されます。
伴ってフロントの型もString()等で変換する必要があります。
Discussion