【发布时间】:2018-11-17 11:00:28
【问题描述】:
假设我有以下模型:
class Blog(TimeStampedModel):
summary = models.TextField()
text = models.TextField()
class BlogComment(TimeStampedModel):
author = models.CharField()
text = models.CharField()
blog = models.ForeignKey(Blog, models.CASCADE, related_name='comments')
class BlogTag(TimeStampedModel):
name = models.CharField()
blog = models.ForeignKey(Blog, models.CASCADE, related_name='tags')
这三个都继承自以下模型,它实现了一些时间戳处理:
class TimeStampedModel(models.Model):
last_changed = models.DateTimeField()
created_at = models.DateTimeField(default=timezone.now)
def save(self, *args, **kwargs):
try:
self._meta.get_field('blog')
except models.FieldDoesNotExist:
self.last_changed = timezone.now()
super(TimeStampedModel, self).save(*args, **kwargs)
else:
now = timezone.now()
self.blog.last_changed = now
self.last_changed = now
with transaction.atomic():
super(TimeStampedModel, self).save(*args, **kwargs)
self.blog.save()
class Meta:
abstract = True
自定义 save() 背后的基本思想是,例如,当更新评论(BlogComment 的实例)时,它应该更新评论实例和相关博客条目的 last_changed 时间戳。
不幸的是,时间戳设置并不完美,因为它会在调用自己的保存时覆盖博客的时间戳,并且时间最终会略有不同:
In [1]: b = Blog.objects.get(id=1)
In [2]: comment0 = t.comments.all()[0]
In [3]: b.last_changed, comment0.last_changed
Out[3]:
(datetime.datetime(2018, 6, 7, 12, 54, 12, 516855, tzinfo=<UTC>),
datetime.datetime(2018, 6, 7, 10, 22, 09, 201690, tzinfo=<UTC>))
In [4]: comment0.text
Out[4]: 'Some text'
In [5]: comment0.text = 'test'
In [6]: comment0.save()
In [7]: t = blog.objects.get(id=1)
In [8]: comment0 = t.comments.all()[0]
In [9]: t.last_changed, comment0.last_changed
Out[9]:
(datetime.datetime(2018, 6, 7, 13, 25, 58, 64131, tzinfo=<UTC>),
datetime.datetime(2018, 6, 7, 13, 25, 58, 61960, tzinfo=<UTC>))
另一个问题是保存函数依赖于名为blog 的外键,这似乎很麻烦,因为添加使用不同外键名称的模型需要更新保存函数。
对于更新相关模型的时间戳这个问题,有没有更通用的解决方案?如何修改上面的 save() 函数以持续更新具有 same 时间戳的模型?
【问题讨论】:
标签: python django django-models timestamp