技術的な話

Pydanticで自作共通クラスを継承していく

Fast APIを使用していてResponseを返す際に自作クラスのJSONデータを返していたのですが、共通使用したい項目については共通クラスを継承させて使いまわしたい時があると思ったのでやってみました。

https://pydantic-docs.helpmanual.io/

共通クラスの用意

共通使用する項目(今回はアクセス時間)を定義します。
ポイントは__new__の部分でしょうか。値の検証せずにモデルを作成するconstruct()を呼び出しています。
値を検証したい場合は今回の方法は不向きなのかもしれません。

from typing import Any, Optional
from datetime import datetime
from pydantic import BaseModel

class MessageBase(BaseModel):

    accessTimeText: Optional[str] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    def __init__(self) -> None:
        super().__init__()

    def __new__(cls) -> Any:
        cls.__new__ = super().__new__
        return super().construct()

https://pydantic-docs.helpmanual.io/usage/models/#creating-models-without-validation

継承するクラスの用意

シンプルにmessageのみを定義しています。
また、前述している共通クラスを継承しています。

from typing import Any, Optional
from models.message_base import MessageBase

class Message(MessageBase):

    message: Optional[str] = ''

    def __init__(self) -> None:
        super().__init__()

    def __new__(cls) -> Any:
        return super().__new__(cls)

Fast APIに組み込んでいく

/sampleにアクセスすると作成したクラスのjsonを返すようにしています。

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from models.message import Message

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/sample", response_model=Message)
def sample() -> JSONResponse:
    res = Message()
    res.message = 'hello!!'
    return JSONResponse(content=jsonable_encoder(res))

ブラウザからアクセスすると上記のようにJSONメッセージを返してくれます。
継承したクラスの要素と呼び出したクラスの要素がそれぞれ返ってきています。

また、Fast APIで生成されるswaggerも確認してみます。

少し見ずらいですがこちらも想定通り反映されています。

-技術的な話
-, ,