如何在Django模型中使用update()时跟踪更改

时间:2016-06-21 18:13:46

标签: django django-models django-simple-history

我试图在字段更改时跟踪更改。

每当我使用.save()方法时,我都可以看到Django管理历史记录中的更改,但每当我使用.update()方法时,它都不记录我在对象中更改的内容。

我想使用update(),因为它可以同时更改多个字段。它使代码更清晰,更有效(一个查询,一行......)

现在我正在使用它:

u = Userlist.objects.filter(username=user['username']).update(**user)

我可以看到所有的变化

u = Userlist.objects.get(username=user['username'])
u.lastname=lastname
u.save()

我也使用django-simple-history来查看changes.setup。

2 个答案:

答案 0 :(得分:0)

来自docs

  

最后,意识到update()在SQL级别进行更新,   因此,不会在您的模型上调用任何save()方法,也不会   发出pre_savepost_save信号(这是...的结果)   致电Model.save()

update()适用于数据库级别,因此当通过.update(...)应用更新时,Django管理员无法跟踪更改。

如果您仍想跟踪更新的更改,可以使用:

for user in Userlist.objects.filter(age__gt=40):
    user.lastname = 'new name'
    user.save()

然而,这是更昂贵的,如果唯一的好处是通过管理历史跟踪更改,则不建议这样做。

答案 1 :(得分:0)

这是我的处理方式,到目前为止效果良好:

# get current model instance to update
instance = UserList.objects.get(username=username)

# use model_to_dict to convert object to dict (imported from django.forms.models import model_to_dict)
obj_dict = model_to_dict(instance)

# create instance of the model with this old data but do not save it
old_instance = UserList(**obj_dict)

# update the model instance (there are multiple ways to do this)
UserList.objects.filter(username=username).update(**user) 

# get the updated object
updated_object = UserList.objects.get(id=id)

# get list of fields in the model class
my_model_fields = [field.name for field in cls._meta.get_fields()]

# get list of fields if they are different
differences = list(filter(lambda field: getattr(updated_object, field, None)!= getattr(old_instance, field, None), my_model_fields))

difference变量将为您提供两个实例之间不同的字段列表。我还发现添加不希望检查差异的模型字段很有帮助(例如,我们知道updated_date将始终被更改,因此我们无需对其进行跟踪)。

skip_diff_fields = ['updated_date']

my_model_fields = []
for field in cls._meta.get_fields():
    if field.name not in skip_diff_fields:
        my_model_fields.append(field.name)