Browse Source

fix(transmitters): update transmitters names with script and also update api responses with status in them

master
Mohsen Taba 2 weeks ago
parent
commit
920afd7175
  1. 23
      apps/hadis/management/commands/update_transmitter_names.py
  2. 17
      apps/hadis/serializers/hadis.py
  3. 7
      apps/hadis/views/transmitter.py
  4. 555
      scripts/update_transmitter_names.py

23
apps/hadis/management/commands/update_transmitter_names.py

@ -0,0 +1,23 @@
from django.core.management.base import BaseCommand
from scripts.update_transmitter_names import update_transmitters
class Command(BaseCommand):
help = "Update transmitters with 80+ unique multilingual names across English, Arabic, and Russian."
def add_arguments(self, parser):
parser.add_argument(
"--dry-run",
action="store_true",
help="Simulate the update without committing changes to the database.",
)
def handle(self, *args, **options):
dry_run = options.get("dry_run", False)
if dry_run:
self.stdout.write(self.style.WARNING("Running in DRY-RUN mode..."))
else:
self.stdout.write(self.style.NOTICE("Starting transmitter name updates..."))
update_transmitters(dry_run=dry_run)
self.stdout.write(self.style.SUCCESS("Finished transmitter updates."))

17
apps/hadis/serializers/hadis.py

@ -185,6 +185,7 @@ class HadisSyncSerializer(serializers.ModelSerializer):
reliability_block = {
'id': t.reliability.id,
'title': get_localized_text(t.reliability.title, request),
'slug': t.reliability.slug,
'color': t.reliability.color,
'main_color_code': t.reliability.main_color_code,
}
@ -197,6 +198,7 @@ class HadisSyncSerializer(serializers.ModelSerializer):
ut_rel_block = {
'id': ut.reliability.id,
'title': get_localized_text(ut.reliability.title, request),
'slug': ut.reliability.slug,
'color': ut.reliability.color,
'main_color_code': ut.reliability.main_color_code,
}
@ -426,6 +428,7 @@ class TransmitterSerializer(serializers.ModelSerializer):
return {
'id': obj.reliability.id,
'title': get_localized_text(obj.reliability.title, self.context.get('request')),
'slug': obj.reliability.slug,
'color': obj.reliability.color,
'main_color_code': obj.reliability.main_color_code,
}
@ -439,6 +442,7 @@ class TransmitterShortSerializer(serializers.ModelSerializer):
arabic_known_as = ArabicLocalizedField(source='known_as')
nickname = LocalizedField()
arabic_nickname = ArabicLocalizedField(source='nickname')
reliability = serializers.SerializerMethodField()
class Meta:
model = Transmitters
@ -446,6 +450,18 @@ class TransmitterShortSerializer(serializers.ModelSerializer):
'id', 'full_name', 'arabic_full_name', 'slug','birth_year_hijri', 'death_year_hijri',
"known_as", 'arabic_known_as', 'nickname', 'arabic_nickname', 'reliability'
]
def get_reliability(self, obj):
if obj.reliability:
request = self.context.get('request')
return {
'id': obj.reliability.id,
'title': get_localized_text(obj.reliability.title, request),
'slug': obj.reliability.slug,
'color': obj.reliability.color,
'main_color_code': obj.reliability.main_color_code,
}
return None
class TransmitterOpinionSerializer(serializers.ModelSerializer):
""" Serializer for TransmitterOpinions """
scholar_name = LocalizedField()
@ -706,6 +722,7 @@ class TransmitterDetailSerializer(serializers.ModelSerializer):
return {
'id': obj.reliability.id,
'title': get_localized_text(obj.reliability.title, self.context.get('request')),
'slug': obj.reliability.slug,
'color': obj.reliability.color,
'main_color_code': obj.reliability.main_color_code,
}

7
apps/hadis/views/transmitter.py

