我正在尝试将一个实体建模为一个或多个一对多关系,以便更新它的last_modified
属性
我把以下最小的例子放在一起:
class Config(Base):
__tablename__ = 'config'
ID = Column('ID', Integer, primary_key=True)
name = Column('name', String)
last_modified = Column('last_modified', DateTime, default=now, onupdate=now)
params = relationship('ConfigParam', backref='config')
class ConfigParam(Base):
__tablename__ = 'config_params'
ID = Column('ID', Integer, primary_key=True)
ConfigID = Column('ConfigID', Integer, ForeignKey('config.ID'), nullable=False)
key = Column('key', String)
value = Column('value', Float)
@event.listens_for(Config.params, 'append')
@event.listens_for(Config.params, 'remove')
def receive_append_or_remove(target, value, initiator):
target.last_modified = now()
@event.listens_for(ConfigParam.key, 'set')
@event.listens_for(ConfigParam.value, 'set')
def receive_attr_change(target, value, oldvalue, initiator):
if target.config:
# don't act if the parent config isn't yet set
# i.e. during __init__
target.config.last_modified = now()
这似乎有效,但我想知道是否有更好的方法来做到这一点?
具体来说,这变得非常冗长,因为我的实际ConfigParam
实现具有更多属性,并且我在父Config
类上配置了多个一对多关系。
答案 0 :(得分:5)
带上一大堆盐,它“似乎”起作用,可能爆炸:
def rel_listener(t, v, i):
t.last_modified = now()
def listener(t, v, o, i):
if t.config:
t.config.last_modified = now()
from sqlalchemy import inspect
for rel in inspect(Config).relationships:
event.listen(rel, 'append', rel_listener)
event.listen(rel, 'remove', rel_listener)
for col in inspect(ConfigParam).column_attrs:
event.listen(col, 'set', listener)
问题是检查没有例外,“ID”和“ConfigID”等列将绑定到事件监听器。
另一种可能稍微繁琐的形式是使用属性列表以类似的方式绑定事件:
for attr in ['key', 'value']:
event.listen(getattr(ConfigParam, attr), 'set', listener)
这使您可以控制与事件绑定的内容和不绑定的内容。