(self, node, include_self=False)
return query.order_by(cte.col._cte_ordering)
Query node descendants

        :param node: A model instance or a QuerySet or Q object querying
        the adjacency list model. If a QuerySet, it should query a
        single value with something like `.values('id')`. If Q the
        `include_self` argument will be ignored.
        :returns: A `QuerySet` instance.
Query node descendants
Query node descendants
def get_descendants(self, node, include_self=False):
        """Query node descendants

        :param node: A model instance or a QuerySet or Q object querying
        the adjacency list model. If a QuerySet, it should query a
        single value with something like `.values('id')`. If Q the
        `include_self` argument will be ignored.
        :returns: A `QuerySet` instance.
        """
        ordering_col = self.model.ordering_col_attr

        discard_dups = False
        if isinstance(node, Q):
            where = node
            discard_dups = True
        elif include_self:
            if isinstance(node, QuerySet):
                if _is_empty(node):
                    return self.none()
                where = Q(id__in=node.order_by())
                discard_dups = True
            else:
                where = Q(id=node.id)
        elif isinstance(node, QuerySet):
            if _is_empty(node):
                return self.none()
            where = Q(parent_id__in=node.order_by())
            discard_dups = True
        else:
            where = Q(parent_id=node.id)

        def make_cte_query(cte):
            return self.filter(where).order_by().annotate(
                _cte_ordering=str_array(ordering_col),
            ).union(
                cte.join(
                    self.all().order_by(),
                    parent_id=cte.col.id,
                ).annotate(
                    _cte_ordering=array_append(
                        cte.col._cte_ordering,
                        F(ordering_col),
                    )
                ),
                all=True,
            )
        cte = With.recursive(make_cte_query)
        query = cte.queryset().with_cte(cte)

        if discard_dups:
            # Remove duplicates when the supplied Queryset or Q object
            # may contain/match both parents and children. For a given
            # id, retain the row with the longest path. TODO remove this
            # and ensure duplicates do not matter or the criteria never
            # matches both parents and children in all calling code.
            xdups = With(
                cte.queryset().annotate(
                    max_len=array_length(
                        F("_cte_ordering"),
                        output_field=field
                    ),
                ).distinct("id").order_by(
                    "id",
                    "-max_len",
                ).values(
                    "id",
                    "_cte_ordering",
                ),
                name="xdups"
            )
            query = query.annotate(
                _exclude_dups=Exists(SubQueryset(xdups.queryset().filter(
                    id=OuterRef("id"),
                    _cte_ordering=OuterRef("_cte_ordering"),
                )))
            ).filter(_exclude_dups=True).with_cte(xdups)

        return query.order_by(cte.col._cte_ordering)
def get_descendants ( self , node , include_self = False ) : ordering_col = self . model . ordering_col_attr discard_dups = False if isinstance ( node , Q ) : where = node discard_dups = True elif include_self : if isinstance ( node , QuerySet ) : if _is_empty ( node ) : return self . none ( ) where = Q ( id__in = node . order_by ( ) ) discard_dups = True else : where = Q ( id = node . id ) elif isinstance ( node , QuerySet ) : if _is_empty ( node ) : return self . none ( ) where = Q ( parent_id__in = node . order_by ( ) ) discard_dups = True else : where = Q ( parent_id = node . id ) def make_cte_query ( cte ) : return self . filter ( where ) . order_by ( ) . annotate ( _cte_ordering = str_array ( ordering_col ) , ) . union ( cte . join ( self . all ( ) . order_by ( ) , parent_id = cte . col . id , ) . annotate ( _cte_ordering = array_append ( cte . col . _cte_ordering , F ( ordering_col ) , ) ) , all = True , ) cte = With . recursive ( make_cte_query ) query = cte . queryset ( ) . with_cte ( cte ) if discard_dups : # Remove duplicates when the supplied Queryset or Q object # may contain/match both parents and children. For a given # id, retain the row with the longest path. TODO remove this # and ensure duplicates do not matter or the criteria never # matches both parents and children in all calling code. xdups = With ( cte . queryset ( ) . annotate ( max_len = array_length ( F ( "_cte_ordering" ) , output_field = field ) , ) . distinct ( "id" ) . order_by ( "id" , "-max_len" , ) . values ( "id" , "_cte_ordering" , ) , name = "xdups" ) query = query . annotate ( _exclude_dups = Exists ( SubQueryset ( xdups . queryset ( ) . filter ( id = OuterRef ( "id" ) , _cte_ordering = OuterRef ( "_cte_ordering" ) , ) ) ) ) . filter ( _exclude_dups = True ) . with_cte ( xdups ) return query . order_by ( cte . col . _cte_ordering )