РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
168 of 818 menu

Сигнал pre_delete

Сигнал pre_delete относится к механизму сигналов Django и используется для выполнения пользовательского кода до того, как объект модели будет удален из базы данных. Сигнал отправляется при вызове метода delete экземпляра модели или при удалении через QuerySet. Основная особенность этого сигнала - возможность выполнить подготовительные действия или вовсе предотвратить удаление объекта (в сочетании с исключениями), а также обработать связанные объекты до того, как каскадное удаление вступит в силу.

Параметрами сигнала являются: sender - класс модели, отправляющий сигнал; instance - удаляемый экземпляр модели; using - псевдоним базы данных, используемый для операции; origin - источник удаления (например, сам экземпляр или QuerySet); transaction - состояние транзакции, в которой выполняется удаление. Эти параметры позволяют гибко управлять процессом удаления и контекстом его выполнения.

Синтаксис

from django.db.models.signals import pre_delete from django.dispatch import receiver @receiver(pre_delete, sender=MyModel) def my_handler(sender, instance, **kwargs): # выполнить действия перед удалением instance pass

Пример

Рассмотрим простой пример логирования удаления статьи. Создадим модель Article с полями title и created_at, и модель Log для хранения истории удалений. Затем подключим обработчик сигнала:

from django.db import models from django.utils import timezone class Article(models.Model): title = models.CharField(max_length=200) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title class Log(models.Model): message = models.CharField(max_length=255) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.message

Теперь создадим обработчик сигнала, который будет записывать информацию об удалении:

from django.db.models.signals import pre_delete from django.dispatch import receiver from myapp.models import Article, Log @receiver(pre_delete, sender=Article) def log_article_deletion(sender, instance, **kwargs): message = f"Article '{instance.title}' deleted at {timezone.now()}" Log.objects.create(message=message)

При удалении объекта Article создается запись в логе:

from myapp.models import Article article = Article.objects.get(id=1) article.delete() # В Log появится запись: "Article 'Some title' deleted at ..."

Пример

Часто возникает необходимость проверить зависимости перед удалением объекта. Например, удалять категорию можно только в том случае, если она не содержит статей. Реализуем это с помощью сигнала:

from django.db import models from django.core.exceptions import ValidationError class Category(models.Model): name = models.CharField(max_length=100) def __str__(self): return self.name class Article(models.Model): title = models.CharField(max_length=200) category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='articles')

Обработчик сигнала для модели Category, который проверяет наличие связанных статей:

from django.db.models.signals import pre_delete from django.dispatch import receiver from django.core.exceptions import ValidationError from myapp.models import Category @receiver(pre_delete, sender=Category) def prevent_category_deletion(sender, instance, **kwargs): if instance.articles.exists(): raise ValidationError( f"Category '{instance.name}' has related articles and cannot be deleted." )

Попытка удалить категорию со статьями приведет к ошибке:

from myapp.models import Category category = Category.objects.get(id=1) try: category.delete() except ValidationError as e: print(e.message)

Результат выполнения кода:

"Category 'Technology' has related articles and cannot be deleted."

Пример

Иногда необходимо выполнить очистку внешних ресурсов, например, удалить файлы, связанные с удаляемым объектом. Предположим, у нас есть модель с полем image:

from django.db import models class Profile(models.Model): name = models.CharField(max_length=100) avatar = models.ImageField(upload_to='avatars/')

Обработчик сигнала, который удаляет файл с диска перед удалением записи из базы:

import os from django.db.models.signals import pre_delete from django.dispatch import receiver from myapp.models import Profile @receiver(pre_delete, sender=Profile) def delete_avatar_file(sender, instance, **kwargs): if instance.avatar: if os.path.isfile(instance.avatar.path): os.remove(instance.avatar.path)

Теперь при удалении профиля его аватар будет удален с файловой системы автоматически:

from myapp.models import Profile profile = Profile.objects.get(id=1) profile.delete() # файл avatar удаляется с диска

Смотрите также

  • сигнал post_delete,
    который срабатывает после удаления объекта
  • сигнал pre_save,
    который срабатывает перед сохранением объекта
  • сигнал post_save,
    который срабатывает после сохранения объекта
  • сигнал m2m_changed,
    который срабатывает при изменении связи ManyToMany
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить