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.
 
 

294 lines
10 KiB

from rest_framework.generics import ListAPIView, RetrieveAPIView
from django.shortcuts import get_object_or_404
from utils.pagination import NoPagination
from rest_framework.response import Response
from django.db.models import Count
from django.db.models import Prefetch
from ..serializers.category import get_localized_text
from ..models import HadisCategory, Hadis, HadisCollection,HadisTransmitter , HadisCorrection
from ..serializers import HadisListSerializer, HadisBasicSerializer, HadisDetailSerializer, HadisCollectionListSerializer, HadisSyncSerializer,HadisCorrectionSerializer,HadisTransmitterListSerializer
from ..docs import hadis_list_swagger, hadis_detail_swagger, hadis_collections_swagger, hadis_sync_swagger, hadis_transmitters_swagger, hadis_corrections_swagger, hadis_basic_swagger, hadis_main_list_swagger
class HadisCollectionListView(ListAPIView):
"""
API view to list all hadis collections
"""
queryset = HadisCollection.objects.filter(status=True).order_by('order')
serializer_class = HadisCollectionListSerializer
pagination_class = NoPagination
@hadis_collections_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
class HadisSyncView(ListAPIView):
"""
API view to sync all hadis data for offline mode
"""
serializer_class = HadisSyncSerializer
pagination_class = NoPagination
def get_queryset(self):
return Hadis.objects.filter(status=True).select_related(
'category', 'hadis_status'
).prefetch_related(
'tags',
'transmitters__transmitter',
'references__images',
'references__book_reference',
'hadiscorrection_set'
).order_by('id')
@hadis_sync_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
response_data = {
'count': queryset.count(),
'results': serializer.data
}
return Response(response_data)
class HadisListView(ListAPIView):
"""
API view to list Hadis by category_id
"""
serializer_class = HadisListSerializer
@hadis_list_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def get_queryset(self):
category_id = self.kwargs.get('category_id')
if not HadisCategory.objects.filter(id=category_id).exists():
return Hadis.objects.none()
return Hadis.objects.filter(
category_id=category_id,
status=True
).order_by('number').annotate(
# distinct=True is CRITICAL here.
# Without it, if 3 narrators are from "Layer 1", it counts as 3.
# With it, it counts as 1 (unique layer).
layer_count=Count('transmitters__narrator_layer', distinct=True)
).select_related('category')
class HadisMainListView(ListAPIView):
"""
API view to list Hadis by category_id
"""
serializer_class = HadisListSerializer
@hadis_main_list_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def get_queryset(self):
queryset = Hadis.objects.select_related('category', 'hadis_status')
# Get search parameters
search_query = self.request.query_params.get('search', None)
status_filter = self.request.query_params.get('status', None)
category_filter = self.request.query_params.get('category', None)
# Apply search filter
if search_query:
queryset = self.apply_search_filter(queryset, search_query)
# Apply status filter
if status_filter:
queryset = queryset.filter(hadis_status__title__icontains=status_filter)
# Apply category filter
if category_filter:
queryset = queryset.filter(category__title__icontains=category_filter)
return queryset
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
# Get category titles
category_titles = self.get_category_titles(request)
# Get status titles
status_titles = self.get_status_titles(request)
response_data = {
'count': queryset.count(),
'categories': category_titles,
'statuses': status_titles,
'results': serializer.data
}
return Response(response_data)
def get_category_titles(self,request):
"""Get list of category titles based on language"""
from ..models import HadisCategory
categories = HadisCategory.objects.all()
category_titles = []
for category in categories:
title = get_localized_text(category.title,request)
category_titles.append(title)
return category_titles
def get_status_titles(self, request):
"""Get list of status titles based on language"""
from ..models import HadisStatus
statuses = HadisStatus.objects.all().order_by('order')
status_titles = []
for status in statuses:
title = get_localized_text(status.title,request)
status_titles.append(title)
return status_titles
def apply_search_filter(self, queryset, search_query):
"""
Apply search filter across multiple fields including JSONFields.
Searches in: title, title_narrator, text, translation
"""
from django.db.models import Q
# Basic search conditions
search_conditions = Q(text__icontains=search_query)
# For JSONFields, search in the JSON string representation
# This will find matches in the "text" values within the JSON arrays
search_conditions |= Q(title__icontains=search_query)
search_conditions |= Q(title_narrator__icontains=search_query)
search_conditions |= Q(translation__icontains=search_query)
return queryset.filter(search_conditions)
class HadisBasicView(RetrieveAPIView):
"""
API view to retrieve basic Hadis information by hadis_slug
"""
serializer_class = HadisBasicSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'hadis_slug'
@hadis_basic_swagger
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def get_queryset(self):
return Hadis.objects.filter(status=True)
class HadisDetailView(RetrieveAPIView):
"""
API view to retrieve detailed Hadis information by hadis_slug (excluding transmitters and corrections)
"""
serializer_class = HadisDetailSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'hadis_slug'
@hadis_detail_swagger
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def get_queryset(self):
return Hadis.objects.filter(status=True).select_related(
'category', 'hadis_status'
).prefetch_related(
'tags',
'references__book_reference__title',
'references__book_reference__images',
'references__book_reference__authors',
'references__book_reference__id',
'references__book_reference__description',
)
class HadisTransmittersView(RetrieveAPIView):
"""
Fetches a single Hadis but filters the nested Transmitters list
if a ?layer=slug param is provided.
"""
serializer_class = HadisTransmitterListSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'hadis_slug'
@hadis_transmitters_swagger
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def get_queryset(self):
# 1. Get the filter param
layer_slug = self.request.query_params.get('layer')
# 2. Build the query for the "Child" (Transmitters)
# We start with the base optimization (select_related)
transmitter_qs = HadisTransmitter.objects.select_related(
'transmitter',
'narrator_layer'
).order_by('order')
# 3. Apply the filter to the Child Query (if param exists)
if layer_slug:
# Assumes 'NarratorLayer' has a 'slug' field.
# If not, use 'narrator_layer__name' or 'narrator_layer__id'.
transmitter_qs = transmitter_qs.filter(narrator_layer__slug=layer_slug)
# 4. Use the Prefetch object to inject this filtered list into the Parent
return Hadis.objects.filter(status=True).prefetch_related(
Prefetch('transmitters', queryset=transmitter_qs)
)
class HadisCorrectionsView(ListAPIView):
"""
API view to retrieve corrections for a specific hadis
"""
serializer_class = HadisCorrectionSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'hadis_slug'
@hadis_corrections_swagger
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
# hadis = self.get_object()
# corrections_data = []
# for correction in hadis.hadiscorrection_set.all():
# correction_info = {
# 'id': correction.id,
# 'title': correction.title,
# 'description': correction.description,
# 'translation': correction.translation
# }
# corrections_data.append(correction_info)
# return Response({
# 'hadis_id': hadis.id,
# 'corrections_count': len(corrections_data),
# 'corrections': corrections_data
# })
def get_queryset(self):
hadis_slug = self.kwargs.get('hadis_slug')
try:
hadis = Hadis.objects.get(slug=hadis_slug, status=True)
if not HadisCorrection.objects.filter(hadis=hadis).exists():
return Hadis.objects.none()
return HadisCorrection.objects.filter(hadis=hadis)
except Hadis.DoesNotExist:
return HadisCorrection.objects.none()