diff --git a/apps/hadis/management/commands/seed_transmitters.py b/apps/hadis/management/commands/seed_transmitters.py index 364f51f..9e06710 100644 --- a/apps/hadis/management/commands/seed_transmitters.py +++ b/apps/hadis/management/commands/seed_transmitters.py @@ -1,270 +1,109 @@ import random from django.core.management.base import BaseCommand -from django.core.exceptions import ObjectDoesNotExist -# Ensure these imports match your actual app structure -from apps.hadis.models import ( - NarratorLayer, - Transmitters, - HadisTransmitter, - TransmitterOpinion, - TransmitterOriginalText, - Hadis, - TransmitterReliability -) +from django.db import transaction +# REPLACE 'apps.hadis.models' WITH YOUR ACTUAL APP PATH +from apps.hadis.models import Transmitters, TransmitterOpinion, TransmitterOriginalText, OpinionStatus class Command(BaseCommand): - help = 'Seeds the database with mock Transmitters, Layers, and Chains' - - def create_json_field(self, en_text, fa_text, ru_text): - """Helper to create your specific JSON format with Russian added""" - return [ - {"text": en_text, "language_code": "en"}, - {"text": fa_text, "language_code": "fa"}, - {"text": ru_text, "language_code": "ru"} - ] + help = 'Seeds TransmitterOpinion and TransmitterOriginalText for transmitters 84-91' def handle(self, *args, **options): - self.stdout.write("--- Starting Transmitters Mock Data Generation (Trilingual) ---") + self.stdout.write("Starting Transmitter Details seeding...") # --------------------------------------------------------- - # 1. Create Narrator Layers (Tabaqat) + # 1. Fetch Target Objects # --------------------------------------------------------- - self.stdout.write("Creating Narrator Layers...") - layers_data = [ - (1, "Companions", "صحابه", "Сподвижники", - "Companions of the Prophet", "یاران پیامبر", "Сподвижники Пророка"), - (2, "Successors", "تابعین", "Табиины", - "The generation after Companions", "نسل بعد از صحابه", "Поколение после сподвижников"), - (3, "Successors of Successors", "تابع تابعین", "Таби ат-Табиин", - "The third generation", "نسل سوم", "Третье поколение передатчиков"), - (4, "Students of the Imams", "شاگردان ائمه", "Ученики Имамов", - "Direct students of the Imams", "شاگردان مستقیم ائمه", "Прямые ученики Имамов"), - (5, "Minor Narrators", "راویان جزئی", "Малые передатчики", - "Lesser known narrators", "راویان کمتر شناخته شده", "Малоизвестные передатчики"), - ] + transmitters = Transmitters.objects.filter(id__range=(84, 91)) + + if not transmitters.exists(): + self.stdout.write(self.style.ERROR("No Transmitters found in range 84-91.")) + return + + # Fetch OpinionStatus objects + # We need these to populate the 'status' ForeignKey in TransmitterOpinion + statuses = list(OpinionStatus.objects.all()) + + # Fallback: If no statuses exist, we can't create opinions safely without knowing your Status model fields. + if not statuses: + self.stdout.write(self.style.ERROR("No 'OpinionStatus' objects found! Please create some via Admin first.")) + return - created_layers = [] - for num, en, fa, ru, en_d, fa_d, ru_d in layers_data: - layer, created = NarratorLayer.objects.get_or_create( - number=num, - defaults={ - 'name': self.create_json_field(en, fa, ru), - 'description': self.create_json_field(en_d, fa_d, ru_d) - } - ) - created_layers.append(layer) - self.stdout.write(self.style.SUCCESS(f"Verified {len(created_layers)} layers.")) + self.stdout.write(f"Found {transmitters.count()} Transmitters and {len(statuses)} Opinion Statuses.") # --------------------------------------------------------- - # 2. Create Transmitters + # 2. Data Generators (Helpers) # --------------------------------------------------------- - self.stdout.write("Creating Transmitters...") - - transmitters_list = [ - { - "full_name": ("Zurarah bin Ayan", "زرارة بن اعین", "Зурара ибн Аян"), - "kunya": ("Abu Ali", "ابو علی", "Абу Али"), - "origin": ("Kufa", "کوفه", "Куфа"), - "reliability": Transmitters.ReliabilityLevel.VERY_RELIABLE, - "madhhab": Transmitters.MadhhabChoices.SHIA, - "died": 150, - "layer": 4 - }, - { - "full_name": ("Muhammad bin Muslim", "محمد بن مسلم", "Мухаммад ибн Муслим"), - "kunya": ("Abu Ja'far", "ابو جعفر", "Абу Джафар"), - "origin": ("Kufa", "کوفه", "Куфа"), - "reliability": Transmitters.ReliabilityLevel.VERY_RELIABLE, - "madhhab": Transmitters.MadhhabChoices.SHIA, - "died": 150, - "layer": 4 - }, - { - "full_name": ("Abu Basir Al-Asadi", "ابو بصیر الاسدی", "Абу Басир Аль-Асади"), - "kunya": ("Abu Muhammad", "ابو محمد", "Абу Мухаммад"), - "origin": ("Kufa", "کوفه", "Куфа"), - "reliability": Transmitters.ReliabilityLevel.RELIABLE, - "madhhab": Transmitters.MadhhabChoices.SHIA, - "died": 150, - "layer": 4 - }, - { - "full_name": ("Yunus bin Abd al-Rahman", "یونس بن عبدالرحمن", "Юнус ибн Абд ар-Рахман"), - "kunya": ("Abu Muhammad", "ابو محمد", "Абу Мухаммад"), - "origin": ("Baghdad", "بغداد", "Багдад"), - "reliability": Transmitters.ReliabilityLevel.VERY_RELIABLE, - "madhhab": Transmitters.MadhhabChoices.SHIA, - "died": 208, - "layer": 3 - }, - { - "full_name": ("Hammad bin Isa", "حماد بن عیسی", "Хаммад ибн Иса"), - "kunya": ("Abu Amin", "ابو امین", "Абу Амин"), - "origin": ("Basra", "بصره", "Басра"), - "reliability": Transmitters.ReliabilityLevel.RELIABLE, - "madhhab": Transmitters.MadhhabChoices.SHIA, - "died": 209, - "layer": 3 - }, - { - "full_name": ("Ibrahim bin Hashim", "ابراهیم بن هاشم", "Ибрагим ибн Хашим"), - "kunya": ("Abu Ishaq", "ابو اسحاق", "Абу Исхак"), - "origin": ("Qom", "قم", "Кум"), - "reliability": Transmitters.ReliabilityLevel.ACCEPTABLE, - "madhhab": Transmitters.MadhhabChoices.SHIA, - "died": 250, - "layer": 2 - }, - { - "full_name": ("Sahl bin Ziyad", "سهل بن زیاد", "Сахль ибн Зияд"), - "kunya": ("Abu Sa'id", "ابو سعید", "Абу Саид"), - "origin": ("Rayy", "ری", "Рей"), - "reliability": Transmitters.ReliabilityLevel.WEAK, - "madhhab": Transmitters.MadhhabChoices.SHIA, - "died": 255, - "layer": 2 - }, - { - "full_name": ("Jabir bin Hayyan", "جابر بن حیان", "Джабир ибн Хайян"), - "kunya": ("Abu Musa", "ابو موسی", "Абу Муса"), - "origin": ("Tus", "توس", "Тус"), - "reliability": Transmitters.ReliabilityLevel.UNKNOWN, - "madhhab": Transmitters.MadhhabChoices.OTHER, - "died": 195, - "layer": 3 - }, + scholars = [ + {"en": "Al-Dhahabi", "ar": "الذهبي", "fa": "ذهبی"}, + {"en": "Ibn Hajar", "ar": "ابن حجر", "fa": "ابن حجر"}, + {"en": "Al-Tusi", "ar": "الطوسي", "fa": "طوسی"}, + {"en": "Al-Najashi", "ar": "النجاشي", "fa": "نجاشی"}, ] - created_transmitters = [] - - for t_data in transmitters_list: - # Check if exists by simple slug check (EN name) - en_name = t_data["full_name"][0] - # Replace spaces with dash for rough slug matching - slug_guess = en_name.lower().replace(' ', '-') - - existing = Transmitters.objects.filter(slug__startswith=slug_guess) - - if existing.exists(): - self.stdout.write(f"Skipping {en_name}, likely exists.") - created_transmitters.append(existing.first()) - continue - - transmitter = Transmitters( - full_name=self.create_json_field(*t_data["full_name"]), - kunya=self.create_json_field(*t_data["kunya"]), - origin=self.create_json_field(*t_data["origin"]), - lived_in=self.create_json_field(*t_data["origin"]), - died_in=self.create_json_field("Unknown", "نامشخص", "Неизвестно"), - reliability=t_data["reliability"], - madhhab=t_data["madhhab"], - death_year_hijri=t_data["died"], - description=self.create_json_field( - f"A narrator from {t_data['origin'][0]}", - f"راوی اهل {t_data['origin'][1]}", - f"Передатчик из города {t_data['origin'][2]}" - ) - ) - transmitter.save() - created_transmitters.append(transmitter) - self.stdout.write(self.style.SUCCESS(f"Created transmitter: {en_name}")) + opinion_texts = [ + {"en": "He is trustworthy and reliable.", "ar": "هو ثقة ثبت.", "fa": "او ثقه و مورد اعتماد است."}, + {"en": "His memory was weak in later years.", "ar": "كان سيء الحفظ في آخره.", "fa": "حافظه او در اواخر عمر ضعیف بود."}, + {"en": "Unknown status.", "ar": "مجهول الحال.", "fa": "مجهول است."}, + {"en": "Highly praised by scholars.", "ar": "ممدوح عند العلماء.", "fa": "مورد ستایش علما است."}, + ] - # --------------------------------------------------------- - # 3. Create Opinions - # --------------------------------------------------------- - self.stdout.write("Adding Opinions...") - if created_transmitters: - t_target = created_transmitters[0] # Zurarah - TransmitterOpinion.objects.create( - transmitter=t_target, - scholar_name=self.create_json_field("Al-Najashi", "النجاشی", "Аль-Наджаши"), - opinion_text=self.create_json_field( - "He is the master of our companions and their teacher.", - "او بزرگ اصحاب ما و استاد آنان است.", - "Он — господин наших сподвижников и их учитель." - ), - status=TransmitterOpinion.OpinionStatus.CONFIRMED - ) - - t_weak = next((t for t in created_transmitters if t.reliability == 'weak'), None) - if t_weak: - TransmitterOpinion.objects.create( - transmitter=t_weak, - scholar_name=self.create_json_field("Ibn al-Ghadairi", "ابن الغضائری", "Ибн аль-Гадаири"), - opinion_text=self.create_json_field( - "Weak in hadith, extremist in belief.", - "ضعیف در حدیث، غالی در مذهب.", - "Слаб в хадисах, экстремист в убеждениях." - ), - status=TransmitterOpinion.OpinionStatus.REJECTED - ) + book_titles = [ + {"en": "Book of Traditions", "ar": "كتاب الحديث", "fa": "کتاب حدیث"}, + {"en": "Treatise on Rights", "ar": "رسالة الحقوق", "fa": "رساله حقوق"}, + {"en": "The Clarification", "ar": "التبين", "fa": "تبیین"}, + {"en": "Collection of Virtues", "ar": "مجموع الفضائل", "fa": "مجموعه فضائل"}, + ] - # --------------------------------------------------------- - # 4. Create Original Texts - # --------------------------------------------------------- - self.stdout.write("Adding Original Texts...") - if created_transmitters: - t_author = created_transmitters[1] # Muhammad bin Muslim - TransmitterOriginalText.objects.create( - transmitter=t_author, - title=self.create_json_field( - "Book of Four Hundred Problems", - "کتاب چهارصد مسئله", - "Книга четырехсот вопросов" - ), - text=self.create_json_field( - "Content of the book regarding jurisprudence...", - "محتوای کتاب در مورد فقه...", - "Содержание книги по исламскому праву..." - ), - translation=self.create_json_field( - "English Translation...", - "ترجمه فارسی...", - "Русский перевод..." - ), - ) + def make_json_field(data_dict): + """Converts simple dict {'en': 'X', 'fa': 'Y'} to your model's JSON structure""" + return [ + {"language_code": "en", "text": data_dict.get("en", "")}, + {"language_code": "ar", "text": data_dict.get("ar", "")}, + {"language_code": "fa", "text": data_dict.get("fa", "")}, + ] # --------------------------------------------------------- - # 5. Link Transmitters to Hadis + # 3. Creation Loop # --------------------------------------------------------- - self.stdout.write("Linking Transmitters to Hadis (1877-1888)...") - - target_hadis_ids = range(1877, 1889) - - for hadis_id in target_hadis_ids: - try: - hadis_obj = Hadis.objects.get(id=hadis_id) - except ObjectDoesNotExist: - self.stdout.write(self.style.WARNING(f"Hadis ID {hadis_id} not found. Skipping.")) - continue - - HadisTransmitter.objects.filter(hadis=hadis_obj).delete() - - # Create a random chain of 3 transmitters - chain_length = 3 - chain_narrators = random.sample(created_transmitters, min(len(created_transmitters), chain_length)) - - for index, narrator in enumerate(chain_narrators): - layer_obj = NarratorLayer.objects.get(number=5-index) if index < 5 else None - - # Get or create reliable status - reliable_status, created = TransmitterReliability.objects.get_or_create( - slug='reliable', - defaults={ - 'title': self.create_json_field('Reliable', 'موثوق', 'Надежный'), - 'color': 'green' + counts = {'opinions': 0, 'texts': 0} + + with transaction.atomic(): + for t in transmitters: + self.stdout.write(f"Processing {t.full_name[0]['text'] if t.full_name else t.id}...") + + # --- A. Create TransmitterOpinion (1 to 2 per person) --- + for _ in range(random.randint(1, 2)): + scholar = random.choice(scholars) + text = random.choice(opinion_texts) + status = random.choice(statuses) + + TransmitterOpinion.objects.create( + transmitter=t, + scholar_name=make_json_field(scholar), + opinion_text=make_json_field(text), + status=status + ) + counts['opinions'] += 1 + + # --- B. Create TransmitterOriginalText (1 to 2 per person) --- + for _ in range(random.randint(1, 2)): + title = random.choice(book_titles) + # Simple dummy text + body = { + "en": f"This is an excerpt from {title['en']}...", + "ar": f"هذا مقتطف من {title['ar']}...", + "fa": f"این بخشی از {title['fa']} است..." } - ) - - HadisTransmitter.objects.create( - hadis=hadis_obj, - transmitter=narrator, - narrator_layer=layer_obj, - order=index + 1, - status=reliable_status, - is_gap=False - ) - - self.stdout.write(f"Created chain for Hadis {hadis_id} with {len(chain_narrators)} transmitters.") - self.stdout.write(self.style.SUCCESS("--- Mock Data Generation Complete ---")) \ No newline at end of file + TransmitterOriginalText.objects.create( + transmitter=t, + title=make_json_field(title), + text=make_json_field(body), + translation=make_json_field(body), # Using same text for translation as placeholder + # Note: 'slug' and 'share_link' are handled by your model's save() method automatically + ) + counts['texts'] += 1 + + self.stdout.write(self.style.SUCCESS( + f"Done! Created {counts['opinions']} Opinions and {counts['texts']} Original Texts." + )) \ No newline at end of file diff --git a/apps/hadis/models/transmitter.py b/apps/hadis/models/transmitter.py index bc28ce1..d04fc9c 100644 --- a/apps/hadis/models/transmitter.py +++ b/apps/hadis/models/transmitter.py @@ -89,7 +89,7 @@ class TransmitterReliability(models.Model): def save(self, *args, **kwargs): if not self.slug: - slug = slugify(self.name[0]['text']) + slug = slugify(self.title[0]['text']) self.slug = slug super().save(*args, **kwargs) @@ -340,7 +340,7 @@ class OpinionStatus(models.Model): def save(self, *args, **kwargs): if not self.slug: - slug = slugify(self.name[0]['text']) + slug = slugify(self.title[0]['text']) self.slug = slug super().save(*args, **kwargs) diff --git a/apps/hadis/serializers/hadis.py b/apps/hadis/serializers/hadis.py index f5c8c9a..2a2ddac 100644 --- a/apps/hadis/serializers/hadis.py +++ b/apps/hadis/serializers/hadis.py @@ -315,6 +315,7 @@ class TransmitterOriginalTextSerializer(serializers.ModelSerializer): """ Serializer for TransmitterOriginalText """ title = LocalizedField() text = LocalizedField() + translation =LocalizedField() class Meta: model = TransmitterOriginalText