Джанго сигналы и переопределить метод save


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

 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()

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

6 69

6 ответов:

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

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

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

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

ты спрашиваешь:

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

Я нашел это в документах django:

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

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

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

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

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

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

небольшое дополнение от Django docs о массовом удалении (.delete() метод on QuerySet объекты):

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

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

и пакетное обновление (.update() метод on QuerySet объекты):

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

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

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