Django,调用 super() 后如何在 save() 方法中更新模型?

Posted

技术标签:

【中文标题】Django,调用 super() 后如何在 save() 方法中更新模型?【英文标题】:Django, how to update model in save() method after calling a super()? 【发布时间】:2014-03-19 23:54:41 【问题描述】:

我有这样的问题。比如我的模型类中有一个字段:

periodic_task = models.OneToOneField(PeriodicTask, null=True, blank=True)

我需要重写save()方法来设置这个字段值:

def save(self, *args, **kwargs):
    super(PostTweetSet, self).save(*args, **kwargs)
    self.periodic_task = TaskScheduler.create(
        'tweets.tasks.post_next_tweet', self.interval.period,
        self.interval.every, args="[" + '"%s"' % str(self.pk) + "]")

您会看到self.periodic_task 在实际调用super() 方法后被分配。我这样做是因为需要一个 pk 字段(我在TaskScheduler create 方法中使用它)。另一方面,我需要在设置这个新字段后更新这个模型的 db-table。如果我再次致电super(),我会收到有关复制 id 的错误。那么,我能做些什么来完成这项工作呢?或者我需要为这项任务重建我的方法?谢谢。

【问题讨论】:

我试图做这样的事情:super(PostTweetSet, self).save(*args, **kwargs) self.periodic_task = TaskScheduler.create( 'tweets.tasks.post_next_tweet', self.interval.period, self.interval.every, args="[" + '"%s"' % str(self.pk) + "]") kwargs.update('update_fields': ['periodic_tweet']) super(PostTweetSet, self).save(*args, **kwargs) 但得到错误 - ValueError: Cannot force both insert and updating in model saving. 【参考方案1】:

我会用保存后的信号来做。

如果你做不到或者那没有吸引力,你可以把你的需求考虑成两条路径:

如果没有主键,需要先保存并获取pk 如果你已经知道主键,你可以创建你的周期性任务,然后调用 super

类似(伪代码):

def save(...):
    if self.pk is None:
        super(...)
        self.save(...)    # Call ourselves -- but this time, we'll have a primary key!
    else:
        ... create your periodic task
        super(...)

【讨论】:

【参考方案2】:

通过在模型中的override save method 中提供一些条件,我已经达到了相同的要求。

在问题中,要求是在保存模型后更新periodic_task字段,所以这是我遵循的sudo代码结构:

class MyModel(models.Model):
    periodic_task = models.OneToOneField(PeriodicTask, null=True, blank=True)
    def save(self):
        super(Asset, self).save()
        if not self.periodic_task: # Checking if the section is not updated.
            self.periodic_task = #code to update the field.
            self.save() #again call the save.

【讨论】:

【参考方案3】:

您可能希望在 post_save 信号中执行此操作。

【讨论】:

【参考方案4】:

您可以在 save() 覆盖结束时调用 super()。这是使用slugify() 方法的示例。 slugify 方法通过将所有字符转换为小写并将空格转换为破折号,将字符串转换为 slug。代码如下:

from django.template.defaultfilters import slugify

def save(self, *args, **kwargs):
    self.slug = slugify(self.title)
    super(Product, self).save(*args, **kwargs)

【讨论】:

我不相信这能让你知道实例的主键。【参考方案5】:

如果您不想使用信号,为什么不存储super() 的结果并返回它而不是调用本身?

def save(self, *args, **kwargs):
    run_task = False
    if not self.pk:
        run_task = True

    result = super().save(*args, **kwargs)

    if run_task:
        TaskScheduler.create(...)

    return result

【讨论】:

以上是关于Django,调用 super() 后如何在 save() 方法中更新模型?的主要内容,如果未能解决你的问题,请参考以下文章

Python/Django 避免保存内联

android视图之间的时间延迟

Sybase数据库sa密码丢失后应当如何找回

在django中渲染模板后如何在我的视图中调用一些逻辑

如何调用super

django项目后台权限管理功能。