3 changed files with 90 additions and 250 deletions
-
335apps/hadis/management/commands/seed_transmitters.py
-
4apps/hadis/models/transmitter.py
-
1apps/hadis/serializers/hadis.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 ---")) |
|||
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." |
|||
)) |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue