1

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)

従業員は、1 つ以上の組織単位に接続できます。

class OUEmployee(models.Model):
    user = models.ForeignKey(User, related_name='employers', on_delete=models.CASCADE)
    orgunit = models.ForeignKey(OrgUnit, on_delete=models.CASCADE)

..管理者は複数の組織単位を管理できます。

class OUManager(models.Model):
    user = models.ForeignKey(User, related_name='+', on_delete=models.CASCADE)
    manages = models.ManyToManyField(OrgUnit, blank=True)

上のメソッドとして実装された、特定のマネージャーの部下であるすべての従業員OUManagerのクエリセットが必要ですが、現在の実装では、子組織ではなく、マネージャーが管理する OrgUnit に直接接続されている従業員のみが提供されます。

    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 のみを返します)。

1 つの 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)

直接またはモデルを変更することによって、1 つの db-hit でこれを達成する直接的な方法はありますか?

4

0 に答える 0