当相关子项更改时,SQLAlchemy 更新父项 [英] SQLAlchemy update parent when related child changes

查看:59
本文介绍了当相关子项更改时,SQLAlchemy 更新父项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将一个实体建模为一个或多个一对多关系,以便它的 last_modified 属性在

I'm trying to model an entity that as one or more one-to-many relationships, such that it's last_modified attribute is updated, when

  • 添加或删除了一个孩子
  • 一个孩子被修改了
  • 实体本身被修改

我整理了以下最小示例:

I've put together the following minimal example:

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()

这似乎有效,但我想知道是否有更好的方法来做到这一点?

This seems to work, but I'm wondering if there's a better way to do this?

具体来说,这变得非常冗长,因为我的实际 ConfigParam 实现具有更多属性,并且我在父 Config 类上配置了多个一对多关系.

Specifically, this becomes very verbose since my actual ConfigParam implementation has more attributes and I'm having multiple one-to-many relations configured on the parent Config class.

推荐答案

对此持怀疑态度,它似乎"有效,但可能会爆炸:

Take this with a huge grain of salt, it "seems" to work, could explode:

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"之类的列将绑定到事件侦听器.

Problem is that the inspections make no exceptions and columns such as 'ID' and 'ConfigID' will be bound to event listeners.

另一种可能稍微不那么乏味的形式是以类似的方式使用属性列表来绑定事件:

Another perhaps slightly less tedious form would be to just use a list of attributes to bind events to in a similar fashion:

for attr in ['key', 'value']:
    event.listen(getattr(ConfigParam, attr), 'set', listener)

这让您可以控制哪些与事件绑定,哪些不绑定.

This gives you control over what is bound to events and what is not.

这篇关于当相关子项更改时,SQLAlchemy 更新父项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