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 from rest_framework.permissions import AllowAny # class CustomAPIView(APIView): # def __init__(self, *args, **kwargs): # super().__init__(*args, **kwargs) # print('here') # print(self.permission_classes) # if not getattr(self, 'permission_classes')[0] != AllowAny or not self.permission_classes: # print('asdf') # self.authentication_classes = [] class AllCategories(APIView): serializer_class = CategorySerializer authentication_classes = [] 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 = ProductSerializer permission_classes = [AllowAny] authentication_classes = [] 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_ser.data, status=status.HTTP_200_OK) from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import status from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes from django.db.models import Q class AllProductsView(APIView): serializer_class = ProductSerializer pagination_class = StructurePagination authentication_classes = [] # Add authentication if required @extend_schema( parameters=[ OpenApiParameter( name="search", description="Search by product name or description.", required=False, type=OpenApiTypes.STR, ), OpenApiParameter( name="category", type={'type': 'array', 'items': {'type': 'number'}}, location=OpenApiParameter.QUERY, required=False, style='form', explode=False, ), 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`, `created_at`, `-created_at`." "\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, ), OpenApiParameter( name="in_stock", description="Filter products that are in stock (positive stock).", required=False, type=OpenApiTypes.BOOL, ), OpenApiParameter( name="has_discount", description="Filter products that have a discount.", required=False, type=OpenApiTypes.BOOL, ) ], description=( "Retrieve products with optional filters and sorting. " "Provide a list of category IDs to filter products by those categories and their subcategories." ), responses={ 200: ProductSerializer(many=True), 404: OpenApiTypes.OBJECT, }, ) def get(self, request): try: # Get list of category IDs from query parameters category_ids = request.query_params.getlist('category', []) if category_ids: # Convert category IDs to integers and filter products by these categories category_ids = [int(id) for id in category_ids] products = ProductModel.objects.filter(category__id__in=category_ids) else: products = ProductModel.objects.all() # 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(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(discount__gt=0) # Search filter search_query = request.query_params.get('search', None) 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) if price_gte: products = products.filter(price__gte=price_gte) if price_lte: products = products.filter(price__lte=price_lte) # Sorting sort_by = request.query_params.get('sort', None) if sort_by in ['name', '-name', 'price', '-price', 'discount', '-discount', 'created_at', '-created_at']: products = products.order_by(sort_by) else: products = products.order_by('name') # Pagination 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 CategoryModel.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)