Browse Source

feat(hadis): support global arguments filtering and expand search with books and narrators

master
Mohsen Taba 3 days ago
parent
commit
3391664923
  1. 96
      apps/hadis/views/hadis.py

96
apps/hadis/views/hadis.py

@ -366,6 +366,9 @@ class HadisListView(ListAPIView):
search_conditions |= Q(title_narrator__icontains=search_query) search_conditions |= Q(title_narrator__icontains=search_query)
search_conditions |= Q(translation__icontains=search_query) search_conditions |= Q(translation__icontains=search_query)
search_conditions |= Q(tags__title__icontains=search_query) search_conditions |= Q(tags__title__icontains=search_query)
search_conditions |= Q(references__book_reference__title__icontains=search_query)
search_conditions |= Q(transmitters__transmitter__full_name__icontains=search_query)
search_conditions |= Q(transmitters__transmitter__known_as__icontains=search_query)
queryset = queryset.filter(search_conditions) queryset = queryset.filter(search_conditions)
# 👇 2. Apply Status Filter (Supports multiple comma-separated slugs) # 👇 2. Apply Status Filter (Supports multiple comma-separated slugs)
@ -448,7 +451,7 @@ class HadisListView(ListAPIView):
class HadisMainListView(ListAPIView): class HadisMainListView(ListAPIView):
""" """
API view to list Hadis by category_id
API view to list Hadis globally with comprehensive filtering
""" """
serializer_class = HadisListSerializer serializer_class = HadisListSerializer
authentication_classes = [TokenAuthentication] authentication_classes = [TokenAuthentication]
@ -460,7 +463,12 @@ class HadisMainListView(ListAPIView):
return self.list(request, *args, **kwargs) return self.list(request, *args, **kwargs)
def get_queryset(self): def get_queryset(self):
queryset = Hadis.objects.select_related('category__sect', 'hadis_status').prefetch_related(
queryset = Hadis.objects.filter(status=True).select_related(
'category__sect', 'hadis_status'
).annotate(
layer_count=Count('transmitters__narrator_layer', distinct=True)
).prefetch_related(
'tags',
Prefetch( Prefetch(
'references', 'references',
queryset=HadisReference.objects.select_related( queryset=HadisReference.objects.select_related(
@ -478,21 +486,58 @@ class HadisMainListView(ListAPIView):
# Get search parameters # Get search parameters
search_query = self.request.query_params.get('search', None) search_query = self.request.query_params.get('search', None)
sect_filter = self.request.query_params.get('sect', None) or self.request.query_params.get('sect_type', None)
source_type_filter = self.request.query_params.get('source_type', None)
status_filter = self.request.query_params.get('status', None) status_filter = self.request.query_params.get('status', None)
category_filter = self.request.query_params.get('category', None)
author_filter = self.request.query_params.get('author', None) or self.request.query_params.get('source_author', None)
source_filter = self.request.query_params.get('source', None)
category_filter = self.request.query_params.get('category', None) or self.request.query_params.get('category_slug', None)
tag_filter = self.request.query_params.get('tag', None) or self.request.query_params.get('tags', None) tag_filter = self.request.query_params.get('tag', None) or self.request.query_params.get('tags', None)
# Apply search filter # Apply search filter
if search_query: if search_query:
queryset = self.apply_search_filter(queryset, search_query) queryset = self.apply_search_filter(queryset, search_query)
# Apply status filter
# Apply sect filter (e.g. shia, sunni)
if sect_filter:
sects = [s.strip().lower() for s in sect_filter.split(',') if s.strip()]
if sects:
queryset = queryset.filter(category__sect__sect_type__in=sects)
# Apply source_type filter (e.g. hadith, quran, history, fatwa, quote)
if source_type_filter:
source_types = [st.strip().lower() for st in source_type_filter.split(',') if st.strip()]
if source_types:
queryset = queryset.filter(category__source_type__in=source_types)
# Apply status filter (by slug or title)
if status_filter: if status_filter:
queryset = queryset.filter(hadis_status__title__icontains=status_filter)
status_items = [s.strip() for s in status_filter.split(',') if s.strip()]
queryset = queryset.filter(
Q(hadis_status__slug__in=status_items) | Q(hadis_status__title__icontains=status_filter)
)
# Apply author filter
if author_filter:
author_slugs = [a.strip() for a in author_filter.split(',') if a.strip()]
author_q = Q(references__book_reference__author__slug__in=author_slugs)
numeric_ids = [int(a) for a in author_slugs if a.isdigit()]
if numeric_ids:
author_q |= Q(references__book_reference__author_id__in=numeric_ids)
queryset = queryset.filter(author_q)
# Apply source filter (reference books)
if source_filter:
source_slugs = [s.strip() for s in source_filter.split(',') if s.strip()]
if source_slugs:
queryset = queryset.filter(references__book_reference__slug__in=source_slugs)
# Apply category filter # Apply category filter
if category_filter: if category_filter:
queryset = queryset.filter(category__title__icontains=category_filter)
cat_items = [c.strip() for c in category_filter.split(',') if c.strip()]
queryset = queryset.filter(
Q(category__slug__in=cat_items) | Q(category__title__icontains=category_filter)
)
# Apply tag filter # Apply tag filter
if tag_filter: if tag_filter:
@ -518,7 +563,23 @@ class HadisMainListView(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
return queryset.distinct()
def get_serializer_context(self):
"""Add user bookmarks to serializer context to avoid caching issues"""
context = super().get_serializer_context()
user = self.request.user
if user.is_authenticated:
from apps.bookmark.models.bookmark import Bookmark
user_bookmarks = Bookmark.objects.filter(
user=user,
service=Bookmark.ServiceChoices.HADITH,
status=True
).values_list('content_id', flat=True)
context['user_bookmarked_hadis_ids'] = set(user_bookmarks)
else:
context['user_bookmarked_hadis_ids'] = set()
return context
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
queryset = self.get_queryset() queryset = self.get_queryset()
@ -528,19 +589,7 @@ class HadisMainListView(ListAPIView):
if page is not None: if page is not None:
serializer = self.get_serializer(page, many=True) serializer = self.get_serializer(page, many=True)
paginated_response = self.get_paginated_response(serializer.data) paginated_response = self.get_paginated_response(serializer.data)
# Get category titles
category_titles = self.get_category_titles(request)
# Get status titles
status_titles = self.get_status_titles(request)
# Modify the paginated response to include our custom data
response_data = paginated_response.data
# response_data['category_titles'] = self.get_cached_category_titles(request)
# response_data['status_titles'] = self.get_cached_status_titles(request)
return Response(response_data)
return Response(paginated_response.data)
# Fallback for when pagination is disabled # Fallback for when pagination is disabled
serializer = self.get_serializer(queryset, many=True) serializer = self.get_serializer(queryset, many=True)
@ -549,8 +598,6 @@ class HadisMainListView(ListAPIView):
'results': serializer.data 'results': serializer.data
}) })
return Response(response_data)
def get_category_titles(self,request): def get_category_titles(self,request):
"""Get list of category titles based on language""" """Get list of category titles based on language"""
from ..models import HadisCategory from ..models import HadisCategory
@ -579,7 +626,7 @@ class HadisMainListView(ListAPIView):
def apply_search_filter(self, queryset, search_query): def apply_search_filter(self, queryset, search_query):
""" """
Apply search filter across multiple fields including JSONFields. Apply search filter across multiple fields including JSONFields.
Searches in: title, title_narrator, text, translation
Searches in: title, title_narrator, text, translation, tags, book references, transmitters
""" """
from django.db.models import Q from django.db.models import Q
@ -592,6 +639,9 @@ class HadisMainListView(ListAPIView):
search_conditions |= Q(title_narrator__icontains=search_query) search_conditions |= Q(title_narrator__icontains=search_query)
search_conditions |= Q(translation__icontains=search_query) search_conditions |= Q(translation__icontains=search_query)
search_conditions |= Q(tags__title__icontains=search_query) search_conditions |= Q(tags__title__icontains=search_query)
search_conditions |= Q(references__book_reference__title__icontains=search_query)
search_conditions |= Q(transmitters__transmitter__full_name__icontains=search_query)
search_conditions |= Q(transmitters__transmitter__known_as__icontains=search_query)
return queryset.filter(search_conditions) return queryset.filter(search_conditions)

Loading…
Cancel
Save