Сигналы Django против преобладающего метода сохранения - PullRequest
75 голосов
/ 04 октября 2008

У меня проблемы с тем, чтобы обернуть голову вокруг этого. Сейчас у меня есть несколько моделей, которые выглядят примерно так:

 def Review(models.Model)
    ...fields...
    overall_score = models.FloatField(blank=True)

def Score(models.Model)
    review = models.ForeignKey(Review)
    question = models.TextField()
    grade = models.IntegerField()

В обзоре есть несколько «баллов», а общий балл - средний балл. Когда отзыв или оценка сохранены, мне нужно пересчитать среднее значение по шкале. Прямо сейчас я использую переопределенный метод сохранения. Будет ли какая-то польза от использования диспетчера сигналов Django?

Ответы [ 6 ]

77 голосов
/ 05 октября 2008

Сигналы сохранения / удаления, как правило, удобны в ситуациях, когда вам необходимо внести изменения, которые не являются полностью специфичными для рассматриваемой модели, или могут быть применены к моделям, которые имеют что-то общее, или могут быть настроены для использования в разных моделях. .

Одной из распространенных задач в переопределенных методах save является автоматическое создание слагов из некоторого текстового поля в модели. Это пример чего-то, что, если бы вам нужно было реализовать его для ряда моделей, было бы полезно использовать сигнал pre_save, где обработчик сигнала мог бы взять имя поля слага и имя поля для генерации слизняк из. Если у вас есть что-то подобное, любая улучшенная функциональность, которую вы используете, также будет применяться ко всем моделям, например ищем слаг, который вы собираетесь добавить для рассматриваемой модели, чтобы обеспечить уникальность.

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

Например, с помощью django-mptt я использовал сигнал pre_save для управления набором полей, которые описывают древовидную структуру для модели, которая должна быть создана или обновлена, и pre_delete сигнал для удаления деталей древовидной структуры для удаляемого объекта и всего его поддерева объектов перед ним, и они удаляются. Из-за использования сигналов пользователям не нужно добавлять или изменять методы save или delete в своих моделях, чтобы сделать это управление для них, они просто должны сообщить django-mptt, какие модели им нужны. управление.

17 голосов
/ 09 марта 2016

Вы спросили:

Будет ли какая-то польза от использования диспетчера сигналов Django?

Я нашел это в django docs:

Переопределенные методы модели не вызываются при массовых операциях

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

К сожалению, при создании или обновлении обходного пути нет объемных объектов, так как ни один из методов save (), pre_save и post_save не является называется.

От: Переопределение предопределенных методов модели

3 голосов
/ 04 октября 2008

Если вы будете использовать сигналы, вы сможете обновлять оценку отзыва при каждом сохранении связанной модели оценки. Но если такая функциональность мне не нужна, я не вижу смысла в том, чтобы показывать это, это довольно модельные вещи.

2 голосов
/ 04 октября 2008

Это своего рода денормализация. Посмотрите на это красивое решение . Определение поля композиции на месте.

1 голос
/ 11 сентября 2018

Небольшое дополнение из документации Django о массовом удалении (метод .delete() для QuerySet объектов):

Имейте в виду, что это, по возможности, будет выполняться исключительно в SQL, и поэтому методы delete () отдельных экземпляров объекта будут не обязательно быть вызванным во время процесса. Если вы предоставили пользовательский метод delete () для класса модели и хотите убедиться, что он при вызове вам нужно будет «вручную» удалить экземпляры этой модели (например, путем перебора QuerySet и вызова delete () для каждого объект), а не метод массового удаления () QuerySet.

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

И массовое обновление (метод .update() для QuerySet объектов):

Наконец, осознайте, что update () выполняет обновление на уровне SQL и, таким образом, не вызывает никаких методов save () в ваших моделях и не делает испускать сигналы pre_save или post_save (которые являются следствием вызывая Model.save ()). Если вы хотите обновить кучу записей для модель, которая имеет собственный метод save (), зацикливается на них и вызывает save ()

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update

0 голосов
/ 25 марта 2011

Сигналы полезны, когда вам нужно выполнить какой-то длительный процесс и не хотите блокировать пользователя, ожидающего завершения сохранения.

...