更新模型时,更新所有相关模型的日期时间

时间:2019-06-18 10:47:29

标签: django django-models

我有两个模型(发布和展示)。两者都有Datetime-auto字段。我的问题是,帖子更新后,我想更新与该帖子相关的所有显示对象。

我在这里已经读到可以覆盖一个模型的保存方法,但是所有示例都是关于使用外键更新模型,然后调用另一个模型的save方法。就我而言,这是另一种方式。我怎样才能做到这一点 ?

class Post(models.Model):
    title = models.CharField(max_length=40)
    content = models.TextField(max_length=300)
    date_posted = models.DateTimeField(auto_now=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    rooms = models.ManyToManyField(Room, related_name='roomposts',  through='Display')


    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return "/post/{}/".format(self.pk)

class Display(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    isdisplayed = models.BooleanField(default=0)
    date_posted = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(self.isdisplayed)

我想在所有相关显示对象的相关帖子更改后更新其date_posted。我不知道覆盖保存方法是否在这里起作用。

2 个答案:

答案 0 :(得分:1)

在这种情况下,您应该看看Django的反向外键文档 https://docs.djangoproject.com/en/2.2/topics/db/queries/#following-relationships-backward

在您的情况下,您可以覆盖Post模型上的save方法

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)
    #either: this excutes many sql statments
    for display in self.display_set.all():
        display.save()
    #or faster: this excute only one sql statements,
    #but note that this does not call Display.save
    self.display_set.all().update(date_posted=self.date_posted)

可以使用display_set选项更改名称related_name

在“显示”中,您可以更改它:

post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='displays')

然后,您可以使用self.display_set

来代替在代码中使用self.displays

答案 1 :(得分:1)

覆盖保存方法有效,但不是,该死,imo。

您需要的是信号:

@receiver(post_save, sender=Post)
def update_displays_on_post_save(sender, instance, **kwargs):
    if kwargs.get('created') is False:  # This means you have updated the post
        # do smth with instance.display_set

通常它进入signals.py。 另外,您还需要在AppConfig中添加

def ready(self):
    from . import signals  # noqa