我有一个模型,看起来像:
class StaffMember(models.Model):
id = models.OneToOneField(to=User, unique=True, primary_key=True, related_name='staff_member')
supervisor = models.ForeignKey(to='self', null=True, blank=True, related_name='team_members')
我当前的团队层次结构的设计方式是让我们说一个管理员(谁是最重要的层次结构)。现在,让我们说3个人(A,B,C)向管理员报告,A,B和C中的每个人都有他们自己的团队向他们报告,等等。
对于任何员工,我想找到所有团队成员(沸腾到最底层次的层次结构)。 我目前获得一个人所有团队成员的方法就像:
def get_team(self):
team = [self]
for c in self.team_members.all():
team += list(c.get_team())
if len(team) > 2000:
break
return team
我通过以下方式获得会员的团队成员:
member = StaffMember.objects.get(pk=72)
team = member.get_team()
但显然,这导致了很多db调用,我的API最终会超时。什么可以更有效的方式来获取团队的所有成员?
答案 0 :(得分:9)
如果您正在使用支持递归公用表表达式的数据库(例如PostgreSQL),那么这正是用例。
team = StaffMember.objects.raw('''
WITH RECURSIVE team(id, supervisor) AS (
SELECT id, supervisor
FROM staff_member
WHERE id = 42
UNION ALL
SELECT sm.id, sm.supervisor
FROM staff_member AS sm, team AS t
WHERE sm.id = t.supervisor
)
SELECT * FROM team
''')
参考文献:
Raw SQL queries in Django
Recursive Common Table Expressions in PostgreSQL
答案 1 :(得分:1)
我找到了问题的解决方案。递归解决方案接受节点,转到它的第一个子节点并深入到层次结构的底部。然后再次回到第二个孩子(如果存在),然后再次下降到底部。简而言之,它逐个探索所有节点并将所有成员附加到数组中。我提出的解决方案,逐层提取成员。
member = StaffMember.objects.get(id__id=user_id)
new_list = [member]
new_list = get_final_team(new_list)
def get_final_team(qs):
team = []
staffmembers = StaffMember.objects.filter(supervisor__in=qs)
team += staffmembers
if staffmembers:
interim_team_qs = get_final_team(staffmembers)
for qs in interim_team_qs:
team.append(qs)
else:
team = [qs]
return team
此方法所需的db调用数是在我们想要找到的团队成员下面的层数(层次结构)。