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.
 
 

296 lines
11 KiB

from django.utils.translation import get_language
from rest_framework import serializers
from django.utils.translation import gettext_lazy as _
# from django.db.models import Count
from ..models import HadisSect, HadisCategory, Hadis , HadisCategory
from django.utils.translation import get_language
def get_localized_text(json_list, request=None, fallback_lang="en"):
"""
Extract localized text from a JSON list based on request's language.
Expects: [{"language_code": "en", "text": "..."}, ...]
Returns: Single text string or None
"""
if not json_list or not isinstance(json_list, list):
return None
# Get target language
language_code = getattr(request, "LANGUAGE_CODE", None) if request else None
if not language_code:
language_code = get_language() or fallback_lang
# 1) Exact match
for item in json_list:
if isinstance(item, dict) and item.get("language_code") == language_code:
return item.get("text")
# 2) Fallback to English
for item in json_list:
if isinstance(item, dict) and item.get("language_code") == "en":
return item.get("text")
# 3) First available
if json_list and isinstance(json_list[0], dict):
return json_list[0].get("text")
return None
class LocalizedField(serializers.Field):
"""
Extracts the correct language from a JSON list
based on request.LANGUAGE_CODE (LocaleMiddleware),
with sensible fallbacks.
"""
def to_representation(self, value):
# Expecting value to be a list of {"language_code": "...", "text": "..."}
if not value or not isinstance(value, list):
return None
# Get language from request, then fall back to global language / 'fa'
request = self.context.get("request")
language_code = getattr(request, "LANGUAGE_CODE", None) if request else None
if not language_code:
language_code = get_language() or "fa" # global active language [web:164][web:172]
# 1) Exact match with request language
for item in value:
if item.get("language_code") == language_code:
return item.get("text")
# 2) Fallback to English
for item in value:
if item.get("language_code") == "en":
return item.get("text")
# 3) Fallback to first item
first = value[0]
return first.get("text") if isinstance(first, dict) else None
class HadisCategorySectListSerializer(serializers.ModelSerializer):
"""Serializer for HadisSect list with grouped response"""
source_types = serializers.SerializerMethodField()
title = LocalizedField()
class Meta:
model = HadisSect
fields = ['id', 'title', 'description', 'source_types']
def get_source_types(self, obj):
"""Get unique source types for this sect's categories"""
source_types = HadisCategory.objects.filter(
sect=obj
).values_list('source_type', flat=True).distinct()
return list(source_types)
class HadisCategoryTreeSerializer(serializers.ModelSerializer):
title = LocalizedField()
"""Serializer for HadisCategory tree structure"""
sect_id = serializers.IntegerField(source='sect.id', read_only=True)
sect_type = serializers.CharField(source='sect.sect_type', read_only=True)
children = serializers.SerializerMethodField()
class Meta:
model = HadisCategory
fields = ['id', 'title', 'source_type', 'sect_id', 'sect_type', 'children']
def get_name(self, obj):
"""Get category name based on request language"""
request = self.context.get('request')
language_code = getattr(request, 'LANGUAGE_CODE', 'en')
return obj.get_translation(language_code) if hasattr(obj, 'get_translation') else obj.title
def get_children(self, obj):
"""Get all active children categories (no filtering by hadis/children)"""
children = obj.get_children().filter(sect=obj.sect).order_by('order')
return [self.to_dict(cat) for cat in children]
def get_hadis_count(self, obj):
"""Get direct hadis count for this category only"""
return Hadis.objects.filter(category=obj, status=True).count()
def get_has_hadis(self, obj):
"""Check if category can have hadis (no active children) and has hadis"""
# Check if category has active children
has_active_children = obj.get_children().filter(sect=obj.sect).exists()
# If has active children, cannot have hadis
if has_active_children:
return False
# If no active children, check if has hadis
return Hadis.objects.filter(category=obj, status=True).exists()
def get_xmind_file(self, obj):
"""Get absolute URL for xmind file"""
if obj.xmind_file:
request = self.context.get('request')
if request:
return request.build_absolute_uri(obj.xmind_file.url)
return obj.xmind_file.url
return None
def get_has_xmind_file(self, obj):
"""Check if category has xmind file"""
return bool(obj.xmind_file)
def get_thumbnail(self, obj):
"""Get absolute URL for thumbnail"""
if hasattr(obj, 'thumbnail') and obj.thumbnail:
request = self.context.get('request')
if request:
return request.build_absolute_uri(obj.thumbnail.url)
return obj.thumbnail.url
return None
def get_hadis_index(self, obj):
"""Get list of hadis numbers in this category (not including children)"""
return list(
Hadis.objects.filter(
category=obj,
status=True
).order_by('number').values_list('number', flat=True)
)
def get_children_count(self, obj):
"""Get count of active children categories"""
return obj.get_children().filter(sect=obj.sect).count()
def to_dict(self, category, request=None):
"""Convert category to dict, applying localization"""
if request is None:
request = self.context.get('request')
return {
'id': category.id,
'title': get_localized_text(category.title, request), # <-- use helper
'description': get_localized_text(category.description, request), # <-- use helper
'slug': category.slug,
'source_type': category.source_type,
'hadis_count': self.get_hadis_count(category),
'has_hadis': self.get_has_hadis(category),
'children_count': self.get_children_count(category),
'order': category.order,
'thumbnail': self.get_thumbnail(category),
'xmind_file': self.get_xmind_file(category),
'has_xmind_file': self.get_has_xmind_file(category),
'children': [
self.to_dict(child, request) # recursively apply
for child in category.children.all()
]
}
class HadisCategorySelectSerializer(serializers.ModelSerializer):
"""Serializer for HadisCategory Selection Flow"""
sect_id = serializers.IntegerField(source='sect.id', read_only=True)
sect_type = serializers.CharField(source='sect.sect_type', read_only=True)
# children = serializers.SerializerMethodField()
children_count = serializers.SerializerMethodField()
has_hadis = serializers.SerializerMethodField()
hadis_count= serializers.SerializerMethodField()
title = LocalizedField()
description =LocalizedField()
class Meta:
model = HadisCategory
fields = ['id', 'title', 'source_type','slug', 'sect_id',
'sect_type','description','children_count','has_hadis','hadis_count']
def get_has_hadis(self, obj):
"""Check if category can have hadis (no active children) and has hadis"""
# Check if category has active children
has_active_children = obj.get_children().filter(sect=obj.sect).exists()
# If has active children, cannot have hadis
if has_active_children:
return False
# If no active children, check if has hadis
return Hadis.objects.filter(category=obj, status=True).exists()
def get_children_count(self, obj):
"""Get count of active children categories that have children or hadis"""
children = obj.get_children().filter(sect=obj.sect)
return len(children)
def get_hadis_count(self,obj):
return len(Hadis.objects.filter(category=obj))
class HadisCategorySelectSourceSerializer(serializers.ModelSerializer):
"""Serializer for HadisCategory Selection Flow"""
sect_id = serializers.IntegerField(source='sect.id', read_only=True)
sect_type = serializers.CharField(source='sect.sect_type', read_only=True)
children_count = serializers.SerializerMethodField()
has_hadis = serializers.SerializerMethodField()
hadis_count = serializers.SerializerMethodField()
title = LocalizedField()
description = LocalizedField()
class Meta:
model = HadisCategory
fields = ['id', 'title', 'source_type','slug', 'sect_id',
'sect_type','description','children_count','has_hadis','hadis_count']
def get_has_hadis(self, obj):
"""Check if category can have hadis (no active children) and has hadis"""
# Check if category has active children
has_active_children = obj.get_children().filter(sect=obj.sect).exists()
# If has active children, cannot have hadis
if has_active_children:
return False
# If no active children, check if has hadis
return Hadis.objects.filter(category=obj, status=True).exists()
def get_children_count(self, obj):
"""Get count of active children categories that have children or hadis"""
children = obj.get_children().filter(sect=obj.sect , source_type= obj.source_type)
return len(children)
def get_hadis_count(self,obj):
return len(Hadis.objects.filter(category=obj))
class CategorySerializer(serializers.ModelSerializer):
sect_id = serializers.IntegerField(source='sect.id', read_only=True)
sect_type = serializers.CharField(source='sect.sect_type', read_only=True)
children_count = serializers.SerializerMethodField()
has_hadis =serializers.SerializerMethodField()
hadis_count=serializers.SerializerMethodField()
title = LocalizedField()
description = LocalizedField()
class Meta:
model = HadisCategory
fields = ['id', 'title', 'sect_id', 'sect_type','source_type',
'description','slug',
'children_count','has_hadis','hadis_count']
def get_children_count(self, obj):
"""Get count of active children categories that have children or hadis"""
children = obj.get_children().filter(sect=obj.sect)
return len(children)
def get_has_hadis(self,obj):
return Hadis.objects.filter(category=obj).exists()
def get_hadis_count(self,obj):
return len(Hadis.objects.filter(category=obj))
# def get_title(self,obj):
# # ✅ Get language from request
# request = self.context.get('request')
# lang = request.query_params.get('lang', 'ru') if request else 'ru'
# # ✅ CALL THE MODEL METHOD!
# return obj.get_title(lang)