A more lightweight option exists for some use cases, that doesn’t require even using a lock. It does depend on your database, and what isolation level it is running at.
The technique is simply to do an UPDATE that uses database values, rather than things that have been retrieved from the database.
So, the SQL needs to look like:
UPDATE accounts SET balance = balance + 100 WHERE balance.id == 123
To do this in Django, you need to do:
Account.objects.filter(id=123).update(balance=F(‘balance’) + 100)
See https://docs.djangoproject.com/en/1.11/ref/models/expressions/ for more on F expresions, and the postgres docs on isolation level which provide some helpful examples — https://www.postgresql.org/docs/9.1/static/transaction-iso.html