4

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?

2
  • Well personally I wonder why you want to construct all those objects in the first place. What if some models require extra columns (without a default value), then what to fill in? Commented Aug 10, 2018 at 7:33
  • @WillemVanOnsem This for data management system. When user clicks a parent object, it will redirect to a page where a user can edit all the child fields for that parent object. Initially all the child fields will be blank, and the user can fill the fields if its blank, else, user can update field values. But to do that, child objects needs to be present in the DB, so that the user can edit those child fields Commented Aug 10, 2018 at 7:39

3 Answers 3

8

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')
Sign up to request clarification or add additional context in comments.

Comments

5

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.

Comments

1

I would recommend using something like django-mptt to deal with trees in Django.

If you really want to keep doing things manually, see @C14L answer. Or just put your code in a Parent method and then call something like parent.create_children().

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.