from django.core.paginator import Paginator from rest_framework.views import APIView from .models import * from .serializers import * from rest_framework import status from rest_framework.response import Response from django.db.models import Q from django.shortcuts import get_object_or_404 from rest_framework.permissions import IsAuthenticatedOrReadOnly from utils.pagination import StructurePagination from drf_spectacular.utils import extend_schema, OpenApiParameter from drf_spectacular.types import OpenApiTypes class AllCategories(APIView): serializer_class = CategorySerializer def get(self, request): categories = CategoryModel.objects.all() categories_ser = self.serializer_class(instance=categories, many=True) return Response({"categories": categories_ser.data}, status=status.HTTP_200_OK) class ProductView(APIView): serializer_class = ProductModel def get(self, request, pk): product = get_object_or_404(ProductModel, id=pk) product_ser = self.serializer_class(instance=product, many=False) return Response({"product": product_ser.data}, status=status.HTTP_200_OK) class AllProductsView(APIView): serializer_class = ProductSerializer pagination_class = StructurePagination @extend_schema( parameters=[ OpenApiParameter( name="search", description="Search by product name or description.", required=False, type=OpenApiTypes.STR, ), OpenApiParameter( name="category", description="Filter by category ID.", required=False, type=OpenApiTypes.INT, ), OpenApiParameter( name="price_gte", description="Filter products with price greater than or equal to this value.", required=False, type=OpenApiTypes.FLOAT, ), OpenApiParameter( name="price_lte", description="Filter products with price less than or equal to this value.", required=False, type=OpenApiTypes.FLOAT, ), OpenApiParameter( name="sort", description=( "Sort results by one of the following fields:\n" "`name`, `-name`, `price`, `-price`, `discount`, `-discount`." "\nPrefix with `-` for descending order." ), required=False, type=OpenApiTypes.STR, ), OpenApiParameter( name="limit", description="Number of results to return per page (pagination).", required=False, type=OpenApiTypes.INT, ), OpenApiParameter( name="offset", description="The starting position of the results (pagination).", required=False, type=OpenApiTypes.INT, ), ], description=( "Retrieve products with optional filters and sorting. " "Provide a category ID to filter products in that category and its subcategories." ), responses={ 200: ProductSerializer(many=True), 404: OpenApiTypes.OBJECT, }, ) def get(self, request, pk=None): try: if pk: category = Category.objects.get(pk=pk) products = ProductModel.objects.filter(category__in=category.get_descendants(include_self=True)) else: products = ProductModel.objects.all() search_query = request.query_params.get('search', None) if search_query: products = products.filter(Q(name__icontains=search_query) | Q(description__icontains=search_query)) category_filter = request.query_params.get('category', None) if category_filter: products = products.filter(category__id=category_filter) price_gte = request.query_params.get('price_gte', None) price_lte = request.query_params.get('price_lte', None) if price_gte: products = products.filter(price__gte=price_gte) if price_lte: products = products.filter(price__lte=price_lte) sort_by = request.query_params.get('sort', None) if sort_by in ['name', '-name', 'price', '-price', 'discount', '-discount']: products = products.order_by(sort_by) else: products = products.order_by('name') paginator = self.pagination_class() paginated_products = paginator.paginate_queryset(products, request) serializer = self.serializer_class(paginated_products, many=True) return paginator.get_paginated_response(serializer.data) except Category.DoesNotExist: return Response({"detail": "Category not found."}, status=status.HTTP_404_NOT_FOUND) class CommentView(APIView): serializer_class = CommentSerializer permission_classes = [IsAuthenticatedOrReadOnly] def get(self, request, pk): product = get_object_or_404(ProductModel, id=pk) comments = product.comments.filter(show=True) comments_ser = self.serializer_class(instance=comments, many=True) return Response({'comments': comments_ser.data}, status=status.HTTP_200_OK) def post(self, request, pk): comment_ser = CommentSerializer(data=request.data) product = get_object_or_404(ProductModel, id=pk) if comment_ser.is_valid(): comment_ser.save(product=product, user=request.user) return Response(comment_ser.data, status=status.HTTP_201_CREATED) return Response(comment_ser.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, pk): comment = get_object_or_404(CommentModel, pk=pk) if comment.user == request.user: comment.delete() return Response(status=status.HTTP_204_NO_CONTENT) else: return Response({"detail": "شما اجازه ی پاک کردن این کامنت را ندارید"}, status=status.HTTP_403_FORBIDDEN)