|
|
|
@ -620,3 +620,159 @@ class HadisFiltersView(ListAPIView): |
|
|
|
} |
|
|
|
|
|
|
|
return Response(response_data) |
|
|
|
|
|
|
|
from rest_framework.views import APIView |
|
|
|
from rest_framework.response import Response |
|
|
|
from rest_framework.permissions import AllowAny |
|
|
|
from rest_framework.authentication import TokenAuthentication |
|
|
|
from drf_yasg.utils import swagger_auto_schema |
|
|
|
from django.utils.translation import get_language |
|
|
|
|
|
|
|
from apps.hadis.models import HadisStatus, HadisCategory, BookReference, Transmitters |
|
|
|
from drf_yasg import openapi |
|
|
|
class HadisFiltersSyncAPIView(APIView): |
|
|
|
""" |
|
|
|
API view to return all filter data for hadis (Sync API for Mobile App) |
|
|
|
Returns statuses, categories, sources (books), and narrators. |
|
|
|
Optimized for offline client-side searching and sorting. |
|
|
|
""" |
|
|
|
permission_classes = [AllowAny] |
|
|
|
authentication_classes = [TokenAuthentication] |
|
|
|
|
|
|
|
@swagger_auto_schema( |
|
|
|
operation_description=( |
|
|
|
"Sync API for Flutter/mobile clients: returns flat hadis filter data for offline " |
|
|
|
"searching and local filtering. Titles are localized from multilingual fields based " |
|
|
|
"on the active request language." |
|
|
|
), |
|
|
|
operation_summary="Sync Hadis Filters", |
|
|
|
tags=['Dobodbi - Hadis'], |
|
|
|
manual_parameters=[ |
|
|
|
openapi.Parameter( |
|
|
|
'Accept-Language', |
|
|
|
openapi.IN_HEADER, |
|
|
|
description="Language code for localized titles, for example `en`, `fa`, `ar`, `ur`, or `ru`.", |
|
|
|
type=openapi.TYPE_STRING, |
|
|
|
required=False, |
|
|
|
) |
|
|
|
], |
|
|
|
responses={ |
|
|
|
status.HTTP_200_OK: openapi.Response( |
|
|
|
description="Flat filter payload for hadis categories, statuses, sources, and narrators.", |
|
|
|
examples={ |
|
|
|
"application/json": { |
|
|
|
"statuses": [ |
|
|
|
{ |
|
|
|
"id": 133, |
|
|
|
"slug": "sahih", |
|
|
|
"title": "Authentic", |
|
|
|
"order": 1, |
|
|
|
"color": "green", |
|
|
|
"main_color_code": "#1DAC43" |
|
|
|
} |
|
|
|
], |
|
|
|
"categories": [ |
|
|
|
{ |
|
|
|
"id": 1036, |
|
|
|
"slug": "general-hadiths", |
|
|
|
"title": "General Hadiths", |
|
|
|
"order": 1 |
|
|
|
} |
|
|
|
], |
|
|
|
"sources": [ |
|
|
|
{ |
|
|
|
"id": 2538, |
|
|
|
"slug": "man-la-yahduruhu-al-faqih", |
|
|
|
"title": "Man La Yahduruhu al-Faqih", |
|
|
|
"search_keywords": "Shaykh al-Saduq" |
|
|
|
} |
|
|
|
], |
|
|
|
"narrators": [ |
|
|
|
{ |
|
|
|
"id": 501, |
|
|
|
"slug": "muhammad-ibn-muslim", |
|
|
|
"title": "Muhammad ibn Muslim", |
|
|
|
"search_aliases": "Abu Ja'far" |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
} |
|
|
|
) |
|
|
|
} |
|
|
|
) |
|
|
|
def get(self, request, *args, **kwargs): |
|
|
|
# تشخیص زبان برای ارسال دیتای لوکالایز شده |
|
|
|
lang = getattr(request, "LANGUAGE_CODE", None) or get_language() or "ru" |
|
|
|
|
|
|
|
# ۱. استتوسها (مرتبشده بر اساس فیلد order) |
|
|
|
statuses = [ |
|
|
|
{ |
|
|
|
"id": status.id, |
|
|
|
"slug": status.slug, |
|
|
|
"title": get_localized_text(status.title, request=request, language_code=lang) or "", |
|
|
|
"order": status.order, |
|
|
|
"color": status.color, |
|
|
|
"main_color_code": status.main_color_code, |
|
|
|
} |
|
|
|
for status in HadisStatus.objects.all().order_by('order') |
|
|
|
] |
|
|
|
|
|
|
|
# ۲. دستهبندیها (مرتبشده بر اساس فیلد order) |
|
|
|
categories = [ |
|
|
|
{ |
|
|
|
"id": cat.id, |
|
|
|
"slug": cat.slug, |
|
|
|
"title": get_localized_text(cat.title, request=request, language_code=lang) or "", |
|
|
|
"order": cat.order, |
|
|
|
} |
|
|
|
for cat in HadisCategory.objects.all().order_by('order') |
|
|
|
] |
|
|
|
|
|
|
|
# ۳. منابع / کتابها |
|
|
|
sources = [] |
|
|
|
# استفاده از prefetch_related برای جلوگیری از مشکل N+1 Query هنگام گرفتن نویسندهها |
|
|
|
books = BookReference.objects.prefetch_related('authors').all().order_by('order', '-id') |
|
|
|
|
|
|
|
for book in books: |
|
|
|
# استخراج نام نویسندهها برای سرچ آفلاین فلاتر |
|
|
|
authors_names = [ |
|
|
|
get_localized_text(author.name, request=request, language_code=lang) or "" |
|
|
|
for author in book.authors.all() |
|
|
|
] |
|
|
|
|
|
|
|
sources.append({ |
|
|
|
"id": book.id, |
|
|
|
"slug": book.slug, |
|
|
|
"title": get_localized_text(book.title, request=request, language_code=lang) or "", |
|
|
|
# تمام اسمهای نویسندهها را به هم میچسبانیم تا فلاتر بتواند روی آنها سرچ بزند |
|
|
|
"search_keywords": " ".join(authors_names).strip() |
|
|
|
}) |
|
|
|
|
|
|
|
# ۴. راویان (نریتورها) |
|
|
|
narrators = [] |
|
|
|
transmitters = Transmitters.objects.all().order_by('id') |
|
|
|
|
|
|
|
for narrator in transmitters: |
|
|
|
# گرفتن نامهای مستعار |
|
|
|
known_as = get_localized_text(narrator.known_as, request=request, language_code=lang) or "" |
|
|
|
nickname = get_localized_text(narrator.nickname, request=request, language_code=lang) or "" |
|
|
|
kunya = get_localized_text(narrator.kunya, request=request, language_code=lang) or "" |
|
|
|
|
|
|
|
# تجمیع نامهای جایگزین |
|
|
|
search_aliases = f"{known_as} {nickname} {kunya}".strip() |
|
|
|
|
|
|
|
narrators.append({ |
|
|
|
"id": narrator.id, |
|
|
|
"slug": narrator.slug, |
|
|
|
"title": get_localized_text(narrator.full_name, request=request, language_code=lang) or "", |
|
|
|
# فلاتر روی این فیلد + title سرچ میزند |
|
|
|
"search_aliases": search_aliases |
|
|
|
}) |
|
|
|
|
|
|
|
# خروجی نهایی بدون پجینیشن |
|
|
|
return Response({ |
|
|
|
"statuses": statuses, |
|
|
|
"categories": categories, |
|
|
|
"sources": sources, |
|
|
|
"narrators": narrators |
|
|
|
}) |