Django,如何在调用super()后在save()方法中更新模型?
我遇到了这样的问题。比如,我在我的模型类里有一个字段:
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()
方法之后被赋值的。我这样做是因为我需要有一个主键字段(我在 TaskScheduler
的创建方法中用到它)。另一方面,我需要在设置这个新字段后更新数据库表。如果我再次调用 super()
,就会出现关于重复 ID 的错误。那么,我该怎么做才能让这个工作正常?或者我需要完全重新考虑我的做法吗?谢谢。
5 个回答
0
如果你不想使用信号,那为什么不把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
0
你可以在自己重写的 save()
方法的最后调用 super()
。下面是一个使用 slugify()
方法的例子。这个 slugify 方法的作用是把一个字符串转换成一个“短链接”,它会把所有字符变成小写,并把空格替换成短横线。以下是代码:
from django.template.defaultfilters import slugify
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Product, self).save(*args, **kwargs)
2
你可能想在 post_save
信号中做这个事情。
4
通过在模型中的 override save method
提供一些条件,我达到了相同的需求。
在这个问题中,需求是要在保存模型后更新 periodic_task
字段,所以我遵循了以下的伪代码结构:
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.
6
我会用一个保存后的信号来处理这个问题。
如果你不能这样做,或者这样做不太合适,你可以把你的需求想成两种情况:
- 如果你还没有主键,你需要先保存数据,然后获取主键。
- 如果你已经知道主键了,你可以创建一个定期任务,然后调用父类的方法。
所以可以写成类似这样的(伪代码):
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(...)