将SQLAlchemy事件侦听器放在多对多表

时间:2017-09-04 23:09:02

标签: python sqlalchemy flask-sqlalchemy

我正在尝试检测创建或删除多对多关系的时间,但我无法找出正确的事件来监听。

假设我有User模型和Team模型,我正在使用成员资格表来定义哪些用户属于哪些团队。这是一个简单的模式(使用Flask-SQLAlchemy的基本模型):

membership_table = db.Table('membership', db.metadata,
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('team_id', db.Integer, db.ForeignKey('team.id')),
    db.PrimaryKeyConstraint('user_id', 'team_id'))

class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    teams = db.relationship('Team', secondary=membership_table, backref='users')

class Team(db.Model):
    __tablename__ = 'team'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))

我想要做的是检测有人加入或离开团队,并触发可以对此信息做某事的事件(例如在某处发送通知:“Dave加入洋基队”;“Sarah离开大都会队”)

我首先尝试将after_insertafter_delete事件直接附加到成员资格表中,但这只是因为AttributeError: after_delete异常而失败,这或多或少是我预期的,因为它不是像其他人一样的模特。

我尝试将set听众附加到User.teams

@event.listens_for(User.teams, 'set')
def membership_updated(target, value, oldvalue, initiator):
    # compare `oldvalue` to `newvalue` to determine membership change

但是,当我从团队中添加或删除用户时,此事件永远不会被触发

我尝试过只听取Team的更新:

@event.listens_for(Team, 'after_update')
def test(mapper, connection, target):
    # check current membership via `target.users`

当成员资格发生变化时,这是正确触发的,但问题是我无法真正解释发生了什么。也许有人只是编辑了团队名称,而且会员资格根本没有变化。如果它改变了,怎么样?有人添加或删除了吗?

我有点卡在下一步去哪里,或者如何获得必要的信息。

1 个答案:

答案 0 :(得分:3)

为了检测有人加入或离开团队的时间"在Team.users关系中收听appendremove个事件:

@event.listens_for(Team.users, 'append')
def receive_team_users_append(target, value, initiator):
    print(value.name, 'added to team', target.name)

@event.listens_for(Team.users, 'remove')
def receive_team_users_append(target, value, initiator):
    print(value.name, 'removed from team', target.name)

如果您将团队附加到用户的团队集合,事件处理程序也会触发,这要归功于两个关系属性之间的how backref / back_populates mirror operations