пятница, 24 сентября 2010 г.

Замена сигнала m2m_changed для Django 1.1.x


Вот столкнулся с необходимостью использовать в проекте сигнал на изменения связей многие ко многим. Для тех, кто с этим не сталкивался коротко объясню. Вот пример:

"Нужно выполнить некие действия над пользователем в случае, когда его включают в группу, или выключают из нее".

В 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. Делаем действия в виде или форме при сохранении объекта.

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

Комментариев нет:

Отправить комментарий

В этом гаджете обнаружена ошибка