Django: не может обнаружить изменения в поле "многие ко многим" с помощью сигнала m2m_changed - аудит на уровне модели
Я хотел бы отслеживать, какое поле изменилось в любой модели (т. Е. Проводить аудит на уровне модели, поскольку он более атомарный, а не на уровне администратора / формы, как то, что 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 выполнит clear() для *custom_groups*, прежде чем вручную добавлять все объекты. Это выполнит pre/post-clear и затем pre/post save в поле m2m.
Я делаю все это неправильно? Есть ли более простой метод, который действительно может работать?
Спасибо!
1 ответ
У меня была похожая проблема, и я думаю, что смогу ее решить. Я не знаю, как вы используете m2m_oted, но оно должно быть на 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
Теперь вы знаете обновленные значения. Я надеюсь, что это может решить вашу проблему.