SQLAlchemy: инициализация атрибута на основе другого атрибута

Я работаю над проектом Python с использованием SQLAlchemy. У меня есть следующий класс (я опустил некоторые методы, не относящиеся к вопросу):

class Cmd(Base):
    __tablename__ = "commands"
    dbid = Column(Integer, Sequence("commands_seq"), primary_key = True)
    cmd_id = Column(SmallInteger)
    instance_dbid =  Column(Integer, ForeignKey("instances.dbid"))
    type = Column(String(20))

    __mapper_args__ = {
    "polymorphic_on" : type,
    "polymorphic_identity" : "Cmd"
    }

    def __init__(self, cmd_id):
        self.cmd_id = cmd_id
        self.cmd_name = event_names[self.cmd_id]

Как видите, при инициализации экземпляра класса атрибут cmd_name создан из cmd_id атрибут с использованием event_names list (также опущен, это простой список, содержащий имена команд).

Я создаю объект Cmdдобавь сеанс, зафиксируй сеанс. После закрытия приложения и его повторного запуска я пытаюсь загрузить это Cmd используя запрос SQLAlchemy. Объект загружен, но конечно __init__ не называется и cmd_name не установлен.

Я хотел бы знать, если есть какой-то простой способ выполнения некоторого кода (self.cmd_name = event_names[self.cmd_id]) после получения Cmd объект с запросом. Конечно, я мог бы сделать специальный метод и всегда запускать его после запроса, но я ищу более элегантный, автоматический способ.

Я прочитал документацию и нашел некоторую информацию о слушателях событий ORM, но они кажутся слишком большими для такого простого случая. Я также нашел часть о событиях атрибутов, но они работают с column_property а также relationship только. Есть ли какой-нибудь короткий, элегантный способ добиться того, чего я хочу?

1 ответ

Решение

Вы можете использовать декоратор @reconstructor:

from sqlalchemy.orm import reconstructor
class Cmd(Base):
    __tablename__ = "commands"
    dbid = Column(Integer, Sequence("commands_seq"), primary_key = True)
    cmd_id = Column(SmallInteger)
    instance_dbid =  Column(Integer, ForeignKey("instances.dbid"))
    type = Column(String(20))

    __mapper_args__ = {
    "polymorphic_on" : type,
    "polymorphic_identity" : "Cmd"
    }

    def __init__(self, cmd_id):
        self.cmd_id = cmd_id
        self.cmd_name = event_names[self.cmd_id]

    @reconstructor
    def init_db_load(self):
        self.cmd_name = event_names[self.cmd_id]

См. Этот документ в разделе "Конструкторы и инициализация объекта".

Другие вопросы по тегам