6

I have a setup which look something like this

class Topic(db.Model):
    __tablename__ = 'topic'

    id = db.Column(db.Integer, primary_key=True)
    parent = db.relationship(
        'Topic',
        secondary='parent_child_relation',
        primaryjoin='Topic.id == ParentChildRelation.child_topic_id',
        secondaryjoin='ParentChildRelation.parent_topic_id == Topic.id',
        backref='children',
        uselist=False
    )

class ParentChildRelation(db.Model):
    __tablename__ = 'parent_child_relation'

    id = db.Column(db.Integer, primary_key=True)
    child_topic_id = db.Column(db.Integer, db.ForeignKey('topic.id'), nullable=False)
    parent_topic_id = db.Column(db.Integer, db.ForeignKey('topic.id'), nullable=False)

and have set up events to watch for ParentChildRelation changes

@event.listens_for(ParentChildRelation, 'after_insert')
def parent_child_relation_inserted(mapper, connection, target):
    # DO STUFF HERE

The problem I'm running into is it seems that SqlAlchemy does not fire off those events when I do something like (I'm using Flask SqlAlchemy):

topic = Topic(id=new_id)
new_parent = Topic.query.get(anotherId)
topic.parent = new_parent
db.session.add(topic)
db.session.commit()

I would assume that the event handlers should be getting called, but the after_insert handler isn't getting called.

Is this a limitation of SqlAlchemy, or am I missing something?

Andrew
  • 1,890
  • 3
  • 16
  • 35
  • 1
    is the record is going in to the parent_child_relation table? would expect you need to do a `db.session.add(topic)` somwhere? Also do you need a many-to-many relationship here? a lot simpler if you don't to just have a `parent_id` column. – Lee Sep 04 '15 at 18:02
  • Whoops, yeah I do have the `db.session.add(topic)` in my actual code (will update my question to reflect that), and the ParentChildRelation is in fact making it into the db, but the after_insert handler is still not firing. – Andrew Sep 04 '15 at 18:31
  • you might want to try listening to an attribute event instead? http://docs.sqlalchemy.org/en/latest/orm/events.html#attribute-events – Lee Sep 04 '15 at 21:49
  • I do need to keep the many-to-many relationship, as I am going to be allowing multiple inheritance in the future. – Andrew Sep 07 '15 at 18:48
  • @Andrew if you do an explicit creation / add / flush of a `ParentChildRelation` does your event get triggered? – Lee Sep 08 '15 at 18:37
  • Yep, and if I instead add the handler `@event.listens_for(Topic.parent, 'set')` that fires when i set `topic.parent = new_parent`, but unfortunately it seems to fire before the flush, which doesn't work for my purposes. – Andrew Sep 08 '15 at 19:31
  • 2
    Can you do `@event.listens_for(Topic.children, 'append')`? Sorry, can't speak to weather this is expected behavior or not. – Lee Sep 08 '15 at 21:07
  • Unfortunately, `append` (as well as any of the other collection events) doesn't fire when using `uselist=False`, as it seems to be treated as a scalar instead of a collection. – Andrew Sep 10 '15 at 16:45

0 Answers0