Features: 1) Add personal_order_only ordering option; 2) Annotate queryset with personal_order_only calculated field; 3) Support custom ordering for price and personal_order_only.
Fixes: 1) Correct `rating` ordering logic to use cleaned field names without signs. Extra: 1) Add missing import for `BooleanField`; 2) Refactor ordering parameter processing for clarity and efficiency.
This commit is contained in:
parent
143cd6804b
commit
91b043ac4f
1 changed files with 41 additions and 2 deletions
|
|
@ -16,6 +16,7 @@ from django.db.models import (
|
|||
When,
|
||||
Max,
|
||||
Prefetch,
|
||||
BooleanField,
|
||||
)
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils.http import urlsafe_base64_decode
|
||||
|
|
@ -92,6 +93,7 @@ class ProductFilter(FilterSet):
|
|||
("price_order", "price"),
|
||||
("sku", "sku"),
|
||||
("?", "random"),
|
||||
("personal_order_only", "personal_order_only"),
|
||||
),
|
||||
initial="uuid",
|
||||
)
|
||||
|
|
@ -279,8 +281,8 @@ class ProductFilter(FilterSet):
|
|||
|
||||
ordering_param = self.data.get("order_by", "")
|
||||
if ordering_param:
|
||||
order_fields = [field.strip() for field in ordering_param.split(",")]
|
||||
if any(field.lstrip("-") == "rating" for field in order_fields):
|
||||
order_fields_no_sign = [field.strip("-") for field in ordering_param.split(",")]
|
||||
if "rating" in order_fields_no_sign:
|
||||
feedback_qs = (
|
||||
Feedback.objects.filter(order_product__product_id=OuterRef("pk"))
|
||||
.values("order_product__product_id")
|
||||
|
|
@ -293,6 +295,43 @@ class ProductFilter(FilterSet):
|
|||
Value(0, output_field=FloatField()),
|
||||
)
|
||||
)
|
||||
|
||||
if ordering_param and any(f.lstrip("-") == "price" for f in ordering_param.split(",")):
|
||||
qs = qs.annotate(
|
||||
price_order=Coalesce(
|
||||
Max("stocks__price"),
|
||||
Value(0.0),
|
||||
output_field=FloatField(),
|
||||
)
|
||||
)
|
||||
|
||||
qs = qs.annotate(
|
||||
personal_order_only=Case(
|
||||
When(has_stock=Value(0), has_price=Value(1), then=Value(True)),
|
||||
default=Value(False),
|
||||
output_field=BooleanField(),
|
||||
)
|
||||
)
|
||||
|
||||
requested = [part.strip() for part in ordering_param.split(",") if part.strip()] if ordering_param else []
|
||||
mapped_requested = []
|
||||
for part in requested:
|
||||
desc = part.startswith("-")
|
||||
key = part.lstrip("-")
|
||||
if key == "price":
|
||||
key = "price_order"
|
||||
if key == "random":
|
||||
key = "?"
|
||||
mapped_requested.append(key)
|
||||
continue
|
||||
mapped_requested.append(f"-{key}" if desc else key)
|
||||
|
||||
has_personal_in_request = any(p.lstrip("-") == "personal_order_only" for p in mapped_requested)
|
||||
final_ordering = (["personal_order_only"] if not has_personal_in_request else []) + mapped_requested
|
||||
|
||||
if final_ordering:
|
||||
qs = qs.order_by(*final_ordering)
|
||||
|
||||
return qs.distinct()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue