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]
См. Этот документ в разделе "Конструкторы и инициализация объекта".