get_descendants for a list of nodes

1,199 views
Skip to first unread message

DK

unread,
Apr 19, 2011, 5:06:56 PM4/19/11
to django-mptt-dev
Hi,

I am trying to get all descendants(include_self=True) not for one
Node, but for a list (a QuerySet) of Nodes. This should be one SQL
query.

Example (that actually is not working:)

some_nodes = Nodes.objects.filter( ...some_condition... )
some_nodes.get_descendants(include_self=True) #hopefully I would like
to have all possible Nodes starting from every node of "some_nodes"

The only idea I have right now is to iterate through some_nodes and
run get_descendants() for every node - but this is terrible solution
(plenty of SQL queries).

If there is no clean way to do it via ORM can you provide me a custom
SQL to run instead? Here you can make assumption that I have list of
Node's pk.

Thank you in advance,
DK

DK

unread,
Apr 19, 2011, 5:19:23 PM4/19/11
to django-mptt-dev
EDIT: If that could help - all of my "some_nodes" are placed in this
same parent directory and have this same "level" in the tree.

Craig de Stigter

unread,
Apr 19, 2011, 5:41:33 PM4/19/11
to django-...@googlegroups.com
DK

That's not in django-mptt, but it's easy enough to implement using Q objects. This takes 2 queries (one to evaluate your some_nodes queryset, and another to fetch descendants.)

Something like this:

from django.db.models import Q
import operator
def get_queryset_descendants(nodes, include_self=False):
    if not nodes:
        return Node.tree.none()
    filters = []
    for n in nodes:
        lft, rght = n.lft, n.rght
        if include_self:
            lft -=1
            rght += 1
        filters.append(Q(tree_id=n.tree_id, lft__gt=n.lft, rght__gt=n.rght))
    q = reduce(operator.or_, filters)
    return Node.tree.filter(q)

Also see this thread for a similar question (with a similar solution): http://groups.google.com/group/django-mptt-dev/browse_thread/thread/92e3d58c2543c81c/89492d7a302a023

HTH

Craig

Craig de Stigter

unread,
Apr 20, 2011, 5:11:37 AM4/20/11
to django-...@googlegroups.com
Correction: that should be:
filters.append(Q(tree_id=n.tree_id, lft__gt=n.lft, rght__lt=n.rght))

DK

unread,
Apr 20, 2011, 6:51:55 AM4/20/11
to django-mptt-dev
Great thanks for help.

Actually it works, but with one exception - include_self has no effect
on result. Anyway I will need to learn the internal way mptt stores
tree info, but in meanwhile could you look at this example and give me
a hint:

Example tree:
T1
---T1.1
---T1.2
T2
T3
---T3.3
------T3.3.3

my some_nodes = [<Folder: T1>, <Folder: T2>, <Folder: T3>]

regarding the include_self True/False i get response:

[<Folder: T1.1>, <Folder: T1.2>, <Folder: T3.3>, <Folder: T3.3.3>]

I would like to get for include_self=True this response:

[<Folder: T1>, <Folder: T1.1>, <Folder: T1.2>, <Folder: T2>, <Folder:
T3>, <Folder: T3.3>, <Folder: T3.3.3>]

DK

unread,
Apr 20, 2011, 7:14:58 AM4/20/11
to django-mptt-dev
Correction:

filters.append(Q(tree_id=n.tree_id, lft__gt=lft, rght__lt=rght))

(removed n. )



On Apr 20, 11:11 am, Craig de Stigter <craig...@gmail.com> wrote:
> Correction: that should be:
>
> > filters.append(Q(tree_id=n.tree_id, lft__gt=n.lft, rght*__lt*=n.rght))
>
> On Wed, Apr 20, 2011 at 9:41 AM, Craig de Stigter <craig...@gmail.com>wrote:
>
>
>
>
>
>
>
> > DK
>
> > That's not in django-mptt, but it's easy enough to implement using Q
> > objects. This takes 2 queries (one to evaluate your some_nodes queryset, and
> > another to fetch descendants.)
>
> > Something like this:
>
> > from django.db.models import Q
> > import operator
> > def get_queryset_descendants(nodes, include_self=False):
> >     if not nodes:
> >         return Node.tree.none()
> >     filters = []
> >     for n in nodes:
> >         lft, rght = n.lft, n.rght
> >         if include_self:
> >             lft -=1
> >             rght += 1
> >         filters.append(Q(tree_id=n.tree_id, lft__gt=n.lft,
> > rght__gt=n.rght))
> >     q = reduce(operator.or_, filters)
> >     return Node.tree.filter(q)
>
> > Also see this thread for a similar question (with a similar solution):
> >http://groups.google.com/group/django-mptt-dev/browse_thread/thread/9...
>
> > HTH
>
> > Craig
Reply all
Reply to author
Forward
0 new messages