I've got a situation where I have to update votes for any candidate.
People can election with this candidate, using more than one election per candidate. i.e. one individual can election 5 votes, while someone else votes 2. Within this situation this candidate should get 7 votes.
Now, I personally use Django. And here the way the pseudo code appears like
votes = candidate.votes vote += citizen.vote
The issue here, as you can tell is really a race condition in which the candidateâ€™s votes could possibly get overwritten by another citizenâ€™s election who did a choose earlier and hang now.
Just how can avoid this by having an ORM like Django?
If this sounds like purely an arithmetic expression then Django includes a nice API known as F expressions
Upgrading characteristics according to existing fields
Sometimes you will need to execute a simple arithmetic task on the area, for example incrementing or decrementing the present value. The apparent way to do this is to behave like:
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese') >>> product.number_sold += 1 >>> product.save()
When the old number_offered value retrieved in the database was 10, then the need for 11 is going to be written to the database.
This is often enhanced slightly by indicating the update in accordance with the initial area value, instead of being an explicit assignment of the new value. Django provides F() expressions as a means of carrying out this type of relative update. Using F() expressions, the prior example could be expressed as:
>>> from django.db.models import F >>> product = Product.objects.get(name='Venezuelan Beaver Cheese') >>> product.number_sold = F('number_sold') + 1 >>> product.save()
This method does not make use of the initial value in the database. Rather, it can make the database perform the update according to whatever value is current at that time the save() is performed.
When the object continues to be saved, you have to reload the item to be able to access the particular value which was put on the up-to-date area:
>>> product = Products.objects.get(pk=product.pk) >>> print product.number_sold 42
Possibly the select_for_update QuerySet technique is useful for you personally.
An excerpt in the paperwork:
All matched up records is going to be locked before the finish from the transaction block, and therefore other transactions is going to be avoided from altering or obtaining locks in it.
Usually, if another transaction has acquired a lock on among the selected rows, the query will block before the lock is launched. If this isn't the behaviour you would like, call choose_for_update(nowait=True). This makes the phone call non-obstructing. If your conflicting lock has already been acquired by another transaction, DatabaseError is going to be elevated once the queryset is examined.
Mind this is just obtainable in the Django development release (i.e. > 1.3).