@ -242,11 +242,14 @@ def get_transmitter_filters(request):
from ..models.transmitter import TransmitterReliability
reliabilities = []
for reliability in TransmitterReliability.objects.all().order_by('id'):
# Get the English title for the slug
if reliability.title:
reliabilities.append({
'id': reliability.id,
'text': get_localized_text(reliability.title, request),
'slug': reliability.slug
'title': get_localized_text(reliability.title, request),
'slug': reliability.slug,
'color': reliability.color,
'main_color_code': reliability.main_color_code,
})
return {

555
scripts/update_transmitter_names.py

@ -0,0 +1,555 @@
#!/usr/bin/env python3
"""
Script to update all transmitters in the database with 80+ distinct, authentic
narrator names across English (en), Arabic (ar), and Russian (ru).
Strictly conforms to the project's multilingual JSON structure:
[
{"language_code": "en", "text": "..."},
{"language_code": "ar", "text": "..."},
{"language_code": "ru", "text": "..."}
]
and regenerates unique, clean slugs for each transmitter.
"""
import os
import sys
import argparse
from pathlib import Path
# Force UTF-8 encoding for console output on Windows
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
if hasattr(sys.stderr, "reconfigure"):
sys.stderr.reconfigure(encoding="utf-8")
BASE_DIR = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(BASE_DIR))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.base")
import django
django.setup()
from django.db import transaction
from django.utils.text import slugify
from apps.hadis.models import Transmitters
# 90 Authentic, prominent Hadith narrators and scholars
TRANSMITTER_NAMES = [
{
"en": "Zurarah ibn A'yan",
"ar": "زرارة بن أعين",
"ru": "Зурара ибн Аян",
},
{
"en": "Muhammad ibn Muslim",
"ar": "محمد بن مسلم",
"ru": "Мухаммад ибн Муслим",
},
{
"en": "Abu Basir al-Asadi",
"ar": "أبو بصير الأسدي",
"ru": "Абу Басир аль-Асади",
},
{
"en": "Jamil ibn Darraj",
"ar": "جميل بن دراج",
"ru": "Джамиль ибн Даррадж",
},
{
"en": "Burayd ibn Mu'awiyah al-Ijli",
"ar": "بريد بن معاوية العجلي",
"ru": "Бурайд ибн Муавия аль-Иджли",
},
{
"en": "Al-Fudayl ibn Yasar",
"ar": "الفضيل بن يسار",
"ru": "Аль-Фудайль ибн Йасар",
},
{
"en": "Aban ibn Taghlib",
"ar": "أبان بن تغلب",
"ru": "Абан ибн Таглиб",
},
{
"en": "Hisham ibn al-Hakam",
"ar": "هشام بن الحكم",
"ru": "Хишам ибн аль-Хакам",
},
{
"en": "Hisham ibn Salim al-Jawaliqi",
"ar": "هشام بن سالم الجواليقي",
"ru": "Хишам ибн Салим аль-Джавалики",
},
{
"en": "Yunus ibn Abd al-Rahman",
"ar": "يونس بن عبد الرحمن",
"ru": "Йунус ибн Абд ар-Рахман",
},
{
"en": "Safwan ibn Yahya",
"ar": "صفوان بن يحيى",
"ru": "Сафван ибн Йахья",
},
{
"en": "Muhammad ibn Abi Umayr",
"ar": "محمد بن أبي عمير",
"ru": "Мухаммад ибн Аби Умайр",
},
{
"en": "Ahmad ibn Muhammad ibn Abi Nasr al-Bazanti",
"ar": "أحمد بن محمد بن أبي نصر البزنطي",
"ru": "Ахмад ибн Мухаммад аль-Базанти",
},
{
"en": "Hammad ibn Isa",
"ar": "حماد بن عيسى",
"ru": "Хаммад ибн Иса",
},
{
"en": "Hammad ibn Uthman",
"ar": "حماد بن عثمان",
"ru": "Хаммад ибн Усман",
},
{
"en": "Mu'awiyah ibn Ammar",
"ar": "معاوية بن عمار",
"ru": "Муавия ибн Аммар",
},
{
"en": "Ali ibn Yaqtin",
"ar": "علي بن يقطين",
"ru": "Али ибн Йактин",
},
{
"en": "Zakariya ibn Adam al-Qummi",
"ar": "زكريا بن آدم القمي",
"ru": "Закария ибн Адам аль-Кумми",
},
{
"en": "Al-Fadl ibn Shadhan",
"ar": "الفضل بن شاذان",
"ru": "Аль-Фадль ибн Шазан",
},
{
"en": "Muhammad ibn Ya'qub al-Kulayni",
"ar": "محمد بن يعقوب الكليني",
"ru": "Мухаммад ибн Йакуб аль-Кулайни",
},
{
"en": "Al-Shaykh al-Saduq (Muhammad ibn Ali ibn Babawayh)",
"ar": "الشيخ الصدوق (محمد بن علي بن بابويه)",
"ru": "Аш-Шейх ас-Садук",
},
{
"en": "Al-Shaykh al-Mufid (Muhammad ibn Muhammad al-Nu'man)",
"ar": "الشيخ المفيد (محمد بن محمد النعمان)",
"ru": "Аш-Шейх аль-Муфид",
},
{
"en": "Ali ibn al-Husayn al-Sharif al-Murtada",
"ar": "الشريف المرتضى (علي بن الحسين)",
"ru": "Аш-Шариф аль-Муртада",
},
{
"en": "Al-Shaykh al-Tusi (Muhammad ibn al-Hasan)",
"ar": "الشيخ الطوسي (محمد بن الحسن)",
"ru": "Аш-Шейх ат-Туси",
},
{
"en": "Al-Allamah al-Hilli (Al-Hasan ibn Yusuf)",
"ar": "العلامة الحلي (الحسن بن يوسف)",
"ru": "Аль-Аллама аль-Хилли",
},
{
"en": "Al-Muhaqqiq al-Hilli (Ja'far ibn al-Hasan)",
"ar": "المحقق الحلي (جعفر بن الحسن)",
"ru": "Аль-Мухаккик аль-Хилли",
},
{
"en": "Al-Shahid al-Awwal (Muhammad ibn Makki)",
"ar": "الشهيد الأول (محمد بن مكي)",
"ru": "Аш-Шахид аль-Авваль",
},
{
"en": "Al-Shahid al-Thani (Zayn al-Din al-Jubba'i)",
"ar": "الشهيد الثاني (زين الدين الجبعي)",
"ru": "Аш-Шахид ас-Сани",
},
{
"en": "Muhammad Baqir al-Majlisi",
"ar": "محمد باقر المجلسي",
"ru": "Мухаммад Бакир аль-Маджлиси",
},
{
"en": "Al-Hurr al-Amili (Muhammad ibn al-Hasan)",
"ar": "الحر العاملي (محمد بن الحسن)",
"ru": "Аль-Хурр аль-Амили",
},
{
"en": "Abu al-Qasim al-Khu'i",
"ar": "أبو القاسم الخوئي",
"ru": "Абу аль-Касим аль-Хои",
},
{
"en": "Salman al-Farsi",
"ar": "سلمان الفارسي",
"ru": "Салман аль-Фарси",
},
{
"en": "Abu Dharr al-Ghifari",
"ar": "أبو ذر الغفاري",
"ru": "Абу Зарр аль-Гифари",
},
{
"en": "Al-Miqdad ibn al-Aswad",
"ar": "المقداد بن الأسود",
"ru": "Аль-Микдад ибн аль-Асвад",
},
{
"en": "Ammar ibn Yasir",
"ar": "عمار بن ياسر",
"ru": "Аммар ибн Йасир",
},
{
"en": "Jabir ibn Abd Allah al-Ansari",
"ar": "جابر بن عبد الله الأنصاري",
"ru": "Джабир ибн Абдуллах аль-Ансари",
},
{
"en": "Hudhayfah ibn al-Yaman",
"ar": "حذيفة بن اليمان",
"ru": "Хузайфа ибн аль-Йаман",
},
{
"en": "Malik al-Ashtar al-Nakha'i",
"ar": "مالك الأشتر النخعي",
"ru": "Малик аль-Аштар",
},
{
"en": "Kumayl ibn Ziyad al-Nakha'i",
"ar": "كميل بن زياد النخعي",
"ru": "Кумайль ибн Зийад",
},
{
"en": "Maytham al-Tammar",
"ar": "ميثم التمار",
"ru": "Майсам ат-Таммар",
},
{
"en": "Sa'id ibn Jubayr",
"ar": "سعيد بن جبير",
"ru": "Саид ибн Джубайр",
},
{
"en": "Tawus ibn Kaysan",
"ar": "طاووس بن كيسان",
"ru": "Тавус ибн Кайсан",
},
{
"en": "Sulaym ibn Qays al-Hilali",
"ar": "سليم بن قيس الهلالي",
"ru": "Сулейм ибн Кайс аль-Хилали",
},
{
"en": "Al-Asbagh ibn Nubatah",
"ar": "الأصبغ بن نباتة",
"ru": "Аль-Асбаг ибн Нубата",
},
{
"en": "Jabir ibn Yazid al-Ju'fi",
"ar": "جابر بن يزيد الجعفي",
"ru": "Джабир ибн Йазид аль-Джуфи",
},
{
"en": "Abu Hamzah al-Thumali (Thabit ibn Dinar)",
"ar": "أبو حمزة الثمالي (ثابت بن دينار)",
"ru": "Абу Хамза ас-Сумали",
},
{
"en": "Zayd ibn Ali ibn al-Husayn",
"ar": "زيد بن علي بن الحسين",
"ru": "Зайд ибн Али",
},
{
"en": "Dawud ibn Sarhan",
"ar": "داود بن سرحان",
"ru": "Давуд ибн Сархан",
},
{
"en": "Abd Allah ibn Sinan",
"ar": "عبد الله بن سنان",
"ru": "Абдуллах ибн Синан",
},
{
"en": "Abd Allah ibn Bukayr",
"ar": "عبد الله بن بكير",
"ru": "Абдуллах ибн Букайр",
},
{
"en": "Abd Allah ibn Mughirah",
"ar": "عبد الله بن المغيرة",
"ru": "Абдуллах ибн аль-Мугира",
},
{
"en": "Al-Husayn ibn Sa'id al-Ahwazi",
"ar": "الحسين بن سعيد الأهوازي",
"ru": "Аль-Хусейн ибн Саид аль-Ахвази",
},
{
"en": "Ali ibn Mahziyar al-Ahwazi",
"ar": "علي بن مهزيار الأهوازي",
"ru": "Али ибн Махзийар аль-Ахвази",
},
{
"en": "Ibrahim ibn Hashim al-Qummi",
"ar": "إبراهيم بن هاشم القمي",
"ru": "Ибрахим ибн Хашим аль-Кумми",
},
{
"en": "Ali ibn Ibrahim al-Qummi",
"ar": "علي بن إبراهيم القمي",
"ru": "Али ибн Ибрахим аль-Кумми",
},
{
"en": "Sa'd ibn Abd Allah al-Ash'ari",
"ar": "سعد بن عبد الله الأشعري",
"ru": "Саад ибн Абдуллах аль-Ашари",
},
{
"en": "Al-Hasan ibn Mahbub al-Sarrad",
"ar": "الحسن بن محبوب السراد",
"ru": "Аль-Хасан ибн Махбуб",
},
{
"en": "Al-Hasan ibn Ali ibn Faddal",
"ar": "الحسن بن علي بن فضال",
"ru": "Аль-Хасан ибн Али ибн Фаддаль",
},
{
"en": "Ali ibn al-Hasan ibn Faddal",
"ar": "علي بن الحسن بن فضال",
"ru": "Али ибн аль-Хасан ибн Фаддаль",
},
{
"en": "Muhammad ibn Ahmad ibn Yahya al-Ash'ari",
"ar": "محمد بن أحمد بن يحيى الأشعري",
"ru": "Мухаммад ибн Ахмад ибн Йахья",
},
{
"en": "Ahmad ibn Muhammad ibn Isa al-Ash'ari",
"ar": "أحمد بن محمد بن عيسى الأشعري",
"ru": "Ахмад ибн Мухаммад ибн Иса аль-Ашари",
},
{
"en": "Ahmad ibn Muhammad ibn Khalid al-Barqi",
"ar": "أحمد بن محمد بن خالد البرقي",
"ru": "Ахмад ибн Мухаммад аль-Барки",
},
{
"en": "Muhammad ibn Yahya al-Attar al-Qummi",
"ar": "محمد بن يحيى العطار القمي",
"ru": "Мухаммад ибн Йахья аль-Аттар",
},
{
"en": "Al-Husayn ibn Muhammad al-Ash'ari",
"ar": "الحسين بن محمد الأشعري",
"ru": "Аль-Хусейн ибн Мухаммад аль-Ашари",
},
{
"en": "Ali ibn al-Husayn ibn Babawayh al-Qummi",
"ar": "علي بن الحسين بن بابويه القمي",
"ru": "Али ибн аль-Хусейн ибн Бабавейх",
},
{
"en": "Ja'far ibn Muhammad ibn Qulawayh",
"ar": "جعفر بن محمد بن قولويه",
"ru": "Джафар ибн Мухаммад ибн Кулавейх",
},
{
"en": "Muhammad ibn al-Hasan al-Saffar",
"ar": "محمد بن الحسن الصفار",
"ru": "Мухаммад ибн аль-Хасан ас-Саффар",
},
{
"en": "Muhammad ibn Umar al-Kashshi",
"ar": "محمد بن عمر الكشي",
"ru": "Мухаммад ибн Умар аль-Кашши",
},
{
"en": "Ahmad ibn Ali al-Najashi",
"ar": "أحمد بن علي النجاشي",
"ru": "Ахмад ибн Али ан-Наджаши",
},
{
"en": "Muhammad ibn Ibrahim al-Nu'mani",
"ar": "محمد بن إبراهيم النعماني",
"ru": "Мухаммад ибн Ибрахим ан-Нумани",
},
{
"en": "Qutb al-Din al-Rawandi",
"ar": "قطب الدين الراوندي",
"ru": "Кутб ад-Дин ар-Раванди",
},
{
"en": "Al-Fadl ibn al-Hasan al-Tabrisi",
"ar": "الفضل بن الحسن الطبرسي",
"ru": "Аль-Фадль ибн аль-Хасан ат-Табарси",
},
{
"en": "Ibn Shahrashub al-Mazandarani",
"ar": "ابن شهرآشوب المازندراني",
"ru": "Ибн Шахрашуб аль-Мазандарани",
},
{
"en": "Ali ibn Musa ibn Tawus",
"ar": "علي بن موسى بن طاووس",
"ru": "Али ибн Муса ибн Тавус",
},
{
"en": "Ahmad ibn Muhammad al-Ardabili",
"ar": "أحمد بن محمد الأردبيلي",
"ru": "Ахмад ибн Мухаммад аль-Ардабили",
},
{
"en": "Al-Muhsin al-Fayd al-Kashani",
"ar": "المحسن الفيض الكاشاني",
"ru": "Аль-Файд аль-Кашани",
},
{
"en": "Yusuf ibn Ahmad al-Bahrani",
"ar": "يوسف بن أحمد البحراني",
"ru": "Йусуф ибн Ахмад аль-Бахрани",
},
{
"en": "Murtada al-Ansari",
"ar": "مرتضى الأنصاري",
"ru": "Муртаза аль-Ансари",
},
{
"en": "Muhammad Hasan al-Shirazi",
"ar": "محمد حسن الشيرازي",
"ru": "Мухаммад Хасан аль-Ширази",
},
{
"en": "Muhsin al-Amin al-Amili",
"ar": "محسن الأمين العاملي",
"ru": "Мухсин аль-Амин аль-Амили",
},
{
"en": "Abd al-Husayn Sharaf al-Din al-Musawi",
"ar": "عبد الحسين شرف الدين الموسوي",
"ru": "Абд аль-Хусейн Шараф ад-Дин",
},
{
"en": "Muhammad Baqir al-Sadr",
"ar": "محمد باقر الصدر",
"ru": "Мухаммад Бакир ас-Садр",
},
{
"en": "Muhammad Husayn al-Tabataba'i",
"ar": "محمد حسين الطباطبائي",
"ru": "Мухаммад Хусейн ат-Табатабаи",
},
{
"en": "Al-Hasan ibn Zayn al-Din (Sahib al-Ma'alim)",
"ar": "الحسن بن زين الدين (صاحب المعالم)",
"ru": "Аль-Хасан ибн Зайн ад-Дин",
},
{
"en": "Muhammad Baqir al-Sabzawari",
"ar": "محمد باقر السبزواري",
"ru": "Мухаммад Бакир ас-Сабзавари",
},
{
"en": "Al-Sharif al-Radi (Muhammad ibn al-Husayn)",
"ar": "الشريف الرضي (محمد بن الحسين)",
"ru": "Аш-Шариф ар-Ради",
},
{
"en": "Ibn Abi Aqil al-Umani",
"ar": "ابن أبي عقيل العماني",
"ru": "Ибн Аби Акиль аль-Умани",
},
{
"en": "Ibn al-Junayd al-Iskafi",
"ar": "ابن الجنيد الإسكافي",
"ru": "Ибн аль-Джунайд аль-Искафи",
},
{
"en": "Al-Qadi Ibn al-Barraj",
"ar": "القاضي ابن البراج",
"ru": "Аль-Кади ибн аль-Баррадж",
},
{
"en": "Sallar ibn Abd al-Aziz al-Daylami",
"ar": "سلار بن عبد العزيز الديلمي",
"ru": "Саллар ибн Абд аль-Азиз",
},
]
def update_transmitters(dry_run: bool = False):
transmitters = list(Transmitters.objects.all().order_by("id"))
total_count = len(transmitters)
print(f"Found {total_count} transmitters in database.")
print(f"Loaded {len(TRANSMITTER_NAMES)} curated narrator names.")
if total_count > len(TRANSMITTER_NAMES):
print(f"Warning: Database has {total_count} transmitters, but we have {len(TRANSMITTER_NAMES)} names.")
updated = 0
with transaction.atomic():
for idx, transmitter in enumerate(transmitters):
name_data = TRANSMITTER_NAMES[idx % len(TRANSMITTER_NAMES)]
en_name = name_data["en"]
ar_name = name_data["ar"]
ru_name = name_data["ru"]
# Format strictly adheres to the multilingual JSON schema:
# [{"language_code": "...", "text": "..."}]
new_full_name = [
{"language_code": "en", "text": en_name},
{"language_code": "ar", "text": ar_name},
{"language_code": "ru", "text": ru_name},
]
transmitter.full_name = new_full_name
# Generating a clean, unique slug from the English name
base_slug = slugify(en_name, allow_unicode=True) or f"transmitter-{transmitter.id}"
# Check for conflict excluding current transmitter
candidate_slug = base_slug[:240]
counter = 1
while Transmitters.objects.filter(slug=candidate_slug).exclude(pk=transmitter.pk).exists():
candidate_slug = f"{base_slug[:230]}-{counter}"
counter += 1
transmitter.slug = candidate_slug
if dry_run:
print(f"[DRY RUN] ID {transmitter.id}: {en_name} | {ar_name} | {ru_name} -> slug: {candidate_slug}")
else:
transmitter.save()
print(f"[UPDATED] ID {transmitter.id}: {en_name} | {ar_name} | {ru_name} -> slug: {transmitter.slug}")
updated += 1
if dry_run:
print(f"\n[DRY RUN COMPLETE] {updated} transmitters would be updated. No changes were committed.")
transaction.set_rollback(True)
else:
print(f"\n[SUCCESS] Successfully updated {updated} transmitters with unique multilingual names and slugs.")
def main():
parser = argparse.ArgumentParser(description="Update transmitters with unique multilingual names.")
parser.add_argument("--dry-run", action="store_true", help="Simulate updates without committing to database.")
args = parser.parse_args()
update_transmitters(dry_run=args.dry_run)
if __name__ == "__main__":
main()
Loading…
Cancel
Save