Browse Source

Add Russian data seeding command and update entrypoint script

- Introduced a new management command to seed Russian language data for Hadis, HadisCategory, and HadisSect.
- Updated entrypoint script to include the new command for seeding Russian data during initialization.
master
mortezaei 4 months ago
parent
commit
def7e033b1
  1. 346
      apps/hadis/management/commands/seed_russian_data.py
  2. 3
      entrypoint.sh

346
apps/hadis/management/commands/seed_russian_data.py

@ -0,0 +1,346 @@
import random
import uuid
from django.core.management.base import BaseCommand
from django.db import transaction
from apps.hadis.models import Hadis, HadisCategory, HadisSect
# Russian word patterns for random combination
RUSSIAN_CATEGORY_PREFIXES = [
"Основы", "Принципы", "Учение", "Заповеди", "Наставления",
"Мудрость", "Знания", "Истина", "Путь", "Свет",
"Благочестие", "Праведность", "Духовность", "Вера", "Надежда",
]
RUSSIAN_CATEGORY_TOPICS = [
"молитвы", "поста", "милостыни", "паломничества", "джихада",
"брака", "семьи", "торговли", "справедливости", "терпения",
"благодарности", "покаяния", "прощения", "любви", "мира",
"знания", "мудрости", "веры", "надежды", "смирения",
]
RUSSIAN_CATEGORY_SUFFIXES = [
"в исламе", "для верующих", "и праведность", "и благочестие",
"и духовность", "и истина", "и свет", "и путь",
]
RUSSIAN_HADIS_OPENINGS = [
"Пророк (мир ему) сказал:",
"Имам Али (мир ему) сказал:",
"Имам Садик (мир ему) сказал:",
"Имам Хусейн (мир ему) сказал:",
"Передается от Пророка (мир ему):",
"Рассказывает имам Бакир (мир ему):",
"Сообщается от имама Казима (мир ему):",
]
RUSSIAN_HADIS_BODIES = [
"Лучший из вас тот, кто учится и учит других.",
"Ищите знания от колыбели до могилы.",
"Терпение - ключ к облегчению.",
"Молитва - столп религии.",
"Знание - свет для сердца.",
"Доброта к родителям - обязанность верующего.",
"Справедливость - основа власти.",
"Правда ведет к благочестию.",
"Смирение возвышает человека.",
"Благодарность увеличивает благословения.",
"Прощение - признак силы.",
"Терпение приносит награду.",
"Вера укрепляется добрыми делами.",
"Знание без действия бесполезно.",
"Лучшее богатство - довольство.",
"Самый сильный - тот, кто владеет собой в гневе.",
"Сосед имеет права на тебя.",
"Улыбка - это милостыня.",
"Чистота - половина веры.",
"Намерение определяет ценность дела.",
]
RUSSIAN_HADIS_ENDINGS = [
"И это истина от Всевышнего.",
"Так учит нас ислам.",
"Это путь праведных.",
"Запомните это наставление.",
"Следуйте этому пути.",
"Это мудрость пророков.",
"Берегите это знание.",
"",
]
RUSSIAN_SECT_DATA = {
'shia': {
'title': 'Шиизм',
'description': 'Шиитское направление ислама, следующее за семьей Пророка (мир ему и его семье).',
},
'sunni': {
'title': 'Суннизм',
'description': 'Суннитское направление ислама, следующее сунне Пророка (мир ему).',
},
}
def make_json_field(text, lang='ru'):
"""Create JSON field in the format used by the models."""
return [{'text': text, 'language_code': lang}]
def generate_unique_slug(prefix, number):
"""Generate a unique slug with prefix and number."""
unique_suffix = uuid.uuid4().hex[:8]
return f"{prefix}-{number}-{unique_suffix}"
def generate_category_title():
"""Generate a random Russian category title."""
prefix = random.choice(RUSSIAN_CATEGORY_PREFIXES)
topic = random.choice(RUSSIAN_CATEGORY_TOPICS)
suffix = random.choice(RUSSIAN_CATEGORY_SUFFIXES) if random.random() > 0.5 else ""
return f"{prefix} {topic} {suffix}".strip()
def generate_category_description(title):
"""Generate a description based on the title."""
descriptions = [
f"Раздел посвящен теме: {title}. Здесь собраны важные хадисы и наставления.",
f"В этом разделе вы найдете хадисы о {title.lower()}.",
f"Категория содержит материалы по теме: {title}.",
f"Изучайте {title.lower()} через достоверные хадисы.",
]
return random.choice(descriptions)
def generate_hadis_text():
"""Generate a random hadis text in Russian."""
opening = random.choice(RUSSIAN_HADIS_OPENINGS)
body = random.choice(RUSSIAN_HADIS_BODIES)
ending = random.choice(RUSSIAN_HADIS_ENDINGS)
return f"{opening} {body} {ending}".strip()
def generate_hadis_title():
"""Generate a random hadis title."""
topics = [
"О терпении и награде",
"О знании и мудрости",
"О молитве и поклонении",
"О справедливости и праведности",
"О семье и воспитании",
"О доброте и милосердии",
"О вере и благочестии",
"О покаянии и прощении",
"О благодарности Аллаху",
"О смирении и скромности",
"О правде и честности",
"О соседях и обществе",
"О торговле и справедливости",
"О чистоте и гигиене",
"О намерении и искренности",
]
return random.choice(topics)
class Command(BaseCommand):
help = 'Seed Russian language data for HadisSect, HadisCategory (3 levels), and Hadis (up to 500 records)'
# Configuration constants
MAX_HADIS_RECORDS = 500
HADIS_PER_CATEGORY = 10
def add_arguments(self, parser):
parser.add_argument(
'--clear',
action='store_true',
help='Clear existing data before seeding',
)
parser.add_argument(
'--force',
action='store_true',
help='Force seeding even if data already exists',
)
def handle(self, *args, **options):
self.stdout.write(self.style.WARNING('=== Starting Russian Data Seeding ==='))
# Check if data already exists (prevent re-running in loops)
existing_hadis = Hadis.objects.count()
existing_categories = HadisCategory.objects.count()
if existing_hadis >= self.MAX_HADIS_RECORDS and not options['force'] and not options['clear']:
self.stdout.write(self.style.SUCCESS(
f'Data already seeded ({existing_hadis} hadis, {existing_categories} categories). '
'Use --force to override or --clear to reset.'
))
return
if options['clear']:
self.stdout.write(self.style.WARNING('Clearing existing data...'))
Hadis.objects.all().delete()
HadisCategory.objects.all().delete()
HadisSect.objects.all().delete()
self.stdout.write(self.style.SUCCESS('Existing data cleared.'))
try:
with transaction.atomic():
# Step 1: Create Sects
sects = self.create_sects()
# Step 2: Create Categories (3 levels)
categories = self.create_categories(sects)
# Step 3: Create Hadis (up to 500 records, distributed across categories)
self.create_hadis(categories)
self.print_statistics()
self.stdout.write(self.style.SUCCESS('=== Russian Data Seeding Complete ==='))
except Exception as e:
self.stdout.write(self.style.ERROR(f'Error during seeding: {str(e)}'))
raise
def create_sects(self):
"""Create or update HadisSect entries."""
self.stdout.write('Creating sects...')
sects = {}
for sect_type, data in RUSSIAN_SECT_DATA.items():
sect, created = HadisSect.objects.update_or_create(
sect_type=sect_type,
defaults={
'title': make_json_field(data['title']),
'description': make_json_field(data['description']),
'is_active': True,
'order': 1 if sect_type == 'shia' else 2,
}
)
sects[sect_type] = sect
status = 'Created' if created else 'Updated'
self.stdout.write(f" {status} sect: {data['title']}")
return sects
def create_categories(self, sects):
"""Create 3-level category tree for each sect and source type."""
self.stdout.write('Creating category tree (3 levels)...')
all_leaf_categories = []
# Limit source types to control total number of categories
source_types = ['hadith', 'quran']
for sect_type, sect in sects.items():
for source_type in source_types:
self.stdout.write(f" Creating categories for {sect_type}/{source_type}...")
# Level 1: Root categories (2 per source type to limit total)
for i in range(2):
level1_title = generate_category_title()
level1_cat = HadisCategory.objects.create(
parent=None,
sect=sect,
source_type=source_type,
title=make_json_field(level1_title),
description=make_json_field(generate_category_description(level1_title)),
order=i + 1,
)
# Level 2: Child categories (2 per level 1)
for j in range(2):
level2_title = generate_category_title()
level2_cat = HadisCategory.objects.create(
parent=level1_cat,
sect=sect,
source_type=source_type,
title=make_json_field(level2_title),
description=make_json_field(generate_category_description(level2_title)),
order=j + 1,
)
# Level 3: Leaf categories (2-3 per level 2)
num_level3 = random.randint(2, 3)
for k in range(num_level3):
level3_title = generate_category_title()
level3_cat = HadisCategory.objects.create(
parent=level2_cat,
sect=sect,
source_type=source_type,
title=make_json_field(level3_title),
description=make_json_field(generate_category_description(level3_title)),
order=k + 1,
)
all_leaf_categories.append(level3_cat)
total_categories = HadisCategory.objects.count()
self.stdout.write(self.style.SUCCESS(f" Created {total_categories} categories total"))
self.stdout.write(self.style.SUCCESS(f" Leaf categories: {len(all_leaf_categories)}"))
return all_leaf_categories
def create_hadis(self, leaf_categories):
"""Create hadis records distributed across categories, up to MAX_HADIS_RECORDS."""
self.stdout.write(f'Creating hadis entries (max {self.MAX_HADIS_RECORDS})...')
hadis_count = 0
hadis_number = 1
# Calculate hadis per category to reach ~500 total
num_categories = len(leaf_categories)
if num_categories == 0:
self.stdout.write(self.style.WARNING('No leaf categories found!'))
return
hadis_per_cat = max(self.HADIS_PER_CATEGORY, self.MAX_HADIS_RECORDS // num_categories)
for idx, category in enumerate(leaf_categories):
# Stop if we've reached the limit
if hadis_count >= self.MAX_HADIS_RECORDS:
break
# Create hadis for this category
for i in range(hadis_per_cat):
if hadis_count >= self.MAX_HADIS_RECORDS:
break
title = generate_hadis_title()
text = generate_hadis_text()
translation = text # Same as text since it's already in Russian
# Generate unique slug to avoid duplicates
slug = generate_unique_slug('hadis-ru', hadis_number)
Hadis.objects.create(
category=category,
number=hadis_number,
slug=slug,
title=make_json_field(title),
title_narrator=make_json_field(random.choice(RUSSIAN_HADIS_OPENINGS).rstrip(':')),
description=make_json_field(f"Хадис номер {hadis_number} из категории {category.title[0]['text']}"),
text=text,
translation=make_json_field(translation),
status=True,
address=make_json_field(f"Том {random.randint(1, 10)}, страница {random.randint(1, 500)}"),
explanation=make_json_field(f"Этот хадис учит нас важности {title.lower()}."),
)
hadis_number += 1
hadis_count += 1
# Progress indicator every 5 categories
if idx % 5 == 0:
self.stdout.write(f" Progress: {hadis_count}/{self.MAX_HADIS_RECORDS} hadis created...")
self.stdout.write(self.style.SUCCESS(f" Created {hadis_count} hadis entries"))
def print_statistics(self):
"""Print final statistics."""
self.stdout.write("\n=== Statistics ===")
self.stdout.write(f"Sects: {HadisSect.objects.count()}")
self.stdout.write(f"Categories: {HadisCategory.objects.count()}")
self.stdout.write(f"Hadis: {Hadis.objects.count()}")
# Show hadis per category stats
leaf_cats = []
for cat in HadisCategory.objects.all():
if not HadisCategory.objects.filter(parent=cat).exists():
leaf_cats.append(cat)
if leaf_cats:
hadis_counts = [Hadis.objects.filter(category=cat).count() for cat in leaf_cats]
self.stdout.write(f"Hadis per leaf category: min={min(hadis_counts)}, max={max(hadis_counts)}, avg={sum(hadis_counts)/len(hadis_counts):.1f}")

3
entrypoint.sh

@ -5,6 +5,9 @@ python manage.py migrate
# python manage.py seed_images
python manage.py collectstatic --noinput
# Seed Russian data (only runs once, skips if data exists)
python manage.py seed_russian_data
# python manage.py populate_books
# python manage.py populate_book_reference
# python manage.py populate_refrence_images

Loading…
Cancel
Save