Как использовать сигнал pre_delete для универсального предотвращения удаления? - PullRequest
0 голосов
/ 05 января 2020

У меня есть общее поле is_active = models.BooleanField() на всех моих моделях.

Я хочу создать универсальное переопределение функции удаления, чтобы вместо удаления записей из базы данных is_active = False.

Я понимаю, что лучший способ сделать это - сигнал pre_delete вместо переопределения самого delete(), поскольку delete() не вызывается в массовых операциях .

Я пытался следующая реализация:

@receiver(pre_delete)
def delete_obj(sender, instance, **kwargs):
    """Override delete() to set object to inactive."""

    return instance.is_active == False

Однако это все равно приводит к удалению объектов из базы данных. Я предполагаю, что это потому, что delete() все еще вызывается после pre_delete. Как это исправить?

Из документов:

Обратите внимание, что метод delete () для объекта не обязательно вызывается при массовом удалении объектов с использованием QuerySet или в качестве результат каскадного удаления. Чтобы обеспечить выполнение настраиваемой логики удаления c, вы можете использовать сигналы pre_delete и / или post_delete.

1 Ответ

0 голосов
/ 06 января 2020

Вы хотите заменить логи c оригинального метода (в этом случае вместо обновления удалять) не до расширить it.

Сигналы должны расширяться основной метод logi c, не заменять его.

В pre_ сигналов - запустить некоторые дополнительные логики c перед действием (возможно, даже изменить объект). В post_ сигналы - запустить дополнительные логи c после основного действия. Но основное действие все еще выполняется - и оно должно - оно было вызвано по праву в коде - сигналы не должны его заменять.

Как и метод расширения в модели: вы добавите немного logi c до того, как или после вызова super().method() - так работают сигналы.

В случае замены метода logi c на другой - при переопределении метода super(), скорее всего, вызываться не будет, поэтому никаких исходных действий не будет. Выполнено.


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


Ссылка на дополнительный код, где выполняется удаление QuerySet :

  • pre_delete сигнал отправляется
  • delete_batch выполняется
  • post_delete сигнал отправляется
...