Django-在创建父对象时创建所有外键对象

时间:2018-08-10 07:26:22

标签: django django-models

请考虑以下代码,其中我有一个父级,并且所有子级模型都通过ForeignKey关系与父级相关。每个孩子可能都有自己的孩子,整个家庭看起来像一棵树。

class Parent(models.Model):
    field = models.CharField(max_length=100, primary_key=True)

class Child_1(models.Model):
    parent = models.ForeignKey(Parent, models.CASCADE, related_name='aa')

class Child_2(models.Model):
    parent = models.ForeignKey(Parent, models.CASCADE, related_name='aa')

class Child_1_Child_1(models.Model):
    parent = models.ForeignKey(Child_1, models.CASCADE, related_name='aa')

class Child_1_Child_2(models.Model):
    parent = models.ForeignKey(Child_1, models.CASCADE, related_name='aa')

在为Parent创建对象时,我想创建所有子对象。

我想我可以像这样创建所有子对象:

parent = Parent.objects.create(**kwargs)
child_1 = Child_1.objects.create(parent=parent)
child_2 = Child_2.objects.create(parent=parent)
child_1_child_1 = Child_1_Child_1.objects.create(parent=child_1)
child_1_child_2 = Child_1_Child_2.objects.create(parent=child_1)
...

但是您知道,这看起来不太好。是否有内置的Django方法可处理链中此类父子对象的创建?

3 个答案:

答案 0 :(得分:3)

在Django中,通常会使用Signals。一种标准情况是,当您创建新的User并希望自动创建其Profile时。

来自this answer的示例:

def create_profile(sender, **kwargs):
    user = kwargs["instance"]
    if kwargs["created"]:
        up = UserProfile(user=user, stuff=1, thing=2)
        up.save()

post_save.connect(create_profile, sender=User)

因此,在您的情况下,您可以使用post_saveParent与创建所有子项的功能连接。

答案 1 :(得分:2)

将模型的 save() 方法覆盖为

class Parent(models.Model):
    field = models.CharField(max_length=100, primary_key=True)

    def save(self, *args, **kwargs):
        is_new = not self.pk
        super().save(*args, **kwargs)
        if is_new:
            Child_1.objects.create(parent=self)
            Child_2.objects.create(parent=self)


class Child_1(models.Model):
    parent = models.ForeignKey(Parent, models.CASCADE, related_name='aa')

    def save(self, *args, **kwargs):
        is_new = not self.pk
        super().save(*args, **kwargs)
        if is_new:
            Child_1_Child_1.objects.create(parent=self)


class Child_2(models.Model):
    parent = models.ForeignKey(Parent, models.CASCADE, related_name='aa')

    def save(self, *args, **kwargs):
        is_new = not self.pk
        super().save(*args, **kwargs)
        if is_new:
            Child_1_Child_2.objects.create(parent=self)


class Child_1_Child_1(models.Model):
    parent = models.ForeignKey(Child_1, models.CASCADE, related_name='aa')


class Child_1_Child_2(models.Model):
    parent = models.ForeignKey(Child_1, models.CASCADE, related_name='aa')

答案 2 :(得分:1)

我建议使用django-mptt之类的东西来处理Django中的树。

如果您真的想继续手动操作,请参阅@ C14L答案。或者只是将您的代码放入Parent方法中,然后调用类似parent.create_children()的代码。