J'essaie de détecter lorsqu'une relation plusieurs-à-plusieurs est créée ou supprimée, mais j'ai de la difficulté à trouver le bon événement à écouter. Disons que j'ai un modèle User
et un modèle Team
, et j'utilise une table d'appartenance pour définir quels utilisateurs appartiennent à quelles équipes. Voici un schéma simple (en utilisant le modèle de base de Flask-SQLAlchemy):Placer un écouteur d'événement SQLAlchemy sur une table plusieurs-à-plusieurs
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))
Ce que je veux faire est de détecter quand quelqu'un rejoint ou quitte l'équipe, et de déclencher un événement qui peut faire quelque chose avec ces informations (par exemple envoyer un notification quelque part: "Dave a rejoint les Yankees", "Sarah a quitté les Mets").
J'ai essayé d'abord fixer des événements after_insert
et after_delete
directement à la table des membres, mais tout simplement échoué à l'exception AttributeError: after_delete
, qui était plus ou moins ce que j'attendais étant donné que ce n'est pas un modèle comme les autres.
J'ai essayé attacher un auditeur set
-User.teams
:
@event.listens_for(User.teams, 'set')
def membership_updated(target, value, oldvalue, initiator):
# compare `oldvalue` to `newvalue` to determine membership change
Cependant cet événement est tout simplement jamais déclenché quand j'ajouter ou supprimer des utilisateurs d'une équipe
J'ai essayé simplement écouter les mises à jour de Team
:
@event.listens_for(Team, 'after_update')
def test(mapper, connection, target):
# check current membership via `target.users`
Ceci est correctement déclenché lorsque l'adhésion change, mais le problème est que je ne peux pas vraiment Ce qui se passe Peut-être que quelqu'un a simplement édité le nom de l'équipe, et l'adhésion n'a pas changé du tout. Et si ça a changé, comment? Quelqu'un a-t-il été ajouté ou supprimé?
Je suis un peu coincé sur où aller, ou comment obtenir les informations nécessaires.
Brillant! Je ne savais même pas à propos de ces événements, exactement ce dont j'avais besoin. Je devrais noter que j'ai obtenu l'exception 'AttributeError: l'objet type 'Team' n'a pas d'attribut 'users'' quand j'ai écouté sur' Team.users', donc j'ai dû faire l'inverse et écouter sur 'User.teams' (ceci est logique je suppose, puisque j'ai défini les deux côtés de la relation à l'intérieur du modèle de l'utilisateur). J'ai testé cela dans mon code et ça fonctionne parfaitement. Merci encore de m'avoir appris quelque chose de nouveau. – daveruinseverything
Les mappeurs sont complètement initialisés la première fois que vous les utilisez, donc si vous essayiez d'utiliser 'Team.users' avant, il ne pourrait pas encore exister car [' Team' est résolu paresseusement] (http: //docs.sqlalchemy .org/fr/latest/orm/relation_api.html # sqlalchemy.orm.relationship.params.argument) car il est transmis en tant que chaîne évaluable Python à la relation. J'espère que cela a du sens. –