1

Given this model:

class Role(models.Model):
    title = models.CharField(max_length=255, verbose_name='Role Title')
    parents = models.ManyToManyField("self", symmetrical=False)
    skills = models.ManyToManyField(Skill)

What is the most efficient way to get a list of all the 'Skill' objects related to this 'Role' object, and its parents, recursively?

For example, if the Role object in question is 'Manager', it will inherit skills from 'Team Leader', which inherits skills from 'Team Member' etc.

Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
Phear46
  • 15
  • 6

2 Answers2

1

I think you'd have to get them one lot at a time.

    skills = list(roll.skills.all())
    for parent in parents:
        skills.extend(list(parent.skills.all())

Or set instead of list if you just want a unique set of skills.

You could of course write this as a modelmanager method, so it was easily available when needed.

michjnich
  • 2,796
  • 3
  • 15
  • 31
1

Try to use a helper function, like the following:

class Role(models.Model):
    title = models.CharField(max_length=255, verbose_name='Role Title')
    parents = models.ManyToManyField("self", symmetrical=False)
    skills = models.ManyToManyField(Skill)

    def get_all_skills(self):
        """
        Recursively retrieve all skills of the role and its parents
        """
        all_skills = set(self.skills.all())
        for parent in self.parents.all():
            all_skills.update(parent.get_all_skills())
        return all_skills

Then use this method to get all the skills of a role and its parents:

role = Role.objects.get(title='Manager')
all_skills = role.get_all_skills()

This solution avoids the need to iterate over the parents multiple times, making it more efficient. It also provides a convenient method to get all the skills of a role and its parents, which can be called wherever needed.

Sunderam Dubey
  • 1
  • 11
  • 20
  • 40