Files
core/orm/base.py
Untone 809bda2b56
Some checks failed
Deploy on push / deploy (push) Failing after 5s
search-fix, devstart-fix, cache-fix, logs-less
2025-07-31 19:13:23 +03:00

74 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import builtins
import logging
from typing import Any, Type
import orjson
from sqlalchemy import JSON
from sqlalchemy.orm import DeclarativeBase
logger = logging.getLogger(__name__)
# Глобальный реестр моделей
REGISTRY: dict[str, Type[Any]] = {}
# Список полей для фильтрации при сериализации
FILTERED_FIELDS: list[str] = []
class BaseModel(DeclarativeBase):
"""
Базовая модель с методами сериализации и обновления
"""
def __init_subclass__(cls, **kwargs: Any) -> None:
REGISTRY[cls.__name__] = cls
super().__init_subclass__(**kwargs)
def dict(self, access: bool = False) -> builtins.dict[str, Any]:
"""
Конвертирует ORM объект в словарь.
Пропускает атрибуты, которые отсутствуют в объекте, но присутствуют в колонках таблицы.
Преобразует JSON поля в словари.
Returns:
Dict[str, Any]: Словарь с атрибутами объекта
"""
column_names = filter(lambda x: x not in FILTERED_FIELDS, self.__table__.columns.keys())
data: builtins.dict[str, Any] = {}
# logger.debug(f"Converting object to dictionary {'with access' if access else 'without access'}")
try:
for column_name in column_names:
try:
# Проверяем, существует ли атрибут в объекте
if hasattr(self, column_name):
value = getattr(self, column_name)
# Проверяем, является ли значение JSON и декодируем его при необходимости
if isinstance(value, (str, bytes)) and isinstance(
self.__table__.columns[column_name].type, JSON
):
try:
data[column_name] = orjson.loads(value)
except (TypeError, orjson.JSONDecodeError) as e:
logger.warning(f"Error decoding JSON for column '{column_name}': {e}")
data[column_name] = value
else:
data[column_name] = value
else:
# Пропускаем атрибут, если его нет в объекте (может быть добавлен после миграции)
logger.debug(f"Skipping missing attribute '{column_name}' for {self.__class__.__name__}")
except AttributeError as e:
logger.warning(f"Attribute error for column '{column_name}': {e}")
except Exception as e:
logger.warning(f"Error occurred while converting object to dictionary {e}")
return data
def update(self, values: builtins.dict[str, Any]) -> None:
for key, value in values.items():
if hasattr(self, key):
setattr(self, key, value)
# Alias for backward compatibility
Base = BaseModel