コンテンツにスキップ

Pydantic で Generic を扱う

Pydantic 1 系のGenericModelを使うと、型を指定しながら柔軟にモデルを定義できる。共通の構造を持つモデルを、内部のデータ型だけ差し替えて再利用したい場合に役立つ。コード例は Python 3.12.3、Pydantic 1.10.24 で動作を確認した。

from typing import Generic, TypeVar

from pydantic import BaseModel
from pydantic.generics import GenericModel

InnerT = TypeVar('InnerT')

class Outer(GenericModel, Generic[InnerT]):
    data: InnerT | None

class InnerX(BaseModel):
    x: int = 1

class InnerY(BaseModel):
    y: str = "foo"

class InnerZ(BaseModel):
    z: bool = True

ModelX = Outer[InnerX]
ModelY = Outer[InnerY]
ModelZ = Outer[InnerZ]

print(ModelX(data=InnerX()).dict())
# {'data': {'x': 1}}
print(ModelY(data=InnerY()).dict())
# {'data': {'y': 'foo'}}
print(ModelZ(data=InnerZ()).dict())
# {'data': {'z': True}}

モデルの動的生成

型のパラメータを切り替える Generic に対して、フィールドの構成自体を実行時に決めたい場合はcreate_modelでモデルを生成できる。

from pydantic import BaseModel, create_model


class FooModel(BaseModel):
    foo: str
    bar: int = 123


BarModel = create_model(
    'BarModel',
    apple='russet',
    banana='yellow',
    __base__=FooModel,
)
print(BarModel)
#> <class 'pydantic.main.BarModel'>
print(BarModel.__fields__.keys())
#> dict_keys(['foo', 'bar', 'apple', 'banana'])

参考