django-tree-queries
django-tree-queries copied to clipboard
Is it feasible to support get queryset descendants or ancestors like features in django-mptt
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.
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/