from rest_framework import generics, status from rest_framework.response import Response from drf_yasg import openapi from drf_yasg.utils import swagger_auto_schema from apps.library.pagination import NoPagination from rest_framework.permissions import IsAuthenticated from apps.article.models import * from apps.article.serializers import * class ArticleCategoryListAPIView(generics.ListAPIView): serializer_class = ArticleCategoryListSerializer @swagger_auto_schema( operation_description="Get a list of all active article categories", tags=["Dobodbi - Article"], responses={ 200: openapi.Response( description="List of article categories", schema=ArticleCategoryListSerializer(many=True) ) } ) def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def get_queryset(self): return ArticleCategory.objects.filter(status=True).order_by('order') class PinnedArticleCollectionListView(generics.ListAPIView): serializer_class = PinnedArticleCollectionSerializer permission_classes = (IsAuthenticated,) pagination_class = NoPagination @swagger_auto_schema( operation_description="Get a list of pinned article collections", tags=["Dobodbi - Article"], responses={ 200: openapi.Response( description="List of pinned article collections", schema=PinnedArticleCollectionSerializer(many=True) ) } ) def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def get_queryset(self): return PinnedArticleCollection.objects.filter( status=True, display_position=ArticleCollection.DisplayPosition.PINNED ).order_by('-order', '-id') def list(self, request, *args, **kwargs): response = super().list(request, *args, **kwargs) categories_count = ArticleCategory.objects.filter(status=True).count() from apps.bookmark.models import Bookmark bookmarks_count = Bookmark.objects.filter( service=Bookmark.ServiceChoices.ARTICLE, ).count() info = { "categories_count": categories_count, "bookmarks_count": bookmarks_count, } data = { "count": response.data.get("count"), "next": response.data.get("next"), "previous": response.data.get("previous"), "info": info, "results": response.data.get("results") } return Response(data, status=status.HTTP_200_OK) class MiddleArticleCollectionListView(generics.ListAPIView): serializer_class = MiddleArticleCollectionSerializer permission_classes = (IsAuthenticated,) pagination_class = NoPagination @swagger_auto_schema( operation_description="Get a list of middle article collections", tags=["Dobodbi - Article"], responses={ 200: openapi.Response( description="List of middle article collections", schema=MiddleArticleCollectionSerializer(many=True) ) } ) def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def get_queryset(self): return ArticleCollection.objects.filter( status=True, display_position=ArticleCollection.DisplayPosition.MIDDLE ).order_by('order') class ArticleListAPIView(generics.ListAPIView): serializer_class = ArticleListSerializer permission_classes = (IsAuthenticated,) @swagger_auto_schema( operation_description="Get a list of articles with optional filtering and sorting", tags=["Dobodbi - Article"], manual_parameters=[ openapi.Parameter( name='category', in_=openapi.IN_QUERY, description='Filter articles by category slug(s). Can be a single slug or comma-separated list of slugs', type=openapi.TYPE_STRING, required=False ), openapi.Parameter( name='collection', in_=openapi.IN_QUERY, description='Filter articles by collection slug', type=openapi.TYPE_STRING, required=False ), openapi.Parameter( name='is_bookmark', in_=openapi.IN_QUERY, description='Filter articles that are bookmarked by the user (true/false)', type=openapi.TYPE_BOOLEAN, required=False ), openapi.Parameter( name='search', in_=openapi.IN_QUERY, description='Search articles by title', type=openapi.TYPE_STRING, required=False ), openapi.Parameter( name='sort', in_=openapi.IN_QUERY, description='Sort articles by field. Options: created_at, -created_at, view_count, -view_count, title, -title', type=openapi.TYPE_STRING, required=False ) ], responses={ 200: openapi.Response( description="List of articles", schema=ArticleListSerializer(many=True) ) } ) def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def get_queryset(self): queryset = Article.objects.filter(status=True) # Search by title if search parameter is provided search_query = self.request.query_params.get('search', None) if search_query: queryset = queryset.filter(title__icontains=search_query) # Filter by category if provided category = self.request.query_params.get('category', None) if category: # Support both single slug and comma-separated list of slugs category_slugs = [slug.strip() for slug in category.split(',')] queryset = queryset.filter(categories__slug__in=category_slugs).distinct() # Filter by collection if provided collection_slug = self.request.query_params.get('collection', None) if collection_slug: # Get all articles that are in the collection with the given slug queryset = queryset.filter( collections__slug=collection_slug ) # Filter by bookmarks if provided is_bookmark = self.request.query_params.get('is_bookmark', '').lower() if is_bookmark == 'true': # Import Bookmark model here to avoid circular imports from apps.bookmark.models import Bookmark # Get all bookmarked article IDs for the current user bookmarked_ids = Bookmark.objects.filter( user=self.request.user, service=Bookmark.ServiceChoices.ARTICLE, status=True ).values_list('content_id', flat=True) # Filter articles by these IDs queryset = queryset.filter(id__in=bookmarked_ids) # Sort by parameter sort = self.request.query_params.get('sort', '-created_at') # Allowed sort fields allowed_sorts = ['created_at', '-created_at', 'view_count', '-view_count', 'title', '-title'] if sort in allowed_sorts: queryset = queryset.order_by(sort) else: queryset = queryset.order_by('-created_at') return queryset class ArticleDetailAPIView(generics.RetrieveAPIView): serializer_class = ArticleDetailSerializer permission_classes = (IsAuthenticated,) lookup_field = 'slug' @swagger_auto_schema( operation_description="Get article details by slug", tags=["Dobodbi - Article"], responses={ 200: openapi.Response( description="Article details", schema=ArticleDetailSerializer() ) } ) def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def get_queryset(self): return Article.objects.filter(status=True) def retrieve(self, request, *args, **kwargs): instance = self.get_object() instance.increment_view_count() serializer = self.get_serializer(instance) return Response(serializer.data)