Reputation: 895
Lets say I have a model A which has an account_number field and when a new instance of A is created a counter field in my model B increments it's value by one. This value will be the same that my account_number field will receive.
I want to protect the operation from concurrent modifications so that my account_number is always the correct one.
I want to do something like the following:
instance.account_number = F('modelB_table.counter') + 1
also updating the counter value in B
How can I achieve this in Django 1.9?
Could transactions be helpful in this case?
Upvotes: 2
Views: 694
Reputation: 49092
Yes, you can achieve this in Django using transactions. You'd do something like:
with transaction.atomic():
ModelB.objects.update(counter=F('counter') + 1)
new_counter = ModelB.objects.get().counter
a_instance.account_number = new_counter
a_instance.save()
This needs to be done at a transaction isolation level of READ_COMMITTED
or above. (In PostgreSQL the default isolation level is READ_COMMITTED
, I'm not sure about other databases.)
It works because that isolation level makes dirty reads impossible, so there's no way for a concurrent transaction to update the counter until the other commits.
Upvotes: 3