본문 바로가기

카테고리 없음

Pydantic model_config 속성 정리

반응형

model_config

- 딕셔너리를 사용하여 모델 전체에 대한 설정을 선언

- 모델의 동작 방식, 직렬화/역직렬화 규칙, 필드 처리 방식 등을 제어하는 메타 설정

✅ 기본 예시

class MyModel(BaseModel):
    id: int
    name: str

    model_config = {
        "title": "사용자 모델",
        "from_attributes": True,
        "populate_by_name": True,
    }

✅ 주요 model_config 속성과 설명

속성명 설명
title 모델의 제목(문서화, OpenAPI 등에서 사용됨)
description 모델 설명
from_attributes ✅ ORM 객체나 일반 객체에서 속성 기반으로 필드 값을 추출할 수 있게 함 (from_orm=True 대체)
populate_by_name 필드 alias가 있더라도 실제 변수명으로도 값을 넣을 수 있게 허용
extra 모델 정의에 없는 필드에 대해 허용할지 설정 ("ignore", "allow", "forbid")
str_strip_whitespace str 필드에서 자동으로 앞뒤 공백 제거
str_min_length, str_max_length 모든 str 필드에 대한 기본 최소/최대 길이 설정
validate_default 필드의 기본값도 유효성 검증할지 여부
frozen 모델을 불변(immutable) 객체로 만듦 (__setattr__ 불가)
arbitrary_types_allowed Pydantic이 기본적으로 처리하지 않는 사용자 정의 타입 허용 여부
json_encoders 특정 타입에 대해 JSON 직렬화 방식을 커스터마이징
ignored_types 필드 정의에서 무시할 타입들을 지정 (예: logging.Logger)
coerce_numbers_to_str 숫자 값을 문자열로 강제 변환할지 설정 (유연성 vs. 안정성 트레이드오프)

✅ 자주 사용하는 설정 정리

1. from_attributes: ORM 객체 지원

model_config = {
    "from_attributes": True
}

→ MyModel.model_validate(orm_instance) 사용 가능


2. extra: 정의되지 않은 필드 허용 여부

model_config = {
    "extra": "ignore"  # 또는 "forbid", "allow"
}
  • "ignore": 무시
  • "forbid": 오류 발생
  • "allow": model.extra_fields로 접근 가능

3. frozen: 모델 불변화 (immutable)

model_config = {
    "frozen": True
}

→ 생성 후 값 변경 시 TypeError 발생


4. populate_by_name: alias가 있어도 변수명으로 값 할당 허용

class M(BaseModel):
    value: int = Field(..., alias="v")

    model_config = {
        "populate_by_name": True
    }

M(value=1)  # ✅ 가능
M(v=1)      # ✅ 가능

5. json_encoders: 커스텀 직렬화

import datetime

model_config = {
    "json_encoders": {
        datetime.datetime: lambda v: v.isoformat()
    }
}

✅ 전체 예시

from pydantic import BaseModel, Field
from typing import Optional

class UserPayload(BaseModel):
    id: int
    name: str = Field(..., alias="username")
    age: Optional[int]

    model_config = {
        "from_attributes": True,
        "populate_by_name": True,
        "extra": "forbid",
        "frozen": False,
    }

✅ 참고 링크

 

+ Pydantic 을 활용해 ORM 업데이트하기

Pydantic 모델로 변환된 객체에서 값을 꺼내어 SQLAlchemy ORM 객체에 다시 할당함으로써 업데이트가 가능

단, 명시적으로 값을 꺼내어 user.field = dto.field 형태로 넣어줘야 하며, Pydantic 객체에서 ORM 객체로 자동 반영되는 기능은 없음.


✅ 예시: AgentJobSchema → ORM 객체 업데이트

1. Pydantic 모델 (v2 기준)

from pydantic import BaseModel

class AgentJobSchema(BaseModel):
    seq: int
    id: str
    status: str
    job_type: str

    model_config = {
        "from_attributes": True
    }

2. ORM에서 불러오고 → Pydantic으로 로직 처리

agent_job = session.get(AgentJob, job_id)

# Pydantic 객체로 복사 (불변 객체처럼 다룸)
dto = AgentJobSchema.model_validate(agent_job)

# 로직 처리
updated = dto.copy(update={"status": "COMPLETE"})

3. Pydantic → ORM 업데이트 수동 반영

agent_job.status = updated.status
agent_job.job_type = updated.job_type  # 필요한 필드만
session.commit()

✅ 자동화하고 싶다면?

방법 1: 간단한 반영 유틸 만들기

def apply_dto_to_model(dto: BaseModel, model, fields: list[str]):
    for field in fields:
        setattr(model, field, getattr(dto, field))

사용 예:

apply_dto_to_model(updated, agent_job, fields=["status", "job_type"])

방법 2: 전체 필드 일괄 반영 (주의 필요)

for field, value in updated.model_dump().items():
    setattr(agent_job, field, value)
  • 이 방식은 모든 필드를 무차별적으로 덮어쓰므로, 부분 업데이트에는 적합하지 않음
  • 민감한 필드가 있을 경우 사용에 주의

❗ 주의할 점

주의사항 설명
ORM 객체는 Pydantic 객체가 아님 자동 반영 X
Pydantic 객체는 불변처럼 다루는 게 안전 직접 .copy(update=...) 후 반영
민감한 필드는 명시적으로 DTO → ORM 반영 시 반드시 컨트롤할 것

✅ 요약

작업 가능 여부 방법
Pydantic → ORM 수동 업데이트 ✅ 가능 setattr 또는 수동 할당
자동 반영 (DTO 전체 → ORM) ⚠️ 조심스럽게 가능 model_dump() + setattr()
ORM → Pydantic 변환 ✅ 아주 일반적 model_validate(orm)

 

반응형