【问题标题】:Updating timestamps of a model and its related parent with the same time用同一时间更新模型及其相关父代的时间戳
【发布时间】: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


    【解决方案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)
    

    【讨论】:

      猜你喜欢
      • 2017-06-06
      • 1970-01-01
      • 2015-10-02
      • 2014-05-21
      • 1970-01-01
      • 1970-01-01
      • 2020-08-31
      • 1970-01-01
      • 2015-08-30
      相关资源
      最近更新 更多