DBMS’ ACID (Atomicity, Consistency, Isolation, Durability) and transaction in Django.
update Within One Step
If we need to update only one field of a model (That is, no other field or model need to be updated simultaneously to ensure the consistency of ACID), we can use F(), select_for_update() and filter() to update field without race condition..
Following example:
- Check if the product adequate for
nquantity before selling.- If adequate, sell
nproducts. - If inadequate, sell nothing.
- If adequate, sell
1 | from django.db.models import F |
select_for_update()returns a queryset that will lock rows until the end of the transaction (generatingSELECT ... FOR UPDATE)FIELDNAME__gte = numbermeans greater than or equal tonumber.filter()always return an objects set.
When no object satisfied the query’s condition (quantity >= n), returns an empty set.
An empty set won’t trigger theupdate()manipulation.get()always return one object. Raise error when get more than one.filter()always return an objects set.(obj, obj, obj, ...)
F()object represents the value of a model field. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.
Transaction With Multiple Steps
But we still need transaction with multiple steps. So use django.db.transaction.atomic() to ensure ACID’s atomic.
A transaction usually need to update multiple fields across models, so we implement the mechanism in
views.pyinstead ofmodels.py.
Now the following example implement the mechanism of add_to_cart():
- User requests for
namount products via a form.- If quantity > requested amount
n:- sell
nproducts; - add
nitems into myCartmodel.
- sell
- If (quantity < requested amount
n) && (quantity > 0):- sell out all stock of the quantity;
- add sold items into my
Cartmodel.
- Else:
- Sell nothing.
- If quantity > requested amount
1 | from django.db import transaction |