I've attempted the following: from sqlalchemy import Column, Integer, String, ForeignKey, create_engine from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy.event import listen from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.associationproxy import association_proxy
Base = declarative_base() class Machine(Base): __tablename__ = 'machines' __table_args__ = {'sqlite_autoincrement': True} machine_id = Column(Integer, primary_key=True) widgets = relationship('Widget') class Widget(Base): __tablename__ = 'widgets' __table_args__ = {'sqlite_autoincrement': True} widget_id = Column(Integer, primary_key=True) machine_id = Column(Integer, ForeignKey('machines.machine_id'), nullable=False) _gadgets = relationship('Gadget') gadgets = association_proxy('_gadgets', 'json_repr', creator=lambda kwargs: Gadget(**kwargs)) class Gadget(Base): __tablename__ = 'gadgets' __table_args__ = {'sqlite_autoincrement': True} gadget_id = Column(Integer, primary_key=True) widget_id = Column(Integer, ForeignKey('widgets.widget_id'), nullable=False) machine_id = Column(Integer, nullable=False) a = Column(String) b = Column(String) c = Column(Integer) @property def json_repr(self): return dict(a=self.a, b=self.b, c=self.c) @staticmethod def update_machine_ids(session, flush_context): widgets = [w for w in session.new if isinstance(w, Widget)] widgets.extend(w for w in session.dirty if isinstance(w, Widget)) print widgets for widget in widgets: session.query(Gadget).with_parent(widget).update( {"machine_id": widget.machine_id}) if __name__ == '__main__': engine = create_engine('sqlite:///:memory:', echo=False) Base.metadata.bind = engine Base.metadata.create_all() Session = sessionmaker(bind=engine) listen(Session, 'after_flush', Gadget.update_machine_ids) session = Session() m = Machine() w = Widget() session.add(m) m.widgets.append(w) w.gadgets.append(dict(a='1', b='2')) session.commit() I still get an integrity error because the after_flush happens after I've already tried to insert the null gadgets. If I move the flush after the widget is added to the session, but before the gadgets are, then the query(Gadget).with_parent(widget) obviously won't find anything. Maybe I should listen for Widget load events? On Wed, Jul 3, 2013 at 5:07 PM, Michael Bayer <mike...@zzzcomputing.com>wrote: > > On Jul 3, 2013, at 5:06 PM, Michael Bayer <mike...@zzzcomputing.com> > wrote: > > > Do the UPDATE through Session.execute() so it's within the same > transaction. > > .. or even just > query(Gadget).with_parent(some_widget).update({"machine_id": > some_widget.machine_id}), then you can have those Gadget objects refreshed > in memory using synchronize_session, if that's important. > > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at http://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/groups/opt_out. > > > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/groups/opt_out.