Сигнали Django проти методу збереження, що замінює


89

У мене проблеми з обгортанням голови навколо цього. Зараз у мене є кілька моделей, які виглядають приблизно так:

 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?

Відповіді:


85

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

Одним із загальних завдань перевизначених saveметодів є автоматизована генерація кульок з якогось текстового поля в моделі. Це приклад того, що, якщо вам потрібно було реалізувати це для ряду моделей, було б корисно використовувати pre_saveсигнал, де обробник сигналу міг би взяти ім'я поля slug та ім'я поля, з якого генерується slug. Після того, як у вас є щось подібне, будь-яка розширена функціональність, яку ви встановите, також застосовуватиметься до всіх моделей - наприклад, пошук кулі, яку ви збираєтеся додати для типу моделі, про яку йде мова, для забезпечення унікальності.

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

Наприклад, за допомогою django-mptt я використовував pre_saveсигнал для управління набором полів, що описують деревоподібну структуру для моделі, яка збирається створити або оновити, та pre_deleteсигнал для видалення деталей деревної структури для об'єкта, що видаляється, і всього його піддерево об'єктів перед ним, і вони видаляються. Завдяки використанню сигналів, користувачі не повинні додавати, модифікувати saveабо deleteметоди на своїх моделях, щоб зробити це управління за них, вони просто повинні повідомити django-mptt, якими моделями вони хочуть ним керувати.


Що робити, якщо обробник сигналу викликає виняток? Я припускаю, що вони не повинні викликати винятки, інакше вони не підходять. Я помиляюся?
x-yuri

20

Ти запитав:

Чи буде якась вигода від використання диспетчера сигналів Django?

Я знайшов це в документації django:

Перевизначені методи моделі не викликаються при масових операціях

Зауважте, що метод delete () для об’єкта не обов’язково викликається при масовому видаленні об’єктів за допомогою QuerySet або в результаті каскадного видалення. Щоб забезпечити виконання налаштованої логіки видалення, ви можете використовувати сигнали pre_delete та / або post_delete.

На жаль, обхідного способу створення або оновлення об’єктів масово не існує, оскільки ніхто з методів save (), pre_save та post_save не викликається.

Від: Заміна попередньо визначених методів моделі


3
У поданні списку адміністратора Django використовується групове видалення ... було заплутано, поки не натрапив на цей шматок.
Н.Баларо

7
у ньому також сказано: "На жаль, не існує обхідного способу створення або оновлення об'єктів навалом, оскільки ніхто з методів save (), pre_save та post_save не викликається." - тому я не думаю, що це компроміс між цими методами.
Кори

Це стосується обох методів, тож відповідь тоді: "ні, немає ніякої користі від використання сигналів на відміну від заміни saveметоду"?
Флімм

3

Якщо ви будете використовувати сигнали, ви зможете оновлювати оцінку огляду кожного разу, коли модель збережених оцінок зберігається. Але якщо така функціональність не потрібна, я не бачу жодної причини подавати це на сигнал, це досить пов'язані з моделями речі.



1

Невелике доповнення з документів 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


Чи не стосується це обох?
Флімм
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.