Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it feasible to support get queryset descendants or ancestors like features in django-mptt #28

Open
jukanntenn opened this issue Jan 9, 2022 · 1 comment
Labels
question Further information is requested

Comments

@jukanntenn
Copy link

django-mptt has a feature get_queryset_descendants which query the descendants of tree nodes represented by a queryset. However, TreeQuerySet.descendants method in django-tree-queries only support query descendants of a certain tree node. After doing some experiments, I find a way to implement such feature, like bellow:

def descendants(self, of, include_self=False):
    ...
    extra_where = " or ".join(['instr(__tree.tree_path, "{sep}{pk}{sep}") <> 0'.format(
                        pk=self.model._meta.pk.get_db_prep_value(pk(obj), connection),
                        sep=SEPARATOR,
                    ) for obj in of])
            queryset = self.with_tree_fields().extra(
                # NOTE! The representation of tree_path is NOT part of the API.
                where=[
                    # XXX This *may* be unsafe with some primary key field types.
                    # It is certainly safe with integers.
                    extra_where
                ]
            )

The idea is if of parameter is a queryset rather than a single model instance, changing the where clause to or.

The downside of this approach is we need an extra database query. I also have no idea if there is performance issue for a large queryset.

Another idea I come up with is inject a a subquery in CTE, like bellow:
change:

SELECT
            0 AS tree_depth,
            array[T.{pk}] AS tree_path,
            array[{order_by}] AS tree_ordering,
            T."{pk}"
        FROM {db_table} T
        WHERE T."{parent}" IS NULL

to:

SELECT
            0 AS tree_depth,
            array[T.{pk}] AS tree_path,
            array[{order_by}] AS tree_ordering,
            T."{pk}"
        FROM {db_table} T
        WHERE T."{parent}" in <<pks of queryset>>

but I also have no idea that this is feasible.

@jukanntenn jukanntenn changed the title Support get queryset descendants or ancestors Is it feasible to support get queryset descendants or ancestors like features in django-mptt Jan 9, 2022
@matthiask
Copy link
Member

This would certainly be doable; the problem is that django-tree-queries doesn't add much API at all. It has almost no extension points. What you write would probably be more straightforward to implement on top of a more generic solution for building CTEs, maybe https://pypi.org/project/django-cte/

@matthiask matthiask added the question Further information is requested label Jun 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants