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.
181 lines
6.0 KiB
181 lines
6.0 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
|
|
|
|
|
|
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
|
|
)
|