pydantic を使う

FastAPI で使う場面でなくても、SQLAlchemy や、いろんな場面でも使えるし
むしろ使った方が良いと思う pydantic
公式マニュアルは、→ https://docs.pydantic.dev/latest/

必要なインポート

from pydantic import BaseModel, ValidationError

サンプル

class Item(BaseModel):
    name :str
    price :int

この name と price は必須になって

try:
    item = Item(name="ABC")
    print(item.__str__())
except ValidationError  as e:
    print(e.json())

バリデーションエラー(ValidationError)発生して

[{"type":"missing","loc":["price"],"msg":"Field required","input":{"name":"ABC"},"url":"https://errors.pydantic.dev/2.7/v/missing"}]

になる。

class Item(BaseModel):
    name :str
    price :int=1000

とすれば、

    item = Item(name="ABC")
    print(item.__str__())
    # dict 型でダンプ
    item_dict = item.model_dump()
    print(item_dict)
    # JSON ダンプ
    print(item.model_dump_json())

に結果は

name='ABC' price=1000
{'name': 'ABC', 'price': 1000}
{"name":"ABC","price":1000}

必須でなく Optional で定義する

from typing import Optional

class Item(BaseModel):
    name :str
    price :Optional[int] = None

結果は、、

name='ABC' price=None
{'name': 'ABC', 'price': None}
{"name":"ABC","price":null}

Constrained Types 条件付きの型

constr, conint, condate など、、、

from pydantic import BaseModel, constr, conint, condate
def constr(
    *,
    strip_whitespace: bool | None = None,
    to_upper: bool | None = None,
    to_lower: bool | None = None,
    strict: bool | None = None,
    min_length: int | None = None,
    max_length: int | None = None,
    pattern: str | Pattern[str] | None = None,
) -> type[str]:
def conint(
    *,
    strict: bool | None = None,
    gt: int | None = None,
    ge: int | None = None,
    lt: int | None = None,
    le: int | None = None,
    multiple_of: int | None = None,
) -> type[int]:
condate(
    *,
    strict: bool | None = None,
    gt: date | None = None,
    ge: date | None = None,
    lt: date | None = None,
    le: date | None = None
) -> type[date]

条件付きの型を持つ

class Item(BaseModel):
    name :constr(min_length=5)
    price :conint(gt=2)=3
    ondate :condate(gt=datetime.date(2024, 6, 1))

これは、デフォルト値を定義していなう。

デフォルトを定義した( con*(~) = デフォルト値 ) モデル

class Item(BaseModel):
    name :constr(min_length=5) = "ABC00"
    price :conint(gt=4) = 10
    ondate :condate(ge=datetime.date(2024, 4, 1))

Field を使えば、同じことができる。

from pydantic import BaseModel, Field

class Item(BaseModel):
    name : str=Field(default="ABC00", min_length=5)
    price : int=Field(10, gt=4)
    ondate : datetime.date=Field(datetime.date.today(), gt=datetime.date(2024, 6, 1))

Field が便利で、Field で書くのが多いのではなかろうか。。。