django 对象更新、跟踪和比较变化
django object updates, track and compare changes
我有一个具有属性值的对象。值可以每周更新一次,例如用户星期一。
我希望能够按周数显示对象值,例如 wk35 值、wk36 值 ... wk40 值。
我希望能够比较历史值并获得百分比变化。
我不知道的是:
我是否应该为我的对象创建属性,例如
创建日期
dateupdated(因此它包含特定日期的最后更新)
dateedited(因此用户可以在一天内多次编辑值)
我知道用户可以多次编辑值,但应该能够在当天更新一次最终编辑。
我正在为上述想法而苦苦挣扎。我已经开始阅读有关 simple-history 的内容,它可以帮助我实现跟踪更改,但我不知道如何实现上面写的内容。
我的模型class是:
class ZoneSubStage(models.Model):
zone = models.ForeignKey(Zone)
substage = models.ForeignKey(SubStage)
value = models.PositiveSmallIntegerField(default=0)
slug = models.SlugField(unique=True)
history = HistoricalRecords()
created = models.DateTimeField(auto_now_add=True)
date = models.DateField(null=True)
可能有一些第三方模块可以为您执行此操作,但我最好的家庭酿造建议是日志记录 table。如果您需要日志条目按日期是唯一的,您只需要修改 ZoneSubStage.save()
方法以在简单地创建一个新的之前查找 ZoneSubStageLog
当前日期(我认为你需要但会离开给你)。
from django.db import transaction
class ZoneSubStage(models.Model):
zone = models.ForeignKey(Zone)
substage = models.ForeignKey(SubStage)
value = models.PositiveSmallIntegerField(default=0)
slug = models.SlugField(unique=True)
history = HistoricalRecords()
created = models.DateTimeField(auto_now_add=True)
date = models.DateField(null=True)
def __init__(self, *args, **kwargs):
super(ZoneSubStage, self).__init__(*args, **kwargs)
self.value_original = self.value
def save(self, **kwargs):
with transaction.atomic():
response = super(ZoneSubStage, self).save(**kwargs)
if self.value_original != self.value:
zone_log = ZoneSubStageLog()
zone_log.zone_sub_stage = self
zone_log.value = self.original_value
zone_log.save()
return response
class ZoneSubStageLog(models.Model):
zone_sub_stage = models.ForeignKey(ZoneSubStage)
value = models.PositiveSmallIntegerField(default=0)
date = models.DateField(auto_now_add=True)
这是一个非常 broad/high-level 的问题,但基本上您应该将历史 data/changes 与您的模型分开存储。
这样想:您的模型是一个有生命的实体,它有一个当前状态。您可以定期拍摄该状态(数据)的 快照 。稍后,您可以使用您制作的这些快照来拼凑模型的历史记录(例如,可视化它是如何随时间变化的)。这基本上就是 Memento pattern.
所以,请考虑您的需求。你的模型快照应该有什么"resolution"?也就是说,它应该存储每个数据点还是只存储几个?它应该存储每个用户的每一次更改,还是每周拍摄一次快照?如果只是每周一次,正如您所建议的,只需 运行 一个将模型数据复制到另一个模型...或另一个数据库的 cron 作业,或者您甚至可以将其写成一个平面 JSON或 CSV 文件!
或者...如果您希望能够完全按照某个时间点的样子重建模型,请考虑像 django-reversion 这样的包。
另一方面,如果随着时间的推移只有一个或两个真正重要的数字需要跟踪,您可以创建一个模型,将原始模型的 id 存储为外键,重要的数字值,和时间戳。
编辑:如果您只想保留 ZoneSubStage.value,Dotcomly 的回答提供了一个很好的实现。为了更好地将日志与模型分离,我建议使用 post_save
signal 来创建日志条目,而不是覆盖模型的保存方法。
我有一个具有属性值的对象。值可以每周更新一次,例如用户星期一。
我希望能够按周数显示对象值,例如 wk35 值、wk36 值 ... wk40 值。
我希望能够比较历史值并获得百分比变化。
我不知道的是:
我是否应该为我的对象创建属性,例如
创建日期 dateupdated(因此它包含特定日期的最后更新) dateedited(因此用户可以在一天内多次编辑值)
我知道用户可以多次编辑值,但应该能够在当天更新一次最终编辑。
我正在为上述想法而苦苦挣扎。我已经开始阅读有关 simple-history 的内容,它可以帮助我实现跟踪更改,但我不知道如何实现上面写的内容。
我的模型class是:
class ZoneSubStage(models.Model):
zone = models.ForeignKey(Zone)
substage = models.ForeignKey(SubStage)
value = models.PositiveSmallIntegerField(default=0)
slug = models.SlugField(unique=True)
history = HistoricalRecords()
created = models.DateTimeField(auto_now_add=True)
date = models.DateField(null=True)
可能有一些第三方模块可以为您执行此操作,但我最好的家庭酿造建议是日志记录 table。如果您需要日志条目按日期是唯一的,您只需要修改 ZoneSubStage.save()
方法以在简单地创建一个新的之前查找 ZoneSubStageLog
当前日期(我认为你需要但会离开给你)。
from django.db import transaction
class ZoneSubStage(models.Model):
zone = models.ForeignKey(Zone)
substage = models.ForeignKey(SubStage)
value = models.PositiveSmallIntegerField(default=0)
slug = models.SlugField(unique=True)
history = HistoricalRecords()
created = models.DateTimeField(auto_now_add=True)
date = models.DateField(null=True)
def __init__(self, *args, **kwargs):
super(ZoneSubStage, self).__init__(*args, **kwargs)
self.value_original = self.value
def save(self, **kwargs):
with transaction.atomic():
response = super(ZoneSubStage, self).save(**kwargs)
if self.value_original != self.value:
zone_log = ZoneSubStageLog()
zone_log.zone_sub_stage = self
zone_log.value = self.original_value
zone_log.save()
return response
class ZoneSubStageLog(models.Model):
zone_sub_stage = models.ForeignKey(ZoneSubStage)
value = models.PositiveSmallIntegerField(default=0)
date = models.DateField(auto_now_add=True)
这是一个非常 broad/high-level 的问题,但基本上您应该将历史 data/changes 与您的模型分开存储。
这样想:您的模型是一个有生命的实体,它有一个当前状态。您可以定期拍摄该状态(数据)的 快照 。稍后,您可以使用您制作的这些快照来拼凑模型的历史记录(例如,可视化它是如何随时间变化的)。这基本上就是 Memento pattern.
所以,请考虑您的需求。你的模型快照应该有什么"resolution"?也就是说,它应该存储每个数据点还是只存储几个?它应该存储每个用户的每一次更改,还是每周拍摄一次快照?如果只是每周一次,正如您所建议的,只需 运行 一个将模型数据复制到另一个模型...或另一个数据库的 cron 作业,或者您甚至可以将其写成一个平面 JSON或 CSV 文件!
或者...如果您希望能够完全按照某个时间点的样子重建模型,请考虑像 django-reversion 这样的包。
另一方面,如果随着时间的推移只有一个或两个真正重要的数字需要跟踪,您可以创建一个模型,将原始模型的 id 存储为外键,重要的数字值,和时间戳。
编辑:如果您只想保留 ZoneSubStage.value,Dotcomly 的回答提供了一个很好的实现。为了更好地将日志与模型分离,我建议使用 post_save
signal 来创建日志条目,而不是覆盖模型的保存方法。