[Python] FastAPI, pydantic 환경에서 api response 수정하는 샘플 (MySql datetime 의 utc 정보 포함한 json encode)

By | 2월 18, 2022

환경

  • python 3.9
  • fastapi 0.73.0
  • pydantic 1.9.0 (VO객체 validtion, json encode/decode 등에 관여하는 라이브러리로 보임)


이슈

  • MySql에서 select한 datetime 컬럼을 별도의 형식 변환 없이 React client에 전달하고, React에서는 dayjs 를 사용하여 포맷팅/출력 해 주고 싶다.
  • 현재는 api response에 타임존(timezone) 정보가 없기 때문에 국제화 출력이 불가한 상태
  • 현재 DB의 timezone은 KST가 아닌 UTC라고 가정한다.


해결

  • 기본적으로 VO객체들은 pydantic의 BaseModel을 상속(?)받는 구조로 되어 있다. 이 BaseModel을 상속받는 다른 타입 BaseModelDtm을 정의하고, 이 정의에는 timezone 관련 json encoder를 추가 정의한다.
  • 이후 VO클래스는 BaseModel 대신 BaseModelDtm 을 사용하여 타입 정의를 한다.


소스

model.py

...

class BaseModelDtm(BaseModel):
    class Config:
        # pydantic 기본 셋팅에서 response 객체의 datetime 타입 필드가 ISO 8601 형식으로 json encode 되지 않는 문제가 있어서,
        # 해당 필드들이 ISO 8601 형태로 json encode 될 수 있도록 설정을 추가한 클래스 생성
        # 최초 config.py (Settings(BaseSettings) 클래스)에서 전역설정을 할 수 있기를 기대했으나 실패하여 이렇게 처리함.
        json_encoders = {
            # 이렇게 하니 timezone이 utc 라는 정보가 포함된다.
            datetime: lambda dt: dt.replace(
                microsecond=0, tzinfo=timezone.utc # 얘를 utc말고 kst 등으로 하는 방법은 아직 모르겠다.
            ).isoformat()
            # 이렇게 하니 timezone 정보가 포함되지 않는다 (BaseModelDtm 생성 전과 동일)
            # datetime: lambda dt: dt.isoformat()
        }

...

# class TestVO(BaseModel):
class TestVO(BaseModelDtm):
    id: Optional[str]
    name: Optional[str]
    create_time: Optional[datetime]
    update_time: Optional[datetime]
...


참고

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments