Features: 1) Add Prefetch import in filters.py; 2) Introduce filter_order_by method with custom ordering logic for Category model.
Fixes: 1) Replace `OrderingFilter` with `CharFilter` for `order_by` field in `CategoryFilter`. Extra: 1) Remove unused ordering configuration from `order_by` field; 2) Refactor ordering logic with prefetch-related optimization for children categories.
This commit is contained in:
parent
eecb4c9ec4
commit
d811d1e5fe
1 changed files with 31 additions and 8 deletions
|
|
@ -15,6 +15,7 @@ from django.db.models import (
|
||||||
Value,
|
Value,
|
||||||
When,
|
When,
|
||||||
Max,
|
Max,
|
||||||
|
Prefetch,
|
||||||
)
|
)
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
from django.utils.http import urlsafe_base64_decode
|
from django.utils.http import urlsafe_base64_decode
|
||||||
|
|
@ -382,14 +383,7 @@ class CategoryFilter(FilterSet):
|
||||||
tags = CaseInsensitiveListFilter(field_name="tags__tag_name", label=_("Tags"))
|
tags = CaseInsensitiveListFilter(field_name="tags__tag_name", label=_("Tags"))
|
||||||
level = NumberFilter(field_name="level", lookup_expr="exact", label=_("Level"))
|
level = NumberFilter(field_name="level", lookup_expr="exact", label=_("Level"))
|
||||||
|
|
||||||
order_by = OrderingFilter(
|
order_by = CharFilter(method="filter_order_by")
|
||||||
fields=(
|
|
||||||
("priority", "priority"),
|
|
||||||
("uuid", "uuid"),
|
|
||||||
("name", "name"),
|
|
||||||
("?", "random"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Category
|
model = Category
|
||||||
|
|
@ -404,6 +398,35 @@ class CategoryFilter(FilterSet):
|
||||||
"whole",
|
"whole",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def filter_order_by(self, queryset, _name, value):
|
||||||
|
if not value:
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
desc = value.startswith("-")
|
||||||
|
key = value.lstrip("-")
|
||||||
|
|
||||||
|
mapping = {
|
||||||
|
"priority": "priority",
|
||||||
|
"uuid": "uuid",
|
||||||
|
"name": "name",
|
||||||
|
"?": "random",
|
||||||
|
}
|
||||||
|
field = mapping.get(key)
|
||||||
|
if field is None:
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
if field == "?":
|
||||||
|
parent_order = "?"
|
||||||
|
child_order = "?"
|
||||||
|
else:
|
||||||
|
parent_order = f"-{field}" if desc else field
|
||||||
|
child_order = parent_order
|
||||||
|
|
||||||
|
qs = queryset.order_by(parent_order)
|
||||||
|
children_qs = Category.objects.all().order_by(child_order)
|
||||||
|
|
||||||
|
return qs.prefetch_related(Prefetch("children", queryset=children_qs))
|
||||||
|
|
||||||
def filter_name(self, queryset, _name, value):
|
def filter_name(self, queryset, _name, value):
|
||||||
search_results = process_query(query=value, request=self.request)["categories"]
|
search_results = process_query(query=value, request=self.request)["categories"]
|
||||||
uuids = [res["uuid"] for res in search_results if res.get("uuid")]
|
uuids = [res["uuid"] for res in search_results if res.get("uuid")]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue