On Aug 30, 2012, at 10:32 AM, Tony Moutaux wrote:

> Hi there !
> 
> I'm going mad looking for a solution for what seems a simple problem.
> 
> When object A is updated, I also want object B to be updated, using some 
> computation based on A new values.
> From now, I can detect when A is modified using after_update.
> 
> What I try is to look at event Session.after_flush, if in Session.dirty there 
> is an instance of A, I call the update of B. Within after_flush I can see 
> Session.dirty with the modified B. But no SQL UPDATE is issued at all.
> 
> Any tip for me ?


You do this kind of thing most simply within the objects themselves, not as 
much in Session events, depending on how things are organized.   Such as in the 
__init__() method of A, or by using an event listener on an attribute of A.

Only if "some computation based on A new values" means that there are SQL-level 
functions which you need to get at, does the rationale for 
"after_update"/"after_flush" events to come up.    Unfortunately you can't emit 
a flush() within any of these events, as they are already local to the flush() 
call itself.    Nor can you change the state of the Session within any of the 
"after_" events, as the Session is already doing its work.  You can add new 
state to the Session within the "after_flush_postexec()" method, however you'd 
need to call flush() again for those changes to be flushed.

So the options:

1. if "some computation" is only "in-Python" computation, and *not* SQL 
functions, then set the state of B within object-level events, such as the 
__init__() of A, a @property on A, @validates events on A, or attribute events 
on A.

2.if "some computation" involves SQL functions:

    a. emit your modifications to B using only SQL statements and 
Session.execute(), not by adding any new state to the Session or re-flushing.

    b. pre-execute your SQL functions for A *outside* of the flush, then apply 
values to B as needed.

    c. use a second Session inside the event:

        def after_flush(session, flush_context):
            my_bs = figure_out_bs(session)
            new_session = Session(bind=session.connection())
            new_session.add_all(my_bs)

            # this won't actually COMMIT the transaction as we are 
            # already inside one
            new_session.commit()
            

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to