Book.objects.select_related('publisher') — JOIN для FK
Book.objects.prefetch_related('genres') — 2 запроса для M2M
@transaction.atomic — атомарный декоратор
with transaction.atomic(): — атомарный блок
transaction.on_commit(callback) — после коммита
Шаблон: Soft Deletion
managers.py
from django.db import models
class SoftDeleteManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_deleted=False)
models.py — полная интеграция
from django.db import models
from django.utils import timezone
from .managers import SoftDeleteManager
class MyModel(models.Model):
# ... остальные поля ...
is_deleted = models.BooleanField(default=False)
deleted_at = models.DateTimeField(null=True, blank=True)
objects = SoftDeleteManager() # только не удалённые
all_objects = models.Manager() # все записи (для администрирования)
def delete(self, *args, **kwargs):
self.is_deleted = True
self.deleted_at = timezone.now()
self.save()
def restore(self):
"""Восстановить мягко удалённую запись."""
self.is_deleted = False
self.deleted_at = None
self.save()
class Meta:
abstract = True # если используется как миксин
Шаблон: QuerySet-оптимизация
select_related — для ForeignKey и OneToOneField
# Один связанный объект (FK)
qs = Book.objects.select_related('publisher')
# Цепочка связей
qs = Book.objects.select_related('publisher__country')
prefetch_related — для ManyToMany и обратных FK
# ManyToMany
qs = Book.objects.prefetch_related('genres')
# Обратный FK (все книги издателя)
qs = Publisher.objects.prefetch_related('book_set')
# Комбинация
qs = Book.objects.select_related('publisher').prefetch_related('genres')
Шаблон: Транзакции
Декоратор @transaction.atomic
from django.db import transaction
@transaction.atomic
@api_view(['POST'])
def my_view(request):
# Вся функция — одна транзакция
obj1 = Model1.objects.create(...)
obj2 = Model2.objects.create(...)
return Response(...)
Контекстный менеджер with transaction.atomic()
@api_view(['POST'])
def my_view(request):
with transaction.atomic():
obj1 = Model1.objects.create(...)
obj2 = Model2.objects.create(...)
# Код вне блока выполняется после коммита
return Response(...)
transaction.on_commit()
with transaction.atomic():
book = Book.objects.create(...)
# Отправить уведомление только после успешного коммита
transaction.on_commit(lambda: send_notification(book.id))
transaction.set_rollback()
with transaction.atomic():
book = Book.objects.create(...)
if some_condition_fails:
transaction.set_rollback(True) # пометить для отката
Ручное управление (редко)
transaction.set_autocommit(False)
try:
# операции
transaction.commit()
except Exception:
transaction.rollback()
finally:
transaction.set_autocommit(True)
Таблица: транзакционный API Django
Функция / декоратор
Назначение
transaction.atomic
Декоратор или контекстный менеджер: атомарный блок
transaction.on_commit(fn)
Вызвать fn после успешного COMMIT
transaction.set_rollback(True)
Пометить транзакцию для отката в конце блока
transaction.set_autocommit(False)
Отключить автокоммит (ручной режим)
transaction.commit()
Явный COMMIT (только в ручном режиме)
transaction.rollback()
Явный ROLLBACK (только в ручном режиме)
Миграции для новых полей
# После добавления is_deleted / deleted_at в модель
python manage.py makemigrations
python manage.py migrate