You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

183 lines
6.1 KiB

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
from utils.pagination import StandardResultsSetPagination
class BlogListAPIView(ListAPIView):
"""
API view to list blogs with search and sort_by filters
"""
serializer_class = BlogListSerializer
permission_classes = [AllowAny]
pagination_class = StandardResultsSetPagination
@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
)