recursively collect children in python/django

  • Last Update :
  • Techknowledgy :

This implementation should work

def get_family_tree(person):
   ""
" return a family tree for a Person object "
""

children = person.children.all()

if not children:
   # this person has no children, recursion ends here
return {
   'name': person.name,
   'children': []
}

# this person has children, get every child 's family tree
return {
   'name': person.name,
   'children': [get_family_tree(child) for child in children],
}

One way to think about recursion is to start off with the base case - i.e. where the recursion will end. In your case, we know how the family tree looks like if a person has no children:

{
   'name': 'FirstPerson',
   'children': [],
}

In your case, it would be parents with children, but no grand children. We know how each child's family tree should look - it's just the base case! This leads us to the solution where we return the parent's name, and a list of each child's family tree. Leading to something like:

{
    'name': FirstPerson,
    'children': [<each element is a child's family tree>]
}

You can accomplish this by writing a custom method on the model. The way you call it would look something like this:

first_person = Person.objects.filter(name = 'FirstPerson')
family_tree = first_person.getChildren()

Where getChildren would look something like this:

def getChildren(self):
   children = Person.objects.filter(parent = self)
#
return children
# OR just format the data so it 's returned in the format you like
# or you can
return them as Person objects and have another method
# to transform each object in the format you like(e.g Person.asJSON())

You can then add this method to the model to get the objects (or look into the docs I have provided to get the children instead of the parents/ancestors):

def get_category_and_parents(self):
   ""
" Recursively retrieves parent categories (including self) using MPTT "
""
full_category = self.category.get_ancestors(include_self = True)
return full_category

Suggestion : 2

One way to think about recursion is to start off with the base case - i.e. where the recursion will end. In your case, we know how the family tree looks like if a person has no children:,In your case, it would be parents with children, but no grand children. We know how each child's family tree should look - it's just the base case! This leads us to the solution where we return the parent's name, and a list of each child's family tree. Leading to something like:,This implementation should work,Note that this will take as many database calls as there are persons. You can try to fetch all the data into memory if you run into performance issues.

This implementation should work

def get_family_tree(person):
   ""
" return a family tree for a Person object "
""

children = person.children.all()

if not children:
   # this person has no children, recursion ends here
return {
   'name': person.name,
   'children': []
}

# this person has children, get every child 's family tree
return {
   'name': person.name,
   'children': [get_family_tree(child) for child in children],
}

One way to think about recursion is to start off with the base case - i.e. where the recursion will end. In your case, we know how the family tree looks like if a person has no children:

{
   'name': 'FirstPerson',
   'children': [],
}

In your case, it would be parents with children, but no grand children. We know how each child's family tree should look - it's just the base case! This leads us to the solution where we return the parent's name, and a list of each child's family tree. Leading to something like:

{
    'name': FirstPerson,
    'children': [<each element is a child's family tree>]
}

You can accomplish this by writing a custom method on the model. The way you call it would look something like this:

first_person = Person.objects.filter(name = 'FirstPerson')
family_tree = first_person.getChildren()

Where getChildren would look something like this:

def getChildren(self):
   children = Person.objects.filter(parent = self)
#
return children
# OR just format the data so it 's returned in the format you like
# or you can
return them as Person objects and have another method
# to transform each object in the format you like(e.g Person.asJSON())

You can then add this method to the model to get the objects (or look into the docs I have provided to get the children instead of the parents/ancestors):

def get_category_and_parents(self):
   ""
" Recursively retrieves parent categories (including self) using MPTT "
""
full_category = self.category.get_ancestors(include_self = True)
return full_category

Suggestion : 3

You can also create recursive relationships (an object with a many-to-one relationship to itself) and relationships to models not yet defined; see the model field reference for details.,As with ForeignKey, you can also create recursive relationships (an object with a many-to-many relationship to itself) and relationships to models not yet defined.,Each model is a Python class that subclasses django.db.models.Model.,To define a many-to-one relationship, use django.db.models.ForeignKey. You use it just like any other Field type: by including it as a class attribute of your model.

from django.db
import models

class Person(models.Model):
   first_name = models.CharField(max_length = 30)
last_name = models.CharField(max_length = 30)
CREATE TABLE myapp_person(
   "id"
   serial NOT NULL PRIMARY KEY,
   "first_name"
   varchar(30) NOT NULL,
   "last_name"
   varchar(30) NOT NULL
);
INSTALLED_APPS = [
   #...
   'myapp',
   #...
]
from django.db
import models

class Musician(models.Model):
   first_name = models.CharField(max_length = 50)
last_name = models.CharField(max_length = 50)
instrument = models.CharField(max_length = 100)

class Album(models.Model):
   artist = models.ForeignKey(Musician, on_delete = models.CASCADE)
name = models.CharField(max_length = 100)
release_date = models.DateField()
num_stars = models.IntegerField()
YEAR_IN_SCHOOL_CHOICES = [
   ('FR', 'Freshman'),
   ('SO', 'Sophomore'),
   ('JR', 'Junior'),
   ('SR', 'Senior'),
   ('GR', 'Graduate'),
]
from django.db
import models

class Person(models.Model):
   SHIRT_SIZES = (
      ('S', 'Small'),
      ('M', 'Medium'),
      ('L', 'Large'),
   )
name = models.CharField(max_length = 60)
shirt_size = models.CharField(max_length = 1, choices = SHIRT_SIZES)