Interview question
How do you use database transactions and atomic() in Django? Django में database transactions और atomic() कैसे use करें?
Answer
Django's atomic() ensures a block of database operations either all succeed together or all roll back together, preventing partial updates that leave data in an inconsistent state.
from django.db import transaction
# Using atomic() as a context manager
def transfer_funds(from_account_id, to_account_id, amount):
with transaction.atomic():
from_account = Account.objects.select_for_update().get(id=from_account_id)
to_account = Account.objects.select_for_update().get(id=to_account_id)
if from_account.balance < amount:
raise ValueError('Insufficient funds')
from_account.balance -= amount
from_account.save()
to_account.balance += amount
to_account.save()
# If ANY exception occurs inside this block, BOTH updates roll back
# Using atomic() as a decorator - the whole function is one transaction
@transaction.atomic
def create_order(user, items):
order = Order.objects.create(user=user)
for item in items:
OrderItem.objects.create(order=order, product=item['product'], qty=item['qty'])
Product.objects.filter(id=item['product'].id).update(
stock=models.F('stock') - item['qty'])
return order
# select_for_update() - locks selected rows until the transaction completes,
# preventing race conditions when multiple requests modify the same rows
with transaction.atomic():
account = Account.objects.select_for_update().get(id=1)
account.balance += 100
account.save()
# Nested atomic blocks use savepoints internally
with transaction.atomic():
order = Order.objects.create(user=user)
try:
with transaction.atomic(): # creates a savepoint
risky_operation()
except SomeException:
pass # only the inner block rolls back, outer transaction continues
# Manually rolling back within a transaction
with transaction.atomic():
do_something()
if some_condition:
transaction.set_rollback(True) # marks the transaction for rollbackDjango का atomic() यह सुनिश्चित करता है कि database operations का block या तो सब साथ succeed हों या सब साथ rollback हों, partial updates को inconsistent state में रहने से रोकता है।
from django.db import transaction
def transfer_funds(from_account_id, to_account_id, amount):
with transaction.atomic():
from_account = Account.objects.select_for_update().get(id=from_account_id)
to_account = Account.objects.select_for_update().get(id=to_account_id)
if from_account.balance < amount:
raise ValueError('Insufficient funds')
from_account.balance -= amount
from_account.save()
to_account.balance += amount
to_account.save()
# किसी भी exception पर दोनों updates rollback होते हैं
@transaction.atomic
def create_order(user, items):
order = Order.objects.create(user=user)
for item in items:
OrderItem.objects.create(order=order, product=item['product'], qty=item['qty'])
Product.objects.filter(id=item['product'].id).update(
stock=models.F('stock') - item['qty'])
return order
# select_for_update() - rows lock करता है transaction पूरी होने तक
with transaction.atomic():
account = Account.objects.select_for_update().get(id=1)
account.balance += 100
account.save()
# Nested atomic blocks savepoints use करते हैं
with transaction.atomic():
order = Order.objects.create(user=user)
try:
with transaction.atomic():
risky_operation()
except SomeException:
passWas this answer clear?