Зіткнувся тут з необхідністю використовувати в проекті сигнал на зміну зв'язку "багато до багатьох". Для тих, хто з цим не стикався, коротко поясню. Ось приклад:
"Необіхдно виконати деякі дії над користувачем у виапдку, коли його включають в групу, або виключають з неї".
В Django 1.2.x існує прекрасний сигнал m2m_changed для обробки таких подій, чого не було у версії 1.1.x, про яку я зараз і пишу.
Перше, що приходить в голову - писати їендлер сигналу post_save для моделі django.contrib.auth.User. Але, спробувавши це зробити, ми побачимо, що в хендлері сигналу ми отримали зміни в об'єкті-користувачі, але групи, в які він включений, не змінились. Проблема в тому, що зв'язок "багато-до-багатьох" відбувається через додаткову таблицю, і на цьому етапі ми не отримуємо зміни, оскільки вони ще не відбулись.
Є декілька шляхів вирішення даної задачі, які підходять при різних вимогах.
1. Створюємо свій власний менеджер моделей (django.db.models.Manager)
Даний підхід, мабуть, вийде найбільш універсальним для даної задачі. Створивши свій менеджер, можна перевизначити методи add, clear, додавши туди необхідну поведінку. Таким чином, вказуємо дії, які можна виконати, в одному місц.
2. Запам'ятовуємо змінені об'єкты, і робимо подальшу обробку в запланованій задачі.
Цей варіант підійде тільки тоді, коли вплив змін є некритичним для роботи проекту, а дії можуть бути виконані через певний час після внесення змін в об'єкти.
3. Використовуємо save_model класу ModelAdmin.
Метод save_model цікавий тим, що отримує в якості аргументів, крім моделі, ще й форму, що дозволяє порівняти старий стан об'єкту і новий через form.cleaned_data, на базі чего можна виконати необхідні додаткові дії. Використовувати варто тоді, коли гарантується зміна моделі через адміністративну частину сайту.
4. Виконуємо дії у view чи чи формі при збереженні об'єкту.
Аналогічно до попереднього методу, тільки так протрібно робити у всіх формах і в'юхах, які приймають участь в зміні потрібного атрибута об'єкта.
Коментарі
Дописати коментар