I have a complex block of code that handle the creation/update of ORM object relationships.
Let's say the models are A and B and the association is a OneToOne A - B
(A.b_line
points to B).
1) Before creating/updating the associations some A objects needs to be updated and saved into db. During this operation some internal fields of A objects are computed and saved.
2) The updated A object are reloaded from db (because we need the derived computed filed) and the associations with the B objects can proceed.
Example:
def update_and_associate(a_items):
with transaction.atomic():
for item in a_items:
item.field_alpha = 1
# updates item.field_beta depending on
# item.field_alpha
item.update_beta()
item.save() # Save to db
with transaction.atomic:
for item in a_items:
item.refresh_from_db()
b = item.b_line
b.total = a.field_beta
b.save()
# later...
try:
update_and_associate(items)
except Exception as e:
handle_exception(e)
I'm enclosing the code in nested atomic transaction block so that if any exception happen the changes should be rolled back (MySql with InnoDB).
The problem is that in the second atomic block when I reload item with refresh_from_db
they are not in sync, meaning they have old values as if the first transaction block didn't run at all.
I though that any changes would be committed as soon as possible but we still had the possibility to roll back in case of exception.
So my question is: by enclosing code in transaction.atomic
means that all the write modifications to be performed to the db are postponed until we exit the block? That would explain why refreshed items from db have old values.