我有组织单位(OrgUnit
)的 Django 模型,可以是公司、部门、团队等,即。它是一个树形结构:
from django.db import models
from django.contrib.auth.models import User
from treebeard.mp_tree import MP_Node, MP_NodeManager
class OrgUnit(MP_Node): # MP_Node adds a .path field
name = models.CharField(max_length=120)
员工可以连接到一个或多个组织单元:
class OUEmployee(models.Model):
user = models.ForeignKey(User, related_name='employers', on_delete=models.CASCADE)
orgunit = models.ForeignKey(OrgUnit, on_delete=models.CASCADE)
..and manager 可以管理多个 OrgUnits:
class OUManager(models.Model):
user = models.ForeignKey(User, related_name='+', on_delete=models.CASCADE)
manages = models.ManyToManyField(OrgUnit, blank=True)
现在我想要一个包含给定经理下属的所有员工的查询集,实现为 on 上的方法OUManager
,但是,当前实现仅将员工直接连接到经理管理的组织单元,而不是子组织单元:
def subordinates(self):
return OUEmployee.objects.filter(
orgunit__in=self.manages.all()
)
即给出:
root = OrgUnit.add_root(name='Acme Corporation')
dept = root.add_child(name='Dept. of Anvils and Tunnels')
team = dept.add_child(name='QA')
emp1 = OUEmployee(user=User.objects.create_user(username='emp1'),
orgunit=team)
emp2 = OUEmployee(user=User.objects.create_user(username='emp2'),
orgunit=dept)
mngr = OUManager(user=User.objects.create_user(username='manager'))
mngr.manages.add(dept)
我想
employees = mngr.subordinates()
返回带有 emp1 和 emp2 的查询集(上述实现仅返回 emp2)。
有没有办法写下属,所以它只需要一个 db-hit?
到目前为止,我想出的最佳方法需要首先实现所有路径:
from django.db.models.query_utils import Q
...
def subordinates(self):
paths = Q()
for p in self.manages.all().values_list('path', flat=True):
paths |= Q(orgunit__path__startswith=p)
return OUEmployee.objects.filter(paths)
是否有任何直接的方法可以在一个 db-hit 中直接或通过更改模型来实现这一目标?