python / expert
Snippet
Django Atomic Transaction Blocks with Savepoint Management
Atomic transactions ensure data integrity when multiple database operations must succeed or fail together. Savepoints create nested transaction points within a larger atomic block, allowing partial rollback without aborting the entire transaction. This pattern is critical for financial operations where a failure in a non-critical step (like sending a notification) should not roll back the actual balance transfer.
snippet.py
1
2
from django.db import transaction\nfrom decimal import Decimal\n\nclass OrderProcessor:\n def process_transfer(self, from_account, to_account, amount):\n with transaction.atomic():\n savepoint = transaction.savepoint()\n try:\n self._deduct_balance(from_account, amount)\n self._apply_transaction_fee(from_account)\n self._credit_balance(to_account, amount)\n self._send_notifications(from_account, to_account)\n except Exception as e:\n transaction.savepoint_rollback(savepoint)\n self._log_failure(from_account, to_account, str(e))\n raise\n else:\n transaction.savepoint_commit(savepoint)\n\n def _deduct_balance(self, account, amount):\n updated = Account.objects.filter(\n id=account.id,balance__gte=amount\n ).update(balance=F('balance') - amount)\n if not updated:\n raise InsufficientFundsError(account, amount)\n\n def _credit_balance(self, account, amount):\n Account.objects.filter(id=account.id).update(\n balance=F('balance') + amount\n )
django
Breakdown
1
with transaction.atomic():
Creates outermost atomic block ensuring all operations within succeed or fail together as a single database transaction
2
savepoint = transaction.savepoint()
Establishes intermediate rollback point allowing partial rollback of nested operations while keeping outer transaction active
3
transaction.savepoint_rollback(savepoint)
Reverts database state to savepoint on exception, discarding only the failed operation rather than entire atomic block
4
filter(balance__gte=amount).update()
Atomic deduction with optimistic locking check ensures race conditions cannot cause negative balances