Django: не может обнаружить изменения в поле «многие ко многим» с помощью сигнала m2m_changed - аудит на уровне модели - PullRequest
5 голосов
/ 20 января 2011

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

Для приведенного ниже примера кода я определяю поле m2m 'custom_groups' в форме изменения пользователя, поскольку это обратное отношение.Когда пользователь сохраняет форму, например, в интерфейсе администратора, я хотел бы войти, если есть изменение в поле 'custom_groups'.

Модель:

from django.contrib.auth.models import User

class CustomGroup(models.Model):
    users = models.ManyToManyField(User, related_name='custom_groups')

ModelForm:

class CustomUserChangeForm(UserChangeForm):
    custom_groups = forms.ModelMultipleChoiceField(required=False, queryset=CustomGroup.objects.all())

Проблема с использованием сигнала m2m_changed заключается в том, что я не могу проверить, что фактически изменилось для случая, когда поле m2m обновляется с помощью оператора присваивания:

user.custom_groups = self.cleaned_data['custom_groups']

Это связано с тем, что внутри django выполнит очистку () для * custom_groups *, прежде чем вручную добавлять все объекты.Это выполнит pre / post-clear и затем pre / post save в поле m2m.

Я все это делаю неправильно?Есть ли более простой способ, который действительно может работать?

Спасибо!

1 Ответ

12 голосов
/ 29 марта 2011

У меня была похожая проблема, и я думаю, что смогу ее решить.Я не знаю, как вы используете m2m_changed, но он должен быть в файле models.py и должен выглядеть примерно так:

signals.m2m_changed.connect(your_function, sender=CustomGroup.users.through)

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

def your_function(sender, instance, action, reverse, model, pk_set, **kwargs):
    if action == 'post_add':
        for val in pk_set:
            print val

Теперь вы знаете обновленные значения.Я надеюсь, что это может решить вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...