diff --git a/core/filters.py b/core/filters.py index 4871b135..3122fdf9 100644 --- a/core/filters.py +++ b/core/filters.py @@ -416,18 +416,49 @@ class CategoryFilter(FilterSet): return queryset if field == "?": - parent_order = "?" - child_order = "?" + order_expression = "?" else: - parent_order = f"-{field}" if desc else field - child_order = parent_order + order_expression = f"-{field}" if desc else field - qs = queryset.order_by(parent_order).prefetch_related(None) + qs = queryset.order_by(order_expression).prefetch_related(None) - children_qs = ( - Category.objects.all().order_by(child_order) if child_order != "?" else Category.objects.all().order_by("?") - ) - return qs.prefetch_related(Prefetch("children", queryset=children_qs)) + def create_ordered_tree_prefetch(max_depth=10): + if field == "?": + + def build_random_prefetch(depth): + if depth <= 0: + return None + + children_qs = Category.objects.all().order_by("?") + nested_prefetch = build_random_prefetch(depth - 1) + + if nested_prefetch: + children_qs = children_qs.prefetch_related(nested_prefetch) + + return Prefetch("children", queryset=children_qs) + + return build_random_prefetch(max_depth) + else: + + def build_ordered_prefetch(depth): + if depth <= 0: + return None + + children_qs = Category.objects.all().order_by(order_expression, "tree_id", "lft") + nested_prefetch = build_ordered_prefetch(depth - 1) + + if nested_prefetch: + children_qs = children_qs.prefetch_related(nested_prefetch) + + return Prefetch("children", queryset=children_qs) + + return build_ordered_prefetch(max_depth) + + tree_prefetch = create_ordered_tree_prefetch() + if tree_prefetch: + qs = qs.prefetch_related(tree_prefetch) + + return qs def filter_name(self, queryset, _name, value): search_results = process_query(query=value, request=self.request)["categories"]