Browse Source

feat: Add Hadis category serializers featuring localized fields, hierarchical data, and related counts, and create a new Hadis view file.

master
Mohsen Taba 2 months ago
parent
commit
e30f301809
  1. 9
      apps/hadis/serializers/category.py
  2. 151
      apps/hadis/views/hadis.py

9
apps/hadis/serializers/category.py

@ -6,9 +6,9 @@ from django.utils.translation import gettext_lazy as _
from ..models import HadisSect, HadisCategory, Hadis , HadisCategory from ..models import HadisSect, HadisCategory, Hadis , HadisCategory
from django.utils.translation import get_language from django.utils.translation import get_language
def get_localized_text(json_list, request=None, fallback_lang="en"):
def get_localized_text(json_list, request=None, fallback_lang="en", language_code=None):
""" """
Extract localized text from a JSON list based on request's language.
Extract localized text from a JSON list based on language.
Expects: [{"language_code": "en", "text": "..."}, ...] Expects: [{"language_code": "en", "text": "..."}, ...]
Returns: Single text string or None Returns: Single text string or None
@ -16,8 +16,9 @@ def get_localized_text(json_list, request=None, fallback_lang="en"):
if not json_list or not isinstance(json_list, list): if not json_list or not isinstance(json_list, list):
return None return None
# Get target language
language_code = getattr(request, "LANGUAGE_CODE", None) if request else None
# Get target language if not provided
if not language_code:
language_code = getattr(request, "LANGUAGE_CODE", None) if request else None
if not language_code: if not language_code:
language_code = get_language() or fallback_lang language_code = get_language() or fallback_lang

151
apps/hadis/views/hadis.py

@ -72,15 +72,152 @@ class HadisSyncView(ListAPIView):
return self.list(request, *args, **kwargs) return self.list(request, *args, **kwargs)
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
from django.utils.translation import get_language
# 1. PRE-FETCH DATA ONCE
queryset = self.get_queryset() queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
response_data = {
'count': queryset.count(),
'results': serializer.data
}
return Response(response_data)
# Get language once for the entire bulk operation
lang = getattr(request, "LANGUAGE_CODE", None) or get_language() or "en"
# Pre-calculate base URL for images
media_url = request.build_absolute_uri('/')[:-1] # Remove trailing slash
results = []
for obj in queryset:
# --- Detail Block ---
status_block = None
if obj.hadis_status:
status_block = {
'id': obj.hadis_status.id,
'title': get_localized_text(obj.hadis_status.title, language_code=lang),
'color': obj.hadis_status.color,
'main_color_code': obj.hadis_status.main_color_code,
}
tags_block = [
{'id': tag.id, 'title': get_localized_text(tag.title, language_code=lang)}
for tag in obj.tags.all()
]
references_block = []
reference_images_block = []
for ref in obj.references.all():
book = ref.book_reference
references_block.append({
'id': ref.id,
'title': get_localized_text(book.title, language_code=lang) if book else None,
'authors': [
{'id': a.id, 'name': get_localized_text(a.name, language_code=lang)}
for a in (book.authors.all() if book else [])
],
'description': book.description if book else None,
})
for img in ref.images.all():
reference_images_block.append({
'id': img.id,
'thumbnail': f"{media_url}{img.thumbnail.url}" if img.thumbnail else None,
'priority': img.priority,
})
address_details_list = []
if hasattr(obj, 'address_details') and obj.address_details and isinstance(obj.address_details, list):
address_details_list = sorted(obj.address_details, key=lambda x: x.get('priority', 0))
detail_block = {
'address': get_localized_text(obj.address, language_code=lang),
'address_details': address_details_list,
'hadis_status': status_block,
'status_text': get_localized_text(obj.hadis_status_text, language_code=lang),
'share_link': obj.share_link,
'links': obj.links,
'tags': tags_block,
'references': references_block,
'reference_images': reference_images_block,
}
# --- Narrators Block ---
transmitters_data = []
for tr_rel in obj.transmitters.all():
t = tr_rel.transmitter
layer = tr_rel.narrator_layer
rel_data = None
if t.reliability:
rel_data = {
'id': t.reliability.id,
'title': get_localized_text(t.reliability.title, language_code=lang),
'color': t.reliability.color,
'main_color_code': t.reliability.main_color_code,
}
transmitters_data.append({
'id': t.id,
'name': get_localized_text(t.full_name, language_code=lang),
'slug': t.slug,
'known_as': get_localized_text(t.known_as, language_code=lang),
'nickname': get_localized_text(t.nickname, language_code=lang),
'reliability': rel_data,
'layer_level': layer.number if layer else None,
'layer_name': get_localized_text(layer.name, language_code=lang) if layer else None,
'is_gap': tr_rel.is_gap,
'birth_year_hijri': t.birth_year_hijri,
'death_year_hijri': t.death_year_hijri,
'order': tr_rel.order,
})
narrators_block = {
'description': get_localized_text(obj.description, language_code=lang),
'transmitters': transmitters_data,
}
# --- Explanations (Complex Logic) ---
explanation_data = []
if hasattr(obj, 'explanations') and obj.explanations and isinstance(obj.explanations, list):
for item in obj.explanations:
if isinstance(item, dict) and item.get('language_code') == lang:
explanation_data.append({
'title': item.get('title', ''),
'description': item.get('description', '')
})
if not explanation_data and obj.explanation:
explanation_data = get_localized_text(obj.explanation, language_code=lang)
else:
explanation_data = explanation_data if explanation_data else None
# --- Corrections ---
corrections_block = []
for c in obj.hadiscorrection_set.all():
corrections_block.append({
'id': c.id,
'title': get_localized_text(c.title, language_code=lang),
'description': get_localized_text(c.description, language_code=lang),
'translation': get_localized_text(c.translation, language_code=lang),
'share_link': c.share_link,
})
# --- Assemble Hadis Item ---
results.append({
'id': obj.id,
'number': obj.number,
'slug': obj.slug,
'category_id': obj.category_id,
'title': get_localized_text(obj.title, language_code=lang),
'title_narrator': get_localized_text(obj.title_narrator, language_code=lang),
'text': obj.text, # Usually JSON structure in our app
'translation': get_localized_text(obj.translation, language_code=lang),
'detail': detail_block,
'narrators': narrators_block,
'explanations': explanation_data,
'corrections': corrections_block,
})
return Response({
'count': len(results),
'results': results
})
class HadisListView(ListAPIView): class HadisListView(ListAPIView):

Loading…
Cancel
Save