How do I query objects of all children of a node with Django mptt?
Asked Answered
M

3

13

I am trying to get the objects of all the children of a given node on Django with django-mppt

I have a model designed as shown below, the classes/categories (node) with the same indent level defines siblings, inner indents are children. The objects tagged with a category are shown just below the category (node). The objects start with a - symbol. The numbers along the classes/categories (nodes) are the ids.

all the nodes are the instances of Category class with the id given.

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

I can get the query sets of a specific node this way,

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


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

How do I query with pk=1, pk=2, pk=3 or pk=4 to get all the child objects?

example,

the query for pk=2 query must return

[Billie, Tre, Mike, Patrik, Pete, Andy]
Mccrary answered 26/10, 2015 at 21:29 Comment(5)
your example seems related to node with pk=2, or I missed something ?Engedus
@Engedus yeah thats a typo, have fixed.Mccrary
@Ivan the levels will be differentMccrary
The query Category.objects.get(pk=4).product_set.all() should return [<Category: Patrik >, <Category: Pete >, <Category: Andy >] or I' don't understand your example?Hovercraft
@AndréAraújo some mess ups there, have updated the questionMccrary
P
31
Category.objects.get(pk=2).get_descendants(include_self=True)

This will get you all category descendants including self.

Assuming that your Product model has a Foreign key category, you can use:

Product.objects.filter(category__in=Category.objects.get(pk=2)\
    .get_descendants(include_self=True))
Puffery answered 3/11, 2015 at 11:41 Comment(2)
Descendants from what field though? How does Category only know to fetch descendants from Product? What if Category also has descendants from Widget? Does it fetch from both of these, or do you have to specify which one to fetch from?Rondi
Where does this get_descendants came from?Peck
C
4

Category.objects.get(pk=1).get_leafnodes() is what you're looking for.

(django-mptt docs)

Contrarious answered 29/10, 2015 at 3:25 Comment(0)
L
3

Django mptt provides two methods to retrieve children.

From the docs

MPTTModel.get_children(*args, **kwargs)

Returns a QuerySet containing the immediate children of this model >instance, in tree order.

The benefit of using this method over the reverse relation provided by the ORM to the instance’s children is that a database query can be avoided in the case where the instance is a leaf node (it has no children).

If called from a template where the tree has been walked by the cache_tree_children filter, no database query is required.

And

MPTTModel.get_leafnodes(*args, **kwargs)

Creates a QuerySet containing leafnodes of this model instance, in tree order.

If include_self is True, the QuerySet will also include this model instance (if it is a leaf node)

I'm not sure how your models are set up but I'm not sure why you use mptt here. You are using Category/Product but it seems to be student or people and work groups.

Maybe you can define EstablishmentLevel, Level|, StudentGroup, Student models and instead of using mptt function query something like:

Student.objects.filter(studentgroup__level__pk=1)

See the Django doc

Hope that helped

Luciferin answered 2/11, 2015 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.