比较有多对多字段的Django模型对象

1 投票
1 回答
1781 浏览
提问于 2025-04-15 14:01

我遇到一个情况,需要在数据库里有变化时通知一些用户。我的想法是捕捉 pre_savepost_save 这两个信号,然后做一些比较(也就是找出变化的地方)并把这些变化通过邮件发送出去。总体来说,这个方法效果不错,但我不知道怎么获取多对多(m2m)字段的变化。

目前我有这样的代码:

def pre_save(sender, **kwargs):
    pk = kwargs['instance'].pk
    instance = copy.deepcopy(sender.objects.get(pk=pk))
    tracking[sender] = instance

def post_save(sender, **kwargs):
    instance = copy.deepcopy(kwargs['instance'])
    print diff(instance, (tracking[sender])) # TODO: don't print, save diff somewhere

这个比较函数应该能适用于每个模型(现在我有四个模型类)。通过深拷贝,我可以保存旧的模型数据,但我不知道怎么保存多对多字段,因为这些字段在一个单独的表里(是的,我知道可以获取这些数据,但在执行的时候我不知道哪些字段是多对多的,而且我不想为每个模型都创建不同的存储方式)。我希望有一个通用的解决方案,这样我可以在以后添加模型时,不用再考虑通知的部分。

我的计划是在视图中调用 save() 后,接着调用 get_data()clear_data() 函数,以清理那些生成的变化数据。

这样做是否合适?有没有更好的方法?有没有现成的 Django 应用可以帮我完成这个工作?

请原谅我的英语,它不是我的母语。

1 个回答

6

首先,你不需要使用深拷贝(deepcopy)。从数据库重新查询发送者会返回一个“新鲜”的对象。

def pre_save(sender, **kwargs):
    pk = kwargs['instance'].pk
    instance = sender.objects.get(pk=pk)
    tracking[sender] = instance

你可以获取一个类中所有多对多字段的列表,然后检查与当前实例相关的值:

for field in sender._meta.local_many:
    values = field.value_from_object(instance).objects.all()
    # Now values is a list of related objects, which you can diff

撰写回答