Django ORM和pre_init信号

时间:2017-02-27 02:26:29

标签: python django

我有一个有两个孩子的课

class MyChild1(models.Model):
    attr1 = models.CharField(default='default value')

class MyChild2(models.Model):
    pass

class MyParent(models.Model):
    child1 = models.ForeignKey(Child1)
    child2 = models.ForeignKey(Child2)

在我的包中,我需要attr1的值 - 为了确保它存在,我用一个信号初始化父:

def init_my_parent(sender, *args, **kwargs):
    child1 = MyChild1()
    child2 = MyChild2()

signals.pre_init.connect(init_my_parent,sender=MyParent)

这似乎可以正常工作,以确保始终实例化child1和child2。但是,即使我手动设置child1和child2(my_parent.child1 = child1等),child1_idchild2_id也没有设置,db会抛出错误

django.db.utils.IntegrityError: NOT NULL constraint failed: myparent.child1

我想知道造成这种行为的原因是什么?以某种方式连接该信号导致问题,但我不知道为什么。这是一个类似于我正在使用的脚本:

c1 = MyChild1()
c2 = MyChild2()
c1.save()
c2.save()
p = MyParent()
p.child1 = c1
p.child2 = c2
p.save()
# Error thrown

init_my_parent中设置的两个值都应该在上面覆盖,因此一切都应该像信号函数不存在一样工作?

2 个答案:

答案 0 :(得分:1)

问题是pre_init信号不带实例参数,因此您正在编辑实际的类(sender)。尝试使用带有post_init参数的instance信号,以便您可以更改它:

def init_my_parent(sender, instance, *args, **kwargs):
    if not hasattr(instance,'child1'): 
        instance.child1 = MyChild1()
        instance.child1.save()
    if not hasattr(instance,'child2'): 
        instance.child2 = MyChild2()
        instance.child2.save()

signals.post_init.connect(init_my_parent, sender=MyParent)

答案 1 :(得分:0)

class MyChild1(models.Model):
    attr1 = models.CharField(default='default value', max_length=100)

class MyChild2(models.Model):
    pass

class MyParent(models.Model):
    child1 = models.ForeignKey(MyChild1)
    child2 = models.ForeignKey(MyChild2

使用class而不是def,然后就可以了。