Django:无法使用m2m_changed信号检测多对多字段的变化 - 在模型级别进行审计

Edw*_*win 5 django-models m2m

我想跟踪任何模型上哪些字段发生了变化(即在模型级别进行审计,因为它更具原子性,而不是像django和django-reversion已经可以执行的管理/表单级别).我可以使用前/后保存/删除信号为任何字段执行此操作.但是,我在m2m字段上有这样做的问题.

对于下面的代码示例,我在用户更改表单中定义'custom_groups'm2m字段,因为它是反向关系.例如,当用户在管理界面上保存表单时,如果"custom_groups"字段中有更改,我想记录.

模型:

from django.contrib.auth.models import User

class CustomGroup(models.Model):
    users = models.ManyToManyField(User, related_name='custom_groups')
Run Code Online (Sandbox Code Playgroud)

的ModelForm:

class CustomUserChangeForm(UserChangeForm):
    custom_groups = forms.ModelMultipleChoiceField(required=False, queryset=CustomGroup.objects.all())
Run Code Online (Sandbox Code Playgroud)

使用m2m_changed信号的问题是我无法检查在使用赋值运算符更新m2m字段的情况下实际更改了什么:

user.custom_groups = self.cleaned_data['custom_groups']
Run Code Online (Sandbox Code Playgroud)

这是因为在手动添加所有对象之前,内部django将在*custom_groups*上执行clear().这将执行前/后清除,然后在m2m字段上执行前/后保存.

我这么做错了吗?是否有一种更简单的方法可以实际工作?

谢谢!

Kik*_*dez 12

我有类似的问题,我想我可以解决它.我不知道你是如何使用m2m_changed但它应该在models.py上,应该类似于这样的东西:

signals.m2m_changed.connect(your_function, sender=CustomGroup.users.through)
Run Code Online (Sandbox Code Playgroud)

现在,我将创建一个包含该函数的signals.py文件,以下代码应该打印出您选择的选项:

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

现在,您知道更新的值.我希望这可以解决你的问题.