from rest_framework.generics import ListAPIView, GenericAPIView from rest_framework.permissions import AllowAny from rest_framework.response import Response from rest_framework import status from rest_framework.permissions import IsAuthenticated from django.db.models import Q from django.shortcuts import get_object_or_404 from .models import Blog from .serializers import BlogListSerializer, BlogDetailSerializer import random from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi class BlogListAPIView(ListAPIView): """ API view to list blogs with search and sort_by filters """ serializer_class = BlogListSerializer permission_classes = [AllowAny] @swagger_auto_schema( operation_description="List blogs with optional search and sort_by filters", tags=["Imam-Javad - Blog"], manual_parameters=[ openapi.Parameter( name='search', in_=openapi.IN_QUERY, description='Search in title, slogan, or summary', type=openapi.TYPE_STRING, required=False ), openapi.Parameter( name='sort_by', in_=openapi.IN_QUERY, description="Sorting: 'latest' or 'most_viewed'", type=openapi.TYPE_STRING, required=False ), ], responses={ 200: openapi.Response( description="List of blogs", schema=BlogListSerializer(many=True) ) } ) def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def get_queryset(self): queryset = Blog.objects.all() # Search filter search = self.request.query_params.get('search', None) if search: queryset = queryset.filter( Q(title__icontains=search) | Q(slogan__icontains=search) | Q(summary__icontains=search) ) # Sort by filter sort_by = self.request.query_params.get('sort_by', None) if sort_by == 'latest': queryset = queryset.order_by('-created_at') elif sort_by == 'most_viewed': queryset = queryset.order_by('-views_count') else: # Default ordering queryset = queryset.order_by('-created_at') return queryset class RelatedBlogsAPIView(GenericAPIView): """ API view to get 10 random related blogs for a given blog ID """ serializer_class = BlogListSerializer permission_classes = [AllowAny] @swagger_auto_schema( operation_description="Get up to 10 random related blogs for the given blog_id", tags=["Imam-Javad - Blog"], manual_parameters=[ openapi.Parameter( name='blog_id', in_=openapi.IN_PATH, description='Current blog ID to exclude', type=openapi.TYPE_INTEGER, required=True ) ], responses={ 200: openapi.Response( description="Related blogs", schema=BlogListSerializer(many=True) ) } ) def get(self, request, blog_id): """ Get 10 random blogs excluding the current blog """ try: # Get the current blog to exclude it from results current_blog = get_object_or_404(Blog, id=blog_id) # Get all blogs except the current one all_blogs = list(Blog.objects.exclude(id=blog_id)) # Get random 10 blogs (or less if there are fewer blogs) random_count = min(10, len(all_blogs)) if random_count > 0: related_blogs = random.sample(all_blogs, random_count) else: related_blogs = [] serializer = self.get_serializer(related_blogs, many=True) return Response(serializer.data, status=status.HTTP_200_OK) except Exception as e: return Response( {'error': 'Blog not found or error occurred'}, status=status.HTTP_404_NOT_FOUND ) class BlogDetailBySlugAPIView(GenericAPIView): """ API view to get blog details by slug and increment view count """ serializer_class = BlogDetailSerializer permission_classes = [AllowAny] @swagger_auto_schema( operation_description="Get blog details by slug and increment view count", tags=["Imam-Javad - Blog"], manual_parameters=[ openapi.Parameter( name='slug', in_=openapi.IN_PATH, description='Blog slug', type=openapi.TYPE_STRING, required=True ) ], responses={ 200: openapi.Response( description="Blog detail", schema=BlogDetailSerializer() ) } ) def get(self, request, slug): """ Get blog details by slug and increment view count """ try: # Slug is stored as list of objects in JSONField -> filter accordingly blog = Blog.objects.filter(slug__contains=[{'title': slug}]).first() if not blog: return Response({'error': 'Blog not found'}, status=status.HTTP_404_NOT_FOUND) # Increment view count blog.increment_view_count() # Get related blog contents ordered by order field blog_with_contents = Blog.objects.prefetch_related( 'contents' ).get(id=blog.id) serializer = self.get_serializer(blog_with_contents, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK) except Exception as e: return Response( {'error': 'Blog not found'}, status=status.HTTP_404_NOT_FOUND )