diff --git a/backend/product/views.py b/backend/product/views.py index 901e9fb..432db49 100644 --- a/backend/product/views.py +++ b/backend/product/views.py @@ -163,12 +163,13 @@ class AllProductsView(APIView): category_type = request.query_params.get('category_type') VALID_CATEGORY_TYPES = {'sub', 'main'} + products = ProductModel.objects.all() if category_slug: if category_type not in VALID_CATEGORY_TYPES: return Response( {"detail": "category_type must be one of ['sub', 'main']"}, - status=status.HTTP_400_BAD_REQUEST + status=status.HTTP_400_BAD_REQUEST ) if category_type == 'sub': @@ -178,36 +179,48 @@ class AllProductsView(APIView): main_category = get_object_or_404(MainCategoryModel, slug=category_slug) sub_categories = main_category.subcategorys.all() products = ProductModel.objects.filter(category__in=sub_categories) - else: - products = ProductModel.objects.all() + in_stock = request.query_params.get('in_stock') + if in_stock is not None: + if in_stock.lower() == 'true': + products = products.filter(variants__in_stock__gt=0) + elif in_stock.lower() != 'false': + return Response({'detail': 'in_stock must be "true" or "false".'}, status=status.HTTP_400_BAD_REQUEST) - # Filter by stock status if `in_stock` is specified - in_stock = request.query_params.get('in_stock', "false") == 'true' - if in_stock: - products = products.filter(variants__in_stock__gt=0) - - # Filter by discount if `has_discount` is specified - has_discount = request.query_params.get('has_discount', "false") == 'true' - if has_discount: - products = products.filter(variants__discount__gt=0) + # Filter by discount + 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) + elif has_discount.lower() != 'false': + return Response({'detail': 'has_discount must be "true" or "false".'}, status=status.HTTP_400_BAD_REQUEST) # Search filter - search_query = request.query_params.get('search', None) + search_query = request.query_params.get('search') if search_query: products = products.filter(Q(name__icontains=search_query) | Q(description__icontains=search_query)) # Price filters - price_gte = request.query_params.get('price_gte', None) - price_lte = request.query_params.get('price_lte', None) + 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: - products = products.filter(max_price__gte=price_gte) + try: + price_gte = float(price_gte) + products = products.filter(max_price__gte=price_gte) + except ValueError: + return Response({'detail': 'price_gte must be a number.'}, status=status.HTTP_400_BAD_REQUEST) + if price_lte: - products = products.filter(min_price__lte=price_lte) + try: + price_lte = float(price_lte) + products = products.filter(min_price__lte=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', None) + sort_by = request.query_params.get('sort') if sort_by in ['name', '-name', 'created_at', '-created_at']: products = products.order_by(sort_by) else: @@ -216,7 +229,10 @@ class AllProductsView(APIView): # Pagination paginator = self.pagination_class() paginated_products = paginator.paginate_queryset(products, request) - serializer = self.serializer_class(paginated_products, many=True, context={'request': request, 'view_type': 'list'}) + serializer = self.serializer_class( + paginated_products, many=True, + context={'request': request, 'view_type': 'list'} + ) return paginator.get_paginated_response(serializer.data) except MainCategoryModel.DoesNotExist: