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.models import ShowCaseSlider
from home.serializers import ShowCaseSliderSerialzier from home.serializers import ShowCaseSliderSerialzier
from order.models import Cart, CartItem from order.models import Cart, CartItem
from django.db.models import Min, Max, Value
# class APIView(APIView): # class APIView(APIView):
# def __init__(self, *args, **kwargs): # def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs) # super().__init__(*args, **kwargs)
@@ -272,61 +273,85 @@ class AllProductsView(APIView):
if in_stock is not None: if in_stock is not None:
if in_stock.lower() == 'true': if in_stock.lower() == 'true':
products = products.filter( products = products.filter(
variants__in_stock__gt=0).distinct() variants__in_stock__gt=0
).distinct()
elif in_stock.lower() != 'false': 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') has_discount = request.query_params.get('has_discount')
if has_discount is not None: if has_discount is not None:
if has_discount.lower() == 'true': if has_discount.lower() == 'true':
products = products.filter( products = products.filter(
variants__discount__gt=0).distinct() variants__discount__gt=0
).distinct()
elif has_discount.lower() != 'false': 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') search_query = request.query_params.get('search')
if search_query: if search_query:
products = products.annotate( products = products.annotate(
similarity=( similarity=(
TrigramSimilarity('name', search_query) TrigramSimilarity('name', search_query) +
+ TrigramSimilarity(Coalesce('description', Value('')), search_query) TrigramSimilarity(
Coalesce('description', Value('')),
search_query
)
) )
).filter(similarity__gt=0.1) ).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 filters
price_gte = request.query_params.get('price_gte') 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: if price_gte:
try: try:
price_gte = float(price_gte) products = products.filter(
products = products.filter(max_price__gte=price_gte) max_price__gte=float(price_gte)
)
except ValueError: 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: if price_lte:
try: try:
price_lte = float(price_lte) products = products.filter(
products = products.filter(min_price__lte=price_lte) min_price__lte=float(price_lte)
)
except ValueError: except ValueError:
return Response({'detail': 'price_lte must be a number.'}, status=status.HTTP_400_BAD_REQUEST) return Response({'detail': 'price_lte must be a number.'}, status=status.HTTP_400_BAD_REQUEST)
# Sorting # Sorting
sort_by = request.query_params.get('sort') 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']: if sort_by in ['name', '-name', 'created_at', '-created_at']:
products = products.order_by(sort_by) 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: elif search_query:
products = products.order_by('-similarity', 'name') products = products.order_by('-similarity', 'name')
else: else:
products = products.order_by('name') products = products.order_by('name')
# Pagination # Pagination
products.order_by('category')
paginator = self.pagination_class() paginator = self.pagination_class()
paginated_products = paginator.paginate_queryset(products, request) paginated_products = paginator.paginate_queryset(products, request)
serializer = self.serializer_class( serializer = self.serializer_class(