如何在保存django模型期间避免递归

时间:2015-05-21 11:33:17

标签: python django django-models

我有一个模型Entry

现在每当为任何日期创建Entry时。然后在保存之前我需要进行检查并添加更多条目,例如,例如。

Entry 1 - red

现在假设任何entry.color = red然后我还需要再创建两个条目,如

Entry 2 - red2
Entry 3 - red3

现在我把它放在pre_save信号

@receiver(pre_save, sender=Entry)
def new_entries(sender, instance, *args, **kwargs):
     pass

现在我的问题是无限递归结束,因为我想保存的那些新条目也发送pre_save信号,这个循环永远不会完成。

在哪里放置这个逻辑以便不发生递归?

4 个答案:

答案 0 :(得分:3)

我会用另一个保存参数来解决它,而不是附加到pre_save:

import django.db.models
class Entry(models.Model):
    color=models.CharField(max_length="50")
    def save(self,create_children=True,**kwargs):
        if create_children and not self.pk:
            result = super(Entry,self).save(**kwargs)
            Entry(color=self.color).save(create_children=False)
            Entry(color=self.color).save(create_children=False)
        else:
            result = super(Entry,self).save(**kwargs)
        return result

您希望确保在实际构建子项之前调用super(Entry,self).save(**kwargs),否则当super()引发IntegrityError

时,您将使用模型使数据库混乱

答案 1 :(得分:0)

我认为你应该有2个独立的模型。你的父母' Entry可以是主Entry模型的子类,这样只有IT才能创建新的子条目。

class Entry(models.Model):
    pass
    # whatever you need here

class ParentEntry(Entry):

    @receiver(pre_save, sender=ParentEntry)
    def new_entries(sender, instance, *args, **kwargs):
        pass

添加另一个模型的原因是这些模型实际上做了2个不同的事情,1创建时创建更多,1创建更多。为清楚起见,我会防止1个模型的构造函数可以做2个不同的事情。

答案 2 :(得分:0)

这样的事情应该有效:

class Entry(model.Model):

   def save(self, color, create_more=True, *args, **kwargs):
       if self.pk is None:  # this is a new Entry              
           if create_more:
               new_color = '%s2' % color
               Entry(color=new_color, create_more=False).save()

       super(Entry, self).save(...)
我怀疑有更好的方法,但我不能不知道你想要做什么的更多细节。

答案 3 :(得分:0)

在 django 中的 post_save singal 中,为了避免递归,“如果创建”检查是必需的

from django.dispatch import receiver
from django.db.models.signals import post_save
@receiver(post_save, sender=DemoModel)
def _post_save_receiver(sender,instance,created, **kwargs):
if created:            
    print('hi..')
    instance.save()