Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Create all foreign key objects upon creating a parent object

Consider the following code, in which I have one parent, and all the child models related to the parent by ForeignKey relationship. Each child may have their own child, making the whole family look like a tree structure.

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')

Upon making an object for Parent, I want to create all the child objects.

I guess I can create all the child objects like this:

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)
...

But you know, this doesn't look very good. Is there any built-in Django method that handles this kind of parent-child object creation in chain?

like image 513
Eric Kim Avatar asked Sep 05 '25 03:09

Eric Kim


2 Answers

Override save() method of model as,

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')
like image 119
JPG Avatar answered Sep 07 '25 21:09

JPG


In Django, you would usually use Signals for this. A standard situation is when you create a new User and want their Profile to be automatically created.

Example from 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)

So in your case, you can use post_save to connect the Parent with a function that creates all the child items.

like image 33
C14L Avatar answered Sep 07 '25 20:09

C14L