From 534dc40adc59a5316674f63475efd452d1918142 Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Sun, 28 Jun 2026 15:17:04 +0330 Subject: [PATCH] sync narrators updated to latest changes --- apps/hadis/serializers/hadis.py | 48 ++++++++++++++++++++++++++++++--- apps/hadis/views/transmitter.py | 22 ++++++++++----- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/apps/hadis/serializers/hadis.py b/apps/hadis/serializers/hadis.py index 05f0502..b7d4d73 100644 --- a/apps/hadis/serializers/hadis.py +++ b/apps/hadis/serializers/hadis.py @@ -575,8 +575,48 @@ class TransmitterSyncSerializer(serializers.ModelSerializer): 'description': get_localized_text(obj.description, request), 'thumbnail': obj.thumbnail.url if obj.thumbnail else None, 'share_link': obj.share_link, + 'tadlis': obj.tadlis, + 'ikhtilat': obj.ikhtilat, + 'companion_type': obj.companion_type, + 'relatives': self._get_relatives(obj, request), } + def _get_relatives(self, obj, request): + relatives_qs = obj.relatives.all() + + grouped = {} + for rel in relatives_qs: + rel_type = rel.relation_type + slug = rel.narrator.slug if rel.narrator else None + + name = rel.name + if rel.narrator and not name: + name = get_localized_text(rel.narrator.full_name, request) + + item = { + "name": name, + "slug": slug + } + + if rel_type not in grouped: + grouped[rel_type] = { + "relation_value": get_localized_text(rel.relation_value, request) if rel.relation_value else None, + "arabic_relation_value": get_arabic_localized_text(rel.relation_value) if rel.relation_value else None, + "items": [] + } + grouped[rel_type]["items"].append(item) + + result = [] + for rel_type, data in grouped.items(): + result.append({ + "relation_type": rel_type, + "relation_value": data["relation_value"], + "arabic_relation_value": data["arabic_relation_value"], + "members": data["items"] + }) + + return result + def get_scholars_opinions(self, obj): """Get all scholarly opinions about this transmitter""" request = self.context.get('request') # ← FIX: Define request @@ -585,12 +625,14 @@ class TransmitterSyncSerializer(serializers.ModelSerializer): { 'id': opinion.id, 'scholar_name': get_localized_text(opinion.scholar_name, request), + 'arabic_scholar_name': get_arabic_localized_text(opinion.scholar_name), 'scholar': { 'id': opinion.scholar.id, 'name': get_localized_text(opinion.scholar.name, request), 'slug': opinion.scholar.slug } if opinion.scholar else None, 'opinion_text': get_localized_text(opinion.opinion_text, request), + 'arabic_opinion_text': get_arabic_localized_text(opinion.opinion_text), 'status': { 'id': opinion.status.id, 'title': get_localized_text(opinion.status.title, request), @@ -614,10 +656,8 @@ class TransmitterSyncSerializer(serializers.ModelSerializer): ).data def get_hadis(self, obj): - # چون از related_name='hadises' در مدل HadisTransmitter استفاده شده، - # لیست تمام رکوردهای واسط را می‌گیریم. - # استفاده از set باعث می‌شود اگر یک راوی در ۲ سند از یک حدیث بود، آیدی آن حدیث تکراری نشود. - return list(set(item.hadis_id for item in obj.hadises.all() if item.hadis_id)) + categories_map = self.context.get('categories_map', {}) + return list(categories_map.get(int(obj.id), set())) def get_relations(self, obj): """ استخراج آنی آیدی اساتید و شاگردان از کانتکست بدون اجرای کوئری اضافه diff --git a/apps/hadis/views/transmitter.py b/apps/hadis/views/transmitter.py index 9611858..523b188 100644 --- a/apps/hadis/views/transmitter.py +++ b/apps/hadis/views/transmitter.py @@ -132,7 +132,7 @@ class TransmitterSyncView(ListAPIView): return self.list(request, *args, **kwargs) def get_queryset(self): - from ..models import TransmitterOriginalText + from ..models import TransmitterOriginalText, TransmitterRelative return ( Transmitters.objects @@ -152,28 +152,35 @@ class TransmitterSyncView(ListAPIView): 'references__images' ) ), - # این مورد را هم برای بهینگی حافظه رم لیمیت می‌کنیم تا کل فیلدها لود نشوند - Prefetch('hadises', queryset=HadisTransmitter.objects.only('id', 'hadis_id', 'transmitter_id')) + Prefetch('relatives', queryset=TransmitterRelative.objects.select_related('narrator')) ) .order_by('id') ) def list(self, request, *args, **kwargs): - # 🧠 ۱. واکشی لینک‌ها با values_list برای جلوگیری از هرگونه تداخل دیکشنری + # 🧠 ۱. واکشی لینک‌ها با values_list برای جلوگیری از هرگونه تداخل دیکشنری و افزایش سرعت all_links = HadisTransmitter.objects.values_list( - 'hadis_id', 'chain_index', 'order', 'transmitter_id' + 'hadis_id', 'chain_index', 'order', 'transmitter_id', 'hadis__category_id' ) # 🧠 ۲. بازسازی کل زنجیره‌های حدیثی به صورت کاملاً ایمن و عددی chains = {} - for hadis_id, chain_index, order, transmitter_id in all_links: + categories_map = {} + for hadis_id, chain_index, order, transmitter_id, category_id in all_links: if transmitter_id is None: continue + tx_id = int(transmitter_id) + + if tx_id not in categories_map: + categories_map[tx_id] = set() + if category_id is not None: + categories_map[tx_id].add(int(category_id)) + key = (int(hadis_id), int(chain_index)) if key not in chains: chains[key] = {} - chains[key][int(order)] = int(transmitter_id) + chains[key][int(order)] = tx_id # دایرکتوری‌های نگاشت روابط teachers_map = {} @@ -201,6 +208,7 @@ class TransmitterSyncView(ListAPIView): context = self.get_serializer_context() context['teachers_map'] = teachers_map context['students_map'] = students_map + context['categories_map'] = categories_map serializer = self.get_serializer_class()( queryset,