fix product filters

This commit is contained in:
Parsa Nazer
2026-05-03 18:42:43 +03:30
parent 556b58216b
commit 8a06133ae8
+44 -19
View File
@@ -20,6 +20,7 @@ from django.db.models import Min, Max, Count, Prefetch
from home.models import ShowCaseSlider
from home.serializers import ShowCaseSliderSerialzier
from order.models import Cart, CartItem
from django.db.models import Min, Max, Value
# class APIView(APIView):
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
@@ -272,61 +273,85 @@ class AllProductsView(APIView):
if in_stock is not None:
if in_stock.lower() == 'true':
products = products.filter(
variants__in_stock__gt=0).distinct()
variants__in_stock__gt=0
).distinct()
elif in_stock.lower() != 'false':
return Response({'detail': 'in_stock must be "true" or "false".'}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{'detail': 'in_stock must be "true" or "false".'},
status=status.HTTP_400_BAD_REQUEST
)
# Filter by discount
# Discount filter
has_discount = request.query_params.get('has_discount')
if has_discount is not None:
if has_discount.lower() == 'true':
products = products.filter(
variants__discount__gt=0).distinct()
variants__discount__gt=0
).distinct()
elif has_discount.lower() != 'false':
return Response({'detail': 'has_discount must be "true" or "false".'}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{'detail': 'has_discount must be "true" or "false".'},
status=status.HTTP_400_BAD_REQUEST
)
# Search filter
# Search
search_query = request.query_params.get('search')
if search_query:
products = products.annotate(
similarity=(
TrigramSimilarity('name', search_query)
+ TrigramSimilarity(Coalesce('description', Value('')), search_query)
TrigramSimilarity('name', search_query) +
TrigramSimilarity(
Coalesce('description', Value('')),
search_query
)
)
).filter(similarity__gt=0.1)
# Price annotation (IMPORTANT for sorting)
products = products.annotate(
min_price=Min('variants__price'),
max_price=Max('variants__price')
)
# Price filters
price_gte = request.query_params.get('price_gte')
price_lte = request.query_params.get('price_lte')
products = products.annotate(min_price=Min(
'variants__price'), max_price=Max('variants__price'))
if price_gte:
try:
price_gte = float(price_gte)
products = products.filter(max_price__gte=price_gte)
products = products.filter(
max_price__gte=float(price_gte)
)
except ValueError:
return Response({'detail': 'price_gte must be a number.'}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{'detail': 'price_gte must be a number.'},
status=status.HTTP_400_BAD_REQUEST
)
price_lte = request.query_params.get('price_lte')
if price_lte:
try:
price_lte = float(price_lte)
products = products.filter(min_price__lte=price_lte)
products = products.filter(
min_price__lte=float(price_lte)
)
except ValueError:
return Response({'detail': 'price_lte must be a number.'}, status=status.HTTP_400_BAD_REQUEST)
# Sorting
sort_by = request.query_params.get('sort')
if sort_by == 'newest':
sort_by = '-created_at'
elif sort_by == 'oldest':
sort_by = 'created_at'
if sort_by in ['name', '-name', 'created_at', '-created_at']:
products = products.order_by(sort_by)
elif sort_by in ['price', '-price']:
products = products.order_by('min_price' if sort_by == 'price' else '-min_price')
elif search_query:
products = products.order_by('-similarity', 'name')
else:
products = products.order_by('name')
# Pagination
products.order_by('category')
paginator = self.pagination_class()
paginated_products = paginator.paginate_queryset(products, request)
serializer = self.serializer_class(