Python/Django中的父子层级/嵌套集合

3 投票
2 回答
1956 浏览
提问于 2025-04-16 00:35

我正在使用Django/Python,不过这里用伪代码也可以。

我在处理一些已经存在的模型,其中有Employee(员工),每个员工都有一个Supervisor(主管),这实际上是指向另一个Employee的外键关系。

员工和主管的层级关系大致是这样的:

每个员工只有一个主管。这个主管可能会有一个或多个“下属”员工,同时他/她自己也有主管。获取我的“上级”应该返回我的主管,他的主管,她的主管,等等,直到找到一个没有主管的员工为止。

在不疯狂安装新应用来管理这些关系的情况下,因为这是一个已有的代码基础和项目,我想知道实现以下功能的“pythonic”或正确方法是什么:

def get_upline(employee): 
    # Get a flat list of Employee objects that are
    # 'supervisors' to eachother, starting with 
    # the given Employee. 
    pass


def get_downline(employee):
    # Starting with the given Employee, find and 
    # return a flat list of all other Employees 
    # that are "below". 
    pass

我觉得用Django的ORM可能有比较简单的方法来做到这一点,但如果没有,我也欢迎任何建议。

我还没有仔细研究Django-MPTT,但如果我能保持模型不变,同时获得更多功能,那就值得尝试。

2 个回答

0

关系型数据库不太适合处理这种图形查询,所以你唯一的选择就是进行很多次查询。下面是一个递归的实现方式:

def get_upline(employee):
    if self.supervisor:
        return [employee] + self.supervisor.get_upline()
    else:
        return [employee]

def get_download(employee):
    l = [employee]
    for minion in self.minion_set.all():
        l.extend(minion.get_download())
    return l
2

你不需要修改你的模型就可以使用django-mptt;只需要在你的模型中创建一个parent字段,django-mptt会自动为你生成其他需要的属性,当你注册你的模型时:mptt.register(MyModel)

不过,如果你只需要“上级”层级结构,那就不需要使用嵌套集合。更大的性能问题在于反向操作,比如收集子节点或叶子节点等,这就需要使用嵌套集合模型了!

撰写回答