我们说我有以下型号:
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>))
另一个问题是save函数依赖于名为blog
的外键,由于添加使用不同外键名称的模型需要更新save函数,因此这看起来很麻烦。
对于更新相关模型的时间戳这个问题,是否有更通用的解决方案?如何修改上面的save()
函数以使用相同时间戳持续更新模型?
答案 0 :(得分:1)
如果在每个模型中使用相同的外键引用,则找到解决方案:
def save(self, *args, **kwargs):
self.last_changed = timezone.now()
try:
self._meta.get_field('blog')
except models.FieldDoesNotExist:
super(TimeStampedModel, self).save(*args, **kwargs)
else:
self.blog.last_changed = self.last_changed
with transaction.atomic():
super(TimeStampedModel, self).save(*args, **kwargs)
super(TimeStampedModel, self.blog).save(*args, **kwargs)