Сигналы Django против преобладающего метода сохранения

StackOverflow https://stackoverflow.com/questions/170337

Вопрос

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

 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?

Это было полезно?

Решение

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

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

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

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

Другие советы

Вы спросили:

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

Я нашел это в Django Docs:

  

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

     

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

     

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

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

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

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

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

  

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

https://docs.djangoproject.com/ ан / 1.11 / темы / дб / запросы / # Удаление-объекты

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

  

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

https://docs.djangoproject.com/en/ 2,1 / исх / модели / querysets / # обновление

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top