Django Avoiding race conditions


Example

See this Q&A question if you don't know what race conditions are.

The following code may be subject to race conditions :

article = Article.objects.get(pk=69)
article.views_count += 1
article.save()

If views_count is equal to 1337, this will result in such query:

UPDATE app_article SET views_count = 1338 WHERE id=69

If two clients access this article at the same time, what may happen is that the second HTTP request executes Article.objects.get(pk=69) before the first executes article.save(). Thus, both requests will have views_count = 1337, increment it, and save views_count = 1338 to the database, while it should actually be 1339.

To fix this, use an F() expression:

article = Article.objects.get(pk=69)
article.views_count = F('views_count') + 1
article.save()

This, on the other hand, will result in such query:

UPDATE app_article SET views_count = views_count + 1 WHERE id=69