Функция atomic
Функция atomic из модуля django.db используется для создания атомарных блоков операций с базой данных. Она применяется как декоратор к функциям или как контекстный менеджер в блоке with. Все операции внутри такого блока выполняются в рамках одной транзакции - если возникает исключение, все изменения откатываются, а если блок завершается успешно, все изменения фиксируются. Функция принимает необязательный параметр using, который указывает, к какой базе данных применять транзакцию, и параметр savepoint, который управляет созданием точек сохранения при вложенных вызовах atomic.
Синтаксис
from django.db import atomic
# Как контекстный менеджер
with atomic(using='default', savepoint=True):
# операции с базой данных
# Как декоратор
@atomic(using='default', savepoint=True)
def view_function(request):
# операции с базой данных
Пример
Давайте создадим атомарный блок для перевода денег между счетами, где оба изменения должны быть выполнены вместе:
from django.db import atomic, transaction
from myapp.models import Account
def transfer_money(from_id, to_id, amount):
try:
with atomic():
from_account = Account.objects.select_for_update().get(id=from_id)
to_account = Account.objects.select_for_update().get(id=to_id)
if from_account.balance < amount:
raise ValueError("Insufficient funds")
from_account.balance -= amount
to_account.balance += amount
from_account.save()
to_account.save()
print("Transfer completed successfully")
return True
except Exception as e:
print(f"Transfer failed: {e}")
return False
Результат выполнения кода при успешном переводе:
"Transfer completed successfully"
Пример
Используем atomic как декоратор для представления, которое создает заказ и обновляет количество товара:
from django.db import atomic
from myapp.models import Order, Product
@atomic
def create_order(product_id, quantity, user):
product = Product.objects.select_for_update().get(id=product_id)
if product.stock < quantity:
raise ValueError("Not enough stock")
order = Order.objects.create(
user=user,
product=product,
quantity=quantity,
total=product.price * quantity
)
product.stock -= quantity
product.save()
return order
Результат выполнения кода при успешном создании заказа:
"Order created: 1024"
Пример
Рассмотрим вложенные транзакции с использованием параметра savepoint для создания точек сохранения:
from django.db import atomic
from myapp.models import Article
def create_article_with_tags(title, content, tags):
try:
with atomic():
article = Article.objects.create(
title=title,
content=content,
status='draft'
)
# Внутренний блок с точкой сохранения
with atomic(savepoint=True):
for tag in tags:
article.tags.add(tag)
# Если здесь произойдет ошибка, статья сохранится,
# а теги не добавятся
print(f"Article {article.id} created with {len(tags)} tags")
return article
except Exception as e:
print(f"Failed to create article: {e}")
return None
Результат выполнения кода при успешном создании:
"Article 5 created with 3 tags"
Смотрите также
-
функция
on_commit,
которая выполняет действия после успешной фиксации транзакции -
метод
select_for_update,
который блокирует строки для предотвращения конкурентных изменений -
метод
get_or_create,
который получает или создает объект в рамках транзакции -
метод
update_or_create,
который обновляет или создает объект в рамках транзакции