如何使用Django mptt查询节点的所有子节点的对象?

时间:2015-10-26 21:29:34

标签: python django tree-traversal django-mptt mptt

我试图用django-mppt

获取Django上给定节点的所有子节点的对象

我有一个如下所示设计的模型,具有相同缩进级别的类/类别(节点)定义了兄弟,内部缩进是子。标有类别的对象显示在类别(节点)下方。对象以-符号开头。类/类别(节点)中的数字是ids。

所有节点都是Category类的实例,并给出了id

high school (1)
    class 8 (2)
        division a (3)
            -Billie
            -Tre
            -Mike

        division b (4)
            -Patrik
            -Pete
            -Andy
    class 9 (3)
        division a (8)
            -Mark
            -Tom
            -Travis

        division b (5)
            -Gerard
            -Frank
            -Mikey

    class 10  (4)
        division a (6)
            -Hayley
            -Jeremy
            -Taylor

        division b (7)
            -Steven
            -Slash
            -Izzy

我可以通过这种方式获取特定节点的查询集,

>>> Category.objects.get(pk=7).product_set.all()
[Steven, Slash, Izzy]


>>> Category.objects.get(pk=4).product_set.all()
[Mark, Tom, Travis]

如何查询pk=1pk=2pk=3pk=4以获取所有子对象?

例如,

pk=2查询的查询必须返回

[Billie, Tre, Mike, Patrik, Pete, Andy]

3 个答案:

答案 0 :(得分:18)

Category.objects.get(pk=2).get_descendants(include_self=True)

这将为您提供包括自我在内的所有类别后代。

假设您的产品型号具有外键类别,您可以使用:

Product.objects.filter(category__in=Category.objects.get(pk=2)\
    .get_descendants(include_self=True))

答案 1 :(得分:3)

Django mptt提供了两种检索子项的方法。

来自docs

  

MPTTModel.get_children(* args,** kwargs)

     

以树的顺序返回一个QuerySet,其中包含此模型>实例的直接子项。

     

使用此方法优于ORM提供给实例子节点的反向关系的好处是,在实例是叶节点(没有子节点)的情况下,可以避免数据库查询。

     

如果从已通过cache_tree_children过滤器遍历树的模板调用,则不需要数据库查询。

  

MPTTModel.get_leafnodes(* args,** kwargs)

     

按树顺序创建包含此模型实例的叶节点的QuerySet。

     

如果include_self为True,则QuerySet还将包含此模型实例(如果它是叶节点)

我不确定你的模型是如何设置的,但我不确定你为什么在这里使用mptt。您正在使用类别/产品,但它似乎是学生,人员和工作组。

也许您可以定义EstablishmentLevelLevel|StudentGroupStudent模型,而不是使用mptt函数查询:

Student.objects.filter(studentgroup__level__pk=1)

请参阅 Django doc

希望有所帮助

答案 2 :(得分:1)

Category.objects.get(pk=1).get_leafnodes()正是您要找的。

django-mptt docs