Browse Source

hadith filters on the category level added

master
Mohsen Taba 1 month ago
parent
commit
46df260813
  1. 63
      apps/hadis/views/hadis.py

63
apps/hadis/views/hadis.py

@ -11,6 +11,8 @@ from ..serializers.category import get_localized_text
from ..models import Transmitters, HadisCategory, Hadis, HadisCollection,HadisTransmitter , HadisCorrection ,HadisReference, HadisStatus ,ReferenceImage from ..models import Transmitters, HadisCategory, Hadis, HadisCollection,HadisTransmitter , HadisCorrection ,HadisReference, HadisStatus ,ReferenceImage
from ..serializers import HadisListSerializer, HadisBasicSerializer, HadisDetailSerializer, HadisCollectionListSerializer, HadisSyncSerializer,HadisCorrectionSerializer,HadisTransmitterListSerializer , SimpleCategory, NarratorLayerSerializer , PinnedHadisCollectionSerializer from ..serializers import HadisListSerializer, HadisBasicSerializer, HadisDetailSerializer, HadisCollectionListSerializer, HadisSyncSerializer,HadisCorrectionSerializer,HadisTransmitterListSerializer , SimpleCategory, NarratorLayerSerializer , PinnedHadisCollectionSerializer
from ..docs import arguments_filters_swagger ,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, hadis_layers_swagger from ..docs import arguments_filters_swagger ,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, hadis_layers_swagger
from django.db.models import Q
from ..serializers.category import get_localized_text
from rest_framework import status from rest_framework import status
@ -161,9 +163,6 @@ class HadisListView(ListAPIView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) return self.list(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
# 1. Run the standard list logic (get pagination, filter, results) # 1. Run the standard list logic (get pagination, filter, results)
response = super().list(request, *args, **kwargs) response = super().list(request, *args, **kwargs)
@ -175,18 +174,15 @@ class HadisListView(ListAPIView):
# 3. Serialize this single category for the Hero section # 3. Serialize this single category for the Hero section
category_data = SimpleCategory(category_obj).data category_data = SimpleCategory(category_obj).data
# 👇 4. NEW LOGIC: Check if it's a Quran Category and fetch verse data
# 4. Check if it's a Quran Category and fetch verse data
quran_data = None quran_data = None
if category_obj.source_type == HadisCategory.SourceType.QURAN: if category_obj.source_type == HadisCategory.SourceType.QURAN:
# سعی می‌کنیم آبجکت قرآن متصل به این کتگوری رو بگیریم
try: try:
# استفاده از prefetch_related برای ترجمه‌های ثانویه جهت جلوگیری از N+1
from ..models.category import CategoryQuranVerse from ..models.category import CategoryQuranVerse
verse_obj = CategoryQuranVerse.objects.prefetch_related( verse_obj = CategoryQuranVerse.objects.prefetch_related(
'secondary_translations' 'secondary_translations'
).get(category=category_obj) ).get(category=category_obj)
# سریالایز کردن دیتای قرآن (با کانتکست ریکوئست برای زبان)
from ..serializers.category import CategoryQuranVerseSerializer from ..serializers.category import CategoryQuranVerseSerializer
quran_data = CategoryQuranVerseSerializer( quran_data = CategoryQuranVerseSerializer(
verse_obj, verse_obj,
@ -195,7 +191,20 @@ class HadisListView(ListAPIView):
except CategoryQuranVerse.DoesNotExist: except CategoryQuranVerse.DoesNotExist:
pass pass
# 5. Inject it into the response data
# 👇 5. NEW LOGIC: Fetch all statuses for frontend filtering UI
lang = getattr(request, "LANGUAGE_CODE", None) or "fa"
statuses_list = [
{
"id": status.id,
"slug": status.slug,
"title": get_localized_text(status.title, request=request, language_code=lang) or "",
"color": status.color,
"main_color_code": status.main_color_code,
}
for status in HadisStatus.objects.all().order_by('order')
]
# 6. Inject it into the response data
if isinstance(response.data, dict): if isinstance(response.data, dict):
ordered_data = {} ordered_data = {}
for key in ['count', 'next', 'previous']: for key in ['count', 'next', 'previous']:
@ -203,10 +212,11 @@ class HadisListView(ListAPIView):
ordered_data[key] = response.data[key] ordered_data[key] = response.data[key]
ordered_data['current_category'] = category_data ordered_data['current_category'] = category_data
# 👇 دیتای قرآن را تزریق می‌کنیم
ordered_data['quran_data'] = quran_data ordered_data['quran_data'] = quran_data
# 👇 تزریق لیست استاتوس‌ها قبل از نتایج
ordered_data['statuses'] = statuses_list
if 'results' in response.data: if 'results' in response.data:
ordered_data['results'] = response.data['results'] ordered_data['results'] = response.data['results']
response.data = ordered_data response.data = ordered_data
@ -222,12 +232,36 @@ class HadisListView(ListAPIView):
category__slug=category_slug, category__slug=category_slug,
status=True status=True
).annotate( ).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) layer_count=Count('transmitters__narrator_layer', distinct=True)
).select_related('category') ).select_related('category')
# 👇 1. Apply Search Filter
search_query = self.request.query_params.get('search', None)
if search_query:
search_conditions = Q(text__icontains=search_query)
search_conditions |= Q(title__icontains=search_query)
search_conditions |= Q(title_narrator__icontains=search_query)
search_conditions |= Q(translation__icontains=search_query)
queryset = queryset.filter(search_conditions)
# 👇 2. Apply Status Filter (Supports multiple comma-separated slugs)
status_filter = self.request.query_params.get('status', None)
if status_filter:
status_slugs = [s.strip() for s in status_filter.split(',')]
queryset = queryset.filter(hadis_status__slug__in=status_slugs)
# 👇 3. Apply Transmitter Filter (Supports multiple comma-separated slugs)
transmitter_filter = self.request.query_params.get('transmitter', None)
if transmitter_filter:
transmitter_slugs = [t.strip() for t in transmitter_filter.split(',')]
queryset = queryset.filter(transmitters__transmitter__slug__in=transmitter_slugs)
# 👇 4. Apply Source Filter (Supports multiple comma-separated slugs)
source_filter = self.request.query_params.get('source', None)
if source_filter:
source_slugs = [s.strip() for s in source_filter.split(',')]
queryset = queryset.filter(references__book_reference__slug__in=source_slugs)
# Filter by bookmarks if provided # Filter by bookmarks if provided
is_bookmark = self.request.query_params.get('is_bookmark', '').lower() is_bookmark = self.request.query_params.get('is_bookmark', '').lower()
if is_bookmark == 'true' and self.request.user.is_authenticated: if is_bookmark == 'true' and self.request.user.is_authenticated:
@ -239,7 +273,8 @@ class HadisListView(ListAPIView):
).values_list('content_id', flat=True) ).values_list('content_id', flat=True)
queryset = queryset.filter(id__in=bookmarked_ids) queryset = queryset.filter(id__in=bookmarked_ids)
return queryset
# ❗️ distinct() برای جلوگیری از دابلیکیت شدن احادیث به خاطر ManyToMany ها الزامی است
return queryset.distinct()
def get_serializer_context(self): def get_serializer_context(self):
"""Add user bookmarks to serializer context to avoid caching issues""" """Add user bookmarks to serializer context to avoid caching issues"""

Loading…
Cancel
Save