Re: [sqlalchemy] How-to : update A also create an update of B
Le jeudi 30 août 2012 17:16:40 UTC+2, Michael Bayer a écrit : 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() As I'm not the only developer for this application, I can't use pure SQL commands. I've tried the after_flush solution. It works. What could be the problem to use setter ? For example Class A has attribut family_id @family_id.setter def family_id(self, family_id): self._family_id = family_id update_linked_entities_with_family(family_id) with update_linked_entities_with_family a function that grab and modify Bs. You point that it could be used only for changing Python attributs. I use it to change SQLAlchemy entities and fields. What could be the drawback of this solution ? -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/h11OiMXCyloJ. 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.
[sqlalchemy] How-to : update A also create an update of B
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 received this message because you are subscribed to the Google Groups sqlalchemy group. To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/d2bO9dVrSpUJ. 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.
Re: [sqlalchemy] How-to : update A also create an update of B
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.
Re: [sqlalchemy] How-to : update A also create an update of B
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. The computation will modify B, which is also a map of a table. 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. I've used something like this : A has field family_id, which trigger the modification of B (and not anly B, but also some more tables) @family_id.setter def family_id(self, family_id): self._family_id = family_id self.update_linked_entities_with_family(family_id) Then at session.commit(), A is updated, but also the other linked entities. This works. But it's not really nice, because any changes, even rollbacked one will call the update_linked_entitites method. 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() I can read this, but I don't understand how to do this and not exactly how it works. It is 3 solutions right , not 3 points I have to go through ? Step A : calling only Session.execute will output direct SQL commands, thus not modify the Session dirty list and the state. Seems quiet easy but less readable because of the direct SQL commands. Step B : what *outside* of the flush means ? Step C : I will try this one because it seems nice, using Session/transaction. Thank you for the explanation. I have a lot to do to fully understand SQLAlchemy. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/DuspcAQVczsJ. 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.
Re: [sqlalchemy] How-to : update A also create an update of B
On Aug 30, 2012, at 11:12 AM, Tony Moutaux wrote: 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() I can read this, but I don't understand how to do this and not exactly how it works. It is 3 solutions right , not 3 points I have to go through ? three different ways to do it. Step A : calling only Session.execute will output direct SQL commands, thus not modify the Session dirty list and the state. Seems quiet easy but less readable because of the direct SQL commands. right, but is the most efficient and simple, if the changes you're emitting are also simple. Step B : what *outside* of the flush means ? This option doesn't apply here, as you aren't dependent on SQL functions. outside the flush means, when you have your A and B and haven't called flush() yet. -- 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.