LINUX.ORG.RU

Конвертор model_dto to model_alchemy

 ,


0

2

Всем привет! Подскажите паттерны решения следующей задачи. Имеется класс алхимический MyModelSql, при реализации бизнес алгоритма работу веду с соответствующей классом MyModelDto, потом для сохранения в БД конвертирую dto-объект в sql-объект, ну и наборот - при чтении из бд.

Что не нравится - поддерживание двух классов при изменениях и тупое перенабитие полей.

Имеется класс алхимии

Base = declarative_base()


class MyModelSql(Base):

    __tablename__ = 'my_model_table'

    id = Column(Integer, primary_key=True)
    create_date = Column(Date)
    user_id = Column(String)
    ...


class MyModelDto:


    create_date: datetime.date
    user_id: str
    # ...
    id: int = None

    @classmethod
    def to_sql(self) -> MyModelSql:
        return MyModelSql(
            # хоть здесь можно-то тупо не перечислять все поля?:
            id = self.id,
            create_date = self.create_date
            user_id = self.user_id,
            # ...
        )
 

Зря хочешь конвертер, не надо передачу данных с базой вязать. Иначе потом прибежишь с вопросом «конвертер но без поля Х», потом «конвертер со сменой типа», потом «конвертер чтоб batching», потом ещё с какой фигней.

upcFrost ★★★★★
()

Использовать датаклассы:

from dataclasses import dataclass, asdict
@dataclass
class MyModelDto:
     def to_sql(self):
         return MyModelSql(**asdict(self))

Но вообще код какой-то неверный. Например, не может у @classmethod быть self. М.б. сначала основы Python подучить надо?

emorozov
()
Ответ на: комментарий от upcFrost

У «теплого» и «мягкого» имеется общее. Класс DTO имеет поля, такие же, что и у SQLAlchemy класса для работы с БД:

class MyModelDto:


    create_date: datetime.date
    user_id: str
    # ...
    id: int = None
эти поля, id, create_date, user_id ... меняются параллельно, и судя по логике и существующему коду врядли разъедутся. Было бы неплохо, поля из MyModelSql выкинуть и MyModelDto подсунуть.

sc1ent13ter
() автор топика
Ответ на: комментарий от emorozov

Но вообще код какой-то неверный. Например, не может у @classmethod быть self. М.б. сначала основы Python подучить надо?

  1. извиняюсь, хотел from_sql зацитировать с cls и забыл удалить classmethod

  2. в бою Питон учить приятнее

sc1ent13ter
() автор топика
Ответ на: комментарий от vvn_black

Да, похоже вот эта штука мне нужна https://docs.sqlalchemy.org/en/14/orm/mapping_styles.html

Но, не понятно: как эксплуатировать этот класс в режимах: (1) когда реализуется бизнес-логика и нет подключения к бд и (2) когда появилась сессия и нужно просто поработать с бд, например, сделать инсерт.

sc1ent13ter
() автор топика

С одной стороны, я такое уже спрашивал.

С другой стороны, можно наметапрограммировать.

У меня модель в plantuml нарисована, я по ней генерирую соответствующий код.

Shadow ★★★★★
()
Последнее исправление: Shadow (всего исправлений: 1)
Ответ на: комментарий от sc1ent13ter

Вроде, список полей в одном месте и пашет: (1) и класс DTO (2) и под сессией БД работает ), посмотрим на чем споткнутся придется ..


@mapper_registry.mapped
@dataclass
class UserExperimental:
    __tablename__ = "user_experimental"

    __sa_dataclass_metadata_key__ = "sa"
    id: int = field(init=False, metadata={"sa": Column(Integer, primary_key=True)})
    name: str = field(default=None, metadata={"sa": Column(String(50))})
    fullname: str = field(default=None, metadata={"sa": Column(String(50))})


u1 = UserExperimental(name='humorist', fullname='Ivan Ivanov')  # (1)

with session_scope_manager() as session:
    session.add(u1)  # (2)

https://docs.sqlalchemy.org/en/14/orm/dataclasses.html

sc1ent13ter
() автор топика