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 = Node.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 Django ORM can you provide me a custom SQL to run instead? Here you can make assumption that I have a list of Node's pk.
EDIT: If that could help - all of my "some_nodes" are placed in the same parent directory and have the same "level" in the tree.
All descendants of root nodes will be given the same tree id as their root node. The name of a field which contains the (zero-based) level at which an item sits in the tree, which should be a PositiveIntegerField . Defaults to 'level'. For example, root nodes would have a level of 0 and their immediate children would have have a level of 1.
In cases of insertion or other updates, where django-mptt will need to re-order the tree you will most likely be left with dangling references. Please see order_insertion_by gotcha for details.
A tree where nodes can have multiple parents isn’t really a tree at all. The default manager for an MPTTModel is a TreeManager. Any QuerySet created with this manager will be ordered based on the tree structure, with root nodes appearing in tree id order and their descendants being ordered in a depth-first fashion.
In cases of insertion or other updates, where django-mptt will need to re-order the tree you will most likely be left with dangling references. Please see order_insertion_by gotcha for details. The preferred way to do model registration in django-mptt is by subclassing MPTTModel.
Later versions of mptt already have this function built into the object manager. So the solution to this is just as follows:
Node.objects.get_queryset_descendants(my_queryset, include_self=False)
Great thanks to Craig de Stigter answered my question on django-mptt-dev group, in case anybody need it I am kindly reposting his solution from http://groups.google.com/group/django-mptt-dev/browse_thread/thread/637c8b2fe816304d
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=lft, rght__lt=rght))
q = reduce(operator.or_, filters)
return Node.tree.filter(q)
Example Node tree:
T1
---T1.1
---T1.2
T2
T3
---T3.3
------T3.3.3
Example usage:
>> some_nodes = [<Node: T1>, <Node: T2>, <Node: T3>] # QureySet
>> print get_queryset_descendants(some_nodes)
[<Node: T1.1>, <Node: T1.2>, <Node: T3.3>, <Node: T3.3.3>]
>> print get_queryset_descendants(some_nodes, include_self=True)
[<Node: T1>, <Node: T1.1>, <Node: T1.2>, <Node: T2>, <Node: T3>, <Node: T3.3>, <Node: T3.3.3>]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With