假设我有许多记录值的探测器。我想设置Django模型来表示探针以及它们记录的测量值。所以这样的事情会起作用:
class Probe(models.Model):
name = models.CharField(max_length=256)
def __unicode__(self):
return u'<Probe: %s>' % self.name
class Observation(models.Model):
probe = models.ForeignKey(Probe)
obstime = models.DateTimeField()
# the above field should be understood to represent the time in the world
# represented by the measurement value recorded. *not* the time at which
# that value was written to the database.
value = models.FloatField()
class Meta:
unique_together = (('probe', 'obstime'), )
def __unicode__(self):
tup = (self.probe.name,
self.obstime.strftime('%Y%m%d-%H%M%S'),
'%0.2f' % self.value)
return u'<Observation: %s @ %s = %s>' % tup
但除此之外,我真的希望我的数据库和应用程序能够跟踪更多信息。特别是,我真的希望Observation
模型有3个额外的字段:db_recording_time
,previous_value
,previous_db_recording_time
。我希望用户直接尝试仅操作上面给出的条目,但让其他字段以预期的方式自动运行。我认为应该可以通过覆盖save
类的Observation
方法来实现,但我需要一些帮助!
所以说一个人从1月5日中午回到现场,坐在他们的电脑旁。他们希望记录一些(从未输入过的)数据,表明ProbeA在1月1日凌晨2点读取3.14。我只希望他们需要指定3.14和2AMJan1st,但我想要观察进入DB:
probe: ProbeA,
obstime: 2AMJan1st,
value: 3.14,
db_recording_time: NoonJan5th,
previous_value: Null,
previous_db_reording_time: Null
然后,几个小时后(2 PM,5月5日),同一个人可以看看他们的笔记本并意识到“哎呀,我误读了笔记本中的价值...它真的是2.14”。所以我希望他们(使用管理员或Python控制台)调用现有观察并将3.14更正为2.14。当他们这样做时,我希望DB中的观察显示:
probe: ProbeA,
obstime: 2AMJan1st,
value: 2.14,
db_recording_time: 2PMJan5th,
previous_value: 3.14,
previous_db_reording_time: NoonJan5th
我觉得这应该非常简单,只需在Admin界面中组合使用只读字段,并在save
类的Observation
方法中覆盖一些合理的覆盖。任何帮助将不胜感激!
答案 0 :(得分:1)
您可以在保存之前从数据库中检索旧记录:
recording_time = models.DateTimeField(auto_now=True)
previous_value = models.FloatField(null=True, default=None)
previous_recording_time = models.DateTimeField(null=True, default=None)
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
try:
obj = Observation.objects.get(pk=self.pk)
# this is the record of this instance before editing
except Observation.DoesNotExist: # self.pk==None: this is a new Observation
pass
else: # this is indeed an update
self.previous_value = obj.value
previous_db_recording_time = obj.db_recording_time
super(Observation, self).save(force_insert=force_insert, force_update=force_update, using=using,
update_fields=update_fields)
现在,没有人必须手动设置recording_time
,previous_value
或previous_recording_time
。因此,您可以从ModelForm
Observation
课程中使用的Admin
中排除这些字段。
答案 1 :(得分:0)
正如我在评论中建议的那样,您可以在观察模型中向self
添加一个外键,该外键是指之前进行的观察,然后您不需要复制这些字段,例如previous_value
,previous_db_recording_time
。
class Observation(models.Model):
...
prev_observation = models.ForeignKey('self', null=True)
# you can also add a `is_recent` field to this model so you set it to True when its created
is_recent = models.BooleanField(default=True)
因此,我们假设您在一周[o1, o2, o3, o4, o5, o6, o7]
中添加了7个观察值,因此对于所有这7个is_recentt
都将为True。
而且,您可以按如下方式获得这些观察结果:
Observation.objects.filter(probe=chosenprobe,
obstime__gte=start, obstime__lte=end,
is_recent=True)
# [o1, o2, o3, o4, o5, o6, o7]
现在,您已使用o1
,o3
和o6
更正了o8
,o9
和o10
,所以此时您可以设置{ {1}},is_recent
和o1
为{1}}。
然后,再次运行上述查询将为您提供更新的(最近的)观察结果:
o3