2013-07-03 8 views
0

Я работаю над проектом Python с использованием SQLAlchemy. У меня следующий класс (я опустил некоторые методы не имеют отношения к вопросу):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 список (также опущены, это простой список, содержащий имена команд).

Я создаю объект 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] 

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

+0

Я знал, что здесь должно быть что-то более простое, чем прослушиватели событий карты :) – Wookie88

Смежные вопросы