refactor(saves): simplify SaveSchema construction with model_validate

Add model_validator to SaveSchema that safely handles SQLAlchemy lazy
relationships by checking inspect(obj).unloaded before attribute access.
This allows direct use of model_validate(orm_obj) instead of manually
building a dict and excluding device_syncs.
This commit is contained in:
nendo
2026-02-03 21:05:03 +09:00
parent 8ae07d77f3
commit e3642523f9
2 changed files with 28 additions and 10 deletions

View File

@@ -1,4 +1,9 @@
from datetime import datetime
from typing import Any
from pydantic import model_validator
from sqlalchemy import inspect
from sqlalchemy.exc import InvalidRequestError
from .base import BaseModel
from .device import DeviceSyncSchema
@@ -37,6 +42,25 @@ class SaveSchema(BaseAsset):
screenshot: ScreenshotSchema | None
device_syncs: list[DeviceSyncSchema] = []
@model_validator(mode="before")
@classmethod
def handle_lazy_relationships(cls, data: Any) -> Any:
if isinstance(data, dict):
return data
try:
state = inspect(data)
except Exception:
return data
result = {}
for field_name in cls.model_fields:
if field_name in state.unloaded:
continue
try:
result[field_name] = getattr(data, field_name)
except InvalidRequestError:
continue
return result
class SlotSummarySchema(BaseModel):
slot: str | None

View File

@@ -35,7 +35,7 @@ def _build_save_schema(
device: Device | None = None,
sync: DeviceSaveSync | None = None,
) -> SaveSchema:
device_syncs: list[DeviceSyncSchema] = []
save_schema = SaveSchema.model_validate(save)
if device:
if sync:
@@ -47,7 +47,7 @@ def _build_save_schema(
last_synced = save.updated_at
is_untracked = False
device_syncs.append(
save_schema.device_syncs = [
DeviceSyncSchema(
device_id=device.id,
device_name=device.name,
@@ -55,15 +55,9 @@ def _build_save_schema(
is_untracked=is_untracked,
is_current=is_current,
)
)
]
save_data = {
key: getattr(save, key)
for key in SaveSchema.model_fields
if key != "device_syncs" and hasattr(save, key)
}
save_data["device_syncs"] = device_syncs
return SaveSchema.model_validate(save_data)
return save_schema
DATETIME_TAG_PATTERN = re.compile(r" \[\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\]")