Browse Source
Add management commands for seeding basic and comprehensive Hadis data
Add management commands for seeding basic and comprehensive Hadis data
- Implemented `seed_basic_data.py` to seed essential Hadis app models including HadisStatus, HadisTag, and HadisSect with initial records. - Created `seed_hadis_data.py` for comprehensive data seeding, establishing realistic sample records for all Hadis app models while maintaining relationships and business logic. - Introduced retry logic for database operations to handle potential locks and integrity errors during seeding. - Added a test command `test_sects.py` to verify the creation of HadisSect records and check for existing sects.master
8 changed files with 1636 additions and 119 deletions
-
1apps/hadis/management/__init__.py
-
72apps/hadis/management/commands/README.md
-
1apps/hadis/management/commands/__init__.py
-
34apps/hadis/management/commands/fix_sects.py
-
138apps/hadis/management/commands/seed_basic_data.py
-
934apps/hadis/management/commands/seed_hadis_data.py
-
45apps/hadis/management/commands/test_sects.py
-
530scripts/seed_hadis_data.py
@ -0,0 +1 @@ |
|||
|
|||
@ -0,0 +1,72 @@ |
|||
# Hadis Management Commands |
|||
|
|||
## seed_hadis_data |
|||
|
|||
This management command seeds comprehensive data for all Hadis app models with realistic sample records while maintaining proper relationships and business domain logic. |
|||
|
|||
### Usage |
|||
|
|||
```bash |
|||
# Basic usage - seed data with default settings |
|||
python manage.py seed_hadis_data |
|||
|
|||
# Clear existing data before seeding |
|||
python manage.py seed_hadis_data --clear |
|||
|
|||
# Specify custom images directory |
|||
python manage.py seed_hadis_data --images-dir /path/to/images |
|||
|
|||
# Specify custom XMind file |
|||
python manage.py seed_hadis_data --xmind-file /path/to/file.xmind |
|||
|
|||
# Combine options |
|||
python manage.py seed_hadis_data --clear --images-dir scripts/seed_images --xmind-file scripts/test.xmind |
|||
``` |
|||
|
|||
### Options |
|||
|
|||
- `--clear`: Clear existing hadis data before seeding (optional) |
|||
- `--images-dir`: Directory containing seed images (default: scripts/seed_images) |
|||
- `--xmind-file`: Path to XMind file for categories (default: scripts/test.xmind) |
|||
|
|||
### What it creates |
|||
|
|||
1. **HadisStatus records**: Various hadis authenticity statuses (Достоверный, Хороший, etc.) |
|||
2. **HadisTag records**: Topic tags for categorizing hadis |
|||
3. **HadisSect records**: Shia and Sunni sects |
|||
4. **HadisCategory records**: Hierarchical categories for both Quran and Hadith sources |
|||
5. **Library data**: Books, categories, and collections for references |
|||
6. **Transmitters**: Historical figures who transmitted hadis |
|||
7. **Hadis records**: Complete hadis with translations, explanations, and relationships |
|||
8. **Transmission chains**: Links between hadis and transmitters |
|||
9. **References**: Book references with images |
|||
|
|||
### Requirements |
|||
|
|||
- The images directory must contain PNG files for book covers and reference images |
|||
- The XMind file is optional but recommended for category mind maps |
|||
- All models must be properly migrated before running |
|||
|
|||
### Performance |
|||
|
|||
The command uses optimized batch operations to create data efficiently: |
|||
- Bulk create/update operations for categories |
|||
- Checks for existing records to avoid duplicates |
|||
- Progress reporting for large datasets |
|||
|
|||
### Example Output |
|||
|
|||
``` |
|||
Starting Hadis data seeding... |
|||
Found 4 seed images |
|||
XMind file: scripts/test.xmind |
|||
Creating Hadis Statuses... |
|||
Created status: Достоверный |
|||
Created status: Хороший |
|||
... |
|||
Creating Hadis Categories... |
|||
Creating categories for Шииты-двунадесятники... |
|||
Batch created 6 Quran categories |
|||
... |
|||
Successfully seeded all Hadis data! |
|||
``` |
|||
@ -0,0 +1 @@ |
|||
|
|||
@ -0,0 +1,34 @@ |
|||
""" |
|||
Fix sects creation issue |
|||
""" |
|||
|
|||
from django.core.management.base import BaseCommand |
|||
from apps.hadis.models import HadisSect |
|||
|
|||
|
|||
class Command(BaseCommand): |
|||
help = 'Fix sects creation' |
|||
|
|||
def handle(self, **options): |
|||
self.stdout.write("Fixing sects...") |
|||
|
|||
# Delete any problematic sects |
|||
HadisSect.objects.filter(sect_type='sunni').delete() |
|||
|
|||
# Create sects with simple titles |
|||
sects_data = [ |
|||
{'sect_type': 'shia', 'title': 'Shia', 'is_active': True, 'order': 1}, |
|||
{'sect_type': 'sunni', 'title': 'Sunni', 'is_active': True, 'order': 2}, |
|||
] |
|||
|
|||
for data in sects_data: |
|||
sect, created = HadisSect.objects.get_or_create( |
|||
sect_type=data['sect_type'], |
|||
defaults=data |
|||
) |
|||
if created: |
|||
self.stdout.write(f"Created: {sect.sect_type} - {sect.title}") |
|||
else: |
|||
self.stdout.write(f"Exists: {sect.sect_type} - {sect.title}") |
|||
|
|||
self.stdout.write(self.style.SUCCESS("Sects fixed!")) |
|||
@ -0,0 +1,138 @@ |
|||
""" |
|||
Basic data seeding management command for Hadis app models. |
|||
This command creates only the essential records needed for the app to function. |
|||
""" |
|||
|
|||
from django.core.management.base import BaseCommand, CommandError |
|||
from django.db import transaction |
|||
|
|||
# Import models |
|||
from apps.hadis.models import HadisSect, HadisStatus, HadisTag |
|||
|
|||
|
|||
class Command(BaseCommand): |
|||
help = 'Seed basic data for Hadis app models' |
|||
|
|||
def add_arguments(self, parser): |
|||
parser.add_argument( |
|||
'--clear', |
|||
action='store_true', |
|||
help='Clear existing basic data before seeding', |
|||
) |
|||
|
|||
def handle(self, **options): |
|||
if options['clear']: |
|||
self.clear_existing_data() |
|||
|
|||
try: |
|||
with transaction.atomic(): |
|||
self.stdout.write( |
|||
self.style.SUCCESS('Starting basic Hadis data seeding...') |
|||
) |
|||
|
|||
# Seed basic data |
|||
statuses = self.seed_hadis_statuses() |
|||
tags = self.seed_hadis_tags() |
|||
sects = self.seed_hadis_sects() |
|||
|
|||
self.stdout.write( |
|||
self.style.SUCCESS( |
|||
f'Successfully seeded basic data: ' |
|||
f'{len(statuses)} statuses, {len(tags)} tags, {len(sects)} sects' |
|||
) |
|||
) |
|||
|
|||
except Exception as e: |
|||
self.stdout.write( |
|||
self.style.ERROR(f'Error during seeding: {str(e)}') |
|||
) |
|||
raise CommandError(f'Seeding failed: {str(e)}') |
|||
|
|||
def clear_existing_data(self): |
|||
"""Clear existing basic data""" |
|||
self.stdout.write("Clearing existing basic data...") |
|||
|
|||
HadisSect.objects.all().delete() |
|||
HadisStatus.objects.all().delete() |
|||
HadisTag.objects.all().delete() |
|||
|
|||
self.stdout.write("Basic data cleared.") |
|||
|
|||
def seed_hadis_statuses(self): |
|||
"""Create HadisStatus records""" |
|||
self.stdout.write("Creating Hadis Statuses...") |
|||
|
|||
statuses_data = [ |
|||
{'title': 'Достоверный', 'color': 'green', 'order': 1}, |
|||
{'title': 'Хороший', 'color': 'blue', 'order': 2}, |
|||
{'title': 'Слабый', 'color': 'yellow', 'order': 3}, |
|||
{'title': 'Выдуманный', 'color': 'red', 'order': 4}, |
|||
] |
|||
|
|||
statuses = [] |
|||
for data in statuses_data: |
|||
status, created = HadisStatus.objects.get_or_create( |
|||
title=data['title'], |
|||
defaults=data |
|||
) |
|||
statuses.append(status) |
|||
if created: |
|||
self.stdout.write(f" Created status: {status.title}") |
|||
|
|||
return statuses |
|||
|
|||
def seed_hadis_tags(self): |
|||
"""Create HadisTag records""" |
|||
self.stdout.write("Creating Hadis Tags...") |
|||
|
|||
tags_data = [ |
|||
'Поклонение', 'Молитва', 'Пост', 'Хадж', 'Закят', |
|||
'Нравственность', 'Терпение', 'Справедливость', |
|||
'Фикх', 'Предписания', 'Толкование', 'Коран', |
|||
'Имамат', 'Мольба', 'Единобожие' |
|||
] |
|||
|
|||
tags = [] |
|||
for tag_title in tags_data: |
|||
tag, created = HadisTag.objects.get_or_create( |
|||
title=tag_title, |
|||
defaults={'status': True} |
|||
) |
|||
tags.append(tag) |
|||
if created: |
|||
self.stdout.write(f" Created tag: {tag.title}") |
|||
|
|||
return tags |
|||
|
|||
def seed_hadis_sects(self): |
|||
"""Create HadisSect records""" |
|||
self.stdout.write("Creating Hadis Sects...") |
|||
|
|||
sects_data = [ |
|||
{'sect_type': 'shia', 'title': 'Шииты-двунадесятники', 'is_active': True, 'order': 1}, |
|||
{'sect_type': 'sunni', 'title': 'Сунниты', 'is_active': True, 'order': 2}, |
|||
] |
|||
|
|||
sects = [] |
|||
for data in sects_data: |
|||
self.stdout.write(f" Processing sect: {data['sect_type']}") |
|||
|
|||
# Check if sect exists |
|||
try: |
|||
sect = HadisSect.objects.get(sect_type=data['sect_type']) |
|||
self.stdout.write(f" Sect already exists: {sect.title}") |
|||
sects.append(sect) |
|||
except HadisSect.DoesNotExist: |
|||
# Create new sect |
|||
self.stdout.write(f" Creating new sect: {data['sect_type']}") |
|||
sect = HadisSect( |
|||
sect_type=data['sect_type'], |
|||
title=data['title'], |
|||
is_active=data['is_active'], |
|||
order=data['order'] |
|||
) |
|||
sect.save() |
|||
self.stdout.write(f" Created sect: {sect.title}") |
|||
sects.append(sect) |
|||
|
|||
return sects |
|||
@ -0,0 +1,934 @@ |
|||
""" |
|||
Comprehensive data seeding management command for Hadis app models. |
|||
This command creates realistic sample records for all Hadis app models |
|||
while maintaining proper relationships and business domain logic. |
|||
""" |
|||
|
|||
import random |
|||
import time |
|||
from pathlib import Path |
|||
from django.core.management.base import BaseCommand, CommandError |
|||
from django.core.files import File |
|||
from django.core.files.base import ContentFile |
|||
from django.db import connection |
|||
from django.db.utils import OperationalError, IntegrityError |
|||
|
|||
# Import models |
|||
from apps.hadis.models import ( |
|||
HadisSect, HadisCategory, HadisStatus, HadisTag, Hadis, |
|||
Transmitters, HadisTransmitter, HadisReference, ReferenceImage |
|||
) |
|||
from apps.library.models import Book, Category as LibraryCategory, BookCollection |
|||
|
|||
|
|||
class Command(BaseCommand): |
|||
help = 'Seed comprehensive data for Hadis app models' |
|||
|
|||
def add_arguments(self, parser): |
|||
parser.add_argument( |
|||
'--clear', |
|||
action='store_true', |
|||
help='Clear existing hadis data before seeding', |
|||
) |
|||
parser.add_argument( |
|||
'--images-dir', |
|||
type=str, |
|||
default='scripts/seed_images', |
|||
help='Directory containing seed images (default: scripts/seed_images)', |
|||
) |
|||
parser.add_argument( |
|||
'--xmind-file', |
|||
type=str, |
|||
default='scripts/test.xmind', |
|||
help='Path to XMind file (default: scripts/test.xmind)', |
|||
) |
|||
|
|||
def __init__(self, *args, **kwargs): |
|||
super().__init__(*args, **kwargs) |
|||
self.seed_images_dir = None |
|||
self.xmind_file_path = None |
|||
self.image_files = [] |
|||
self.retry_delay = 2 # seconds |
|||
self.max_retries = 5 |
|||
|
|||
def handle(self, **options): |
|||
self.setup_paths(options) |
|||
|
|||
# Check database status before starting |
|||
self.stdout.write("🔍 Checking database status...") |
|||
self.check_database_locks() |
|||
|
|||
if options['clear']: |
|||
self.stdout.write("🧹 Clearing existing data...") |
|||
self.safe_execute_with_retry("Clear existing data", self.clear_existing_data) |
|||
|
|||
try: |
|||
self.stdout.write( |
|||
self.style.SUCCESS('🚀 Starting Hadis data seeding...') |
|||
) |
|||
|
|||
# Seed data in proper order WITHOUT transaction.atomic() to avoid locks |
|||
self.stdout.write("📊 Step 1: Creating basic lookup data...") |
|||
statuses = self.safe_execute_with_retry("Seed statuses", self.seed_hadis_statuses) |
|||
|
|||
self.stdout.write("🏷️ Step 2: Creating tags...") |
|||
tags = self.safe_execute_with_retry("Seed tags", self.seed_hadis_tags) |
|||
|
|||
self.stdout.write("🕌 Step 3: Creating sects...") |
|||
sects = self.safe_execute_with_retry("Seed sects", self.seed_hadis_sects) |
|||
|
|||
self.stdout.write("📚 Step 4: Creating categories...") |
|||
categories = self.safe_execute_with_retry("Seed categories", self.seed_hadis_categories, sects) |
|||
|
|||
self.stdout.write("📖 Step 5: Creating library data...") |
|||
books, _, _ = self.safe_execute_with_retry("Seed library data", self.seed_library_data) |
|||
|
|||
self.stdout.write("👥 Step 6: Creating transmitters...") |
|||
transmitters = self.safe_execute_with_retry("Seed transmitters", self.seed_transmitters) |
|||
|
|||
self.stdout.write("📜 Step 7: Creating hadis records...") |
|||
self.safe_execute_with_retry("Seed hadis records", self.seed_hadis_records, |
|||
categories, statuses, tags, transmitters, books) |
|||
|
|||
self.stdout.write( |
|||
self.style.SUCCESS('✅ Successfully seeded all Hadis data!') |
|||
) |
|||
|
|||
except Exception as e: |
|||
self.stdout.write( |
|||
self.style.ERROR(f'❌ Error during seeding: {str(e)}') |
|||
) |
|||
import traceback |
|||
self.stdout.write(self.style.ERROR(traceback.format_exc())) |
|||
raise CommandError(f'Seeding failed: {str(e)}') |
|||
|
|||
def setup_paths(self, options): |
|||
"""Setup file paths and verify required files exist""" |
|||
self.seed_images_dir = Path(options['images_dir']) |
|||
self.xmind_file_path = Path(options['xmind_file']) |
|||
|
|||
# Verify required files exist |
|||
if not self.seed_images_dir.exists(): |
|||
raise CommandError(f"Seed images directory not found: {self.seed_images_dir}") |
|||
|
|||
# Get available images |
|||
self.image_files = list(self.seed_images_dir.glob('*.png')) |
|||
if not self.image_files: |
|||
raise CommandError("No PNG images found in seed_images directory") |
|||
|
|||
self.stdout.write(f"Found {len(self.image_files)} seed images") |
|||
if self.xmind_file_path.exists(): |
|||
self.stdout.write(f"XMind file: {self.xmind_file_path}") |
|||
else: |
|||
self.stdout.write(self.style.WARNING(f"XMind file not found: {self.xmind_file_path}")) |
|||
|
|||
def clear_existing_data(self): |
|||
"""Clear existing hadis data (optional - for clean seeding)""" |
|||
self.stdout.write("Clearing existing hadis data...") |
|||
|
|||
# Clear in reverse dependency order |
|||
ReferenceImage.objects.all().delete() |
|||
HadisReference.objects.all().delete() |
|||
HadisTransmitter.objects.all().delete() |
|||
Hadis.objects.all().delete() |
|||
HadisCategory.objects.all().delete() |
|||
HadisSect.objects.all().delete() |
|||
HadisStatus.objects.all().delete() |
|||
HadisTag.objects.all().delete() |
|||
Transmitters.objects.all().delete() |
|||
|
|||
self.stdout.write("Existing data cleared.") |
|||
|
|||
def safe_execute_with_retry(self, operation_name, operation_func, *args, **kwargs): |
|||
"""Execute database operation with retry logic for handling locks""" |
|||
for attempt in range(self.max_retries): |
|||
try: |
|||
self.stdout.write(f" Attempting {operation_name} (attempt {attempt + 1}/{self.max_retries})") |
|||
result = operation_func(*args, **kwargs) |
|||
self.stdout.write(f" ✓ {operation_name} completed successfully") |
|||
return result |
|||
|
|||
except OperationalError as e: |
|||
error_msg = str(e).lower() |
|||
if 'database is locked' in error_msg or 'deadlock' in error_msg: |
|||
self.stdout.write( |
|||
self.style.WARNING( |
|||
f" ⚠ Database lock detected in {operation_name}: {str(e)}" |
|||
) |
|||
) |
|||
if attempt < self.max_retries - 1: |
|||
self.stdout.write(f" ⏳ Waiting {self.retry_delay} seconds before retry...") |
|||
time.sleep(self.retry_delay) |
|||
# Increase delay for next attempt |
|||
self.retry_delay = min(self.retry_delay * 1.5, 10) |
|||
else: |
|||
self.stdout.write( |
|||
self.style.ERROR(f" ❌ Max retries reached for {operation_name}") |
|||
) |
|||
raise |
|||
else: |
|||
# Non-lock related error, don't retry |
|||
self.stdout.write( |
|||
self.style.ERROR(f" ❌ Non-lock error in {operation_name}: {str(e)}") |
|||
) |
|||
raise |
|||
|
|||
except IntegrityError as e: |
|||
# Handle unique constraint violations gracefully |
|||
if 'unique' in str(e).lower() or 'duplicate' in str(e).lower(): |
|||
self.stdout.write( |
|||
self.style.WARNING(f" ⚠ Record already exists in {operation_name}: {str(e)}") |
|||
) |
|||
return None # Indicate that record already exists |
|||
else: |
|||
self.stdout.write( |
|||
self.style.ERROR(f" ❌ Integrity error in {operation_name}: {str(e)}") |
|||
) |
|||
raise |
|||
|
|||
except Exception as e: |
|||
self.stdout.write( |
|||
self.style.ERROR(f" ❌ Unexpected error in {operation_name}: {str(e)}") |
|||
) |
|||
raise |
|||
|
|||
def check_database_locks(self): |
|||
"""Check for existing database locks""" |
|||
try: |
|||
with connection.cursor() as cursor: |
|||
# Check for SQLite locks (if using SQLite) |
|||
cursor.execute("PRAGMA locking_mode;") |
|||
locking_mode = cursor.fetchone() |
|||
self.stdout.write(f"Database locking mode: {locking_mode}") |
|||
|
|||
# Force a simple query to test connectivity |
|||
cursor.execute("SELECT 1;") |
|||
cursor.fetchone() |
|||
|
|||
except Exception as e: |
|||
self.stdout.write( |
|||
self.style.WARNING(f"Could not check database locks: {str(e)}") |
|||
) |
|||
|
|||
def create_single_status(self, status_data): |
|||
"""Create a single status with proper error handling""" |
|||
status, created = HadisStatus.objects.get_or_create( |
|||
title=status_data['title'], |
|||
defaults=status_data |
|||
) |
|||
if created: |
|||
self.stdout.write(f" ✅ Created status: {status.title}") |
|||
else: |
|||
self.stdout.write(f" ✓ Status already exists: {status.title}") |
|||
return status |
|||
|
|||
def seed_hadis_statuses(self): |
|||
"""Create HadisStatus records""" |
|||
self.stdout.write("Creating Hadis Statuses...") |
|||
|
|||
statuses_data = [ |
|||
{'title': 'Authentic', 'color': 'green', 'order': 1}, |
|||
{'title': 'Good', 'color': 'blue', 'order': 2}, |
|||
{'title': 'Weak', 'color': 'yellow', 'order': 3}, |
|||
{'title': 'Fabricated', 'color': 'red', 'order': 4}, |
|||
{'title': 'Interrupted', 'color': 'orange', 'order': 5}, |
|||
{'title': 'Broken', 'color': 'purple', 'order': 6}, |
|||
{'title': 'Unknown', 'color': 'gray', 'order': 7}, |
|||
] |
|||
|
|||
statuses = [] |
|||
for i, data in enumerate(statuses_data): |
|||
self.stdout.write(f" 📋 Processing status {i+1}/{len(statuses_data)}: {data['title']}") |
|||
|
|||
# Add small delay between operations |
|||
if i > 0: |
|||
time.sleep(0.2) |
|||
|
|||
status = self.safe_execute_with_retry( |
|||
f"Create status {data['title']}", |
|||
self.create_single_status, |
|||
data |
|||
) |
|||
|
|||
if status: |
|||
statuses.append(status) |
|||
|
|||
self.stdout.write(f"✅ Successfully processed {len(statuses)} statuses") |
|||
return statuses |
|||
|
|||
def create_single_tag(self, tag_title): |
|||
"""Create a single tag with proper error handling""" |
|||
tag, created = HadisTag.objects.get_or_create( |
|||
title=tag_title, |
|||
defaults={'status': True} |
|||
) |
|||
if created: |
|||
self.stdout.write(f" ✅ Created tag: {tag.title}") |
|||
else: |
|||
self.stdout.write(f" ✓ Tag already exists: {tag.title}") |
|||
return tag |
|||
|
|||
def seed_hadis_tags(self): |
|||
"""Create HadisTag records""" |
|||
self.stdout.write("Creating Hadis Tags...") |
|||
|
|||
tags_data = [ |
|||
'Worship', 'Prayer', 'Fasting', 'Hajj', 'Zakat', 'Khums', |
|||
'Ethics', 'Patience', 'Gratitude', 'Trust', 'Piety', 'Justice', |
|||
'Fiqh', 'Rulings', 'Halal', 'Haram', 'Mustahab', 'Makruh', |
|||
'Interpretation', 'Quran', 'Verses', 'Surah', 'Recitation', |
|||
'Imamate', 'Authority', 'Infallibles', 'Prophets Family', |
|||
'Supplication', 'Remembrance', 'Forgiveness', 'Praise', 'Monotheism' |
|||
] |
|||
|
|||
tags = [] |
|||
# Process tags in smaller batches to avoid locks |
|||
batch_size = 5 |
|||
for i in range(0, len(tags_data), batch_size): |
|||
batch = tags_data[i:i + batch_size] |
|||
self.stdout.write(f" 📋 Processing tag batch {i//batch_size + 1}/{(len(tags_data) + batch_size - 1)//batch_size}") |
|||
|
|||
for j, tag_title in enumerate(batch): |
|||
# Add small delay between operations |
|||
if j > 0: |
|||
time.sleep(0.1) |
|||
|
|||
tag = self.safe_execute_with_retry( |
|||
f"Create tag {tag_title}", |
|||
self.create_single_tag, |
|||
tag_title |
|||
) |
|||
|
|||
if tag: |
|||
tags.append(tag) |
|||
|
|||
# Delay between batches |
|||
if i + batch_size < len(tags_data): |
|||
time.sleep(0.5) |
|||
|
|||
self.stdout.write(f"✅ Successfully processed {len(tags)} tags") |
|||
return tags |
|||
|
|||
def create_single_sect(self, sect_data): |
|||
"""Create a single sect with proper error handling""" |
|||
sect_type = sect_data['sect_type'] |
|||
|
|||
# Check if sect already exists |
|||
try: |
|||
existing_sect = HadisSect.objects.get(sect_type=sect_type) |
|||
self.stdout.write(f" ✓ Sect '{sect_type}' already exists: {existing_sect.title}") |
|||
return existing_sect |
|||
except HadisSect.DoesNotExist: |
|||
pass |
|||
|
|||
# Create new sect |
|||
self.stdout.write(f" 🔨 Creating new sect: {sect_type}") |
|||
sect = HadisSect( |
|||
sect_type=sect_data['sect_type'], |
|||
title=sect_data['title'], |
|||
is_active=sect_data['is_active'], |
|||
order=sect_data['order'] |
|||
) |
|||
sect.save() |
|||
self.stdout.write(f" ✅ Created sect: {sect.title}") |
|||
return sect |
|||
|
|||
def seed_hadis_sects(self): |
|||
"""Create HadisSect records""" |
|||
self.stdout.write("Creating Hadis Sects...") |
|||
|
|||
sects_data = [ |
|||
{'sect_type': 'shia', 'title': 'Shia Twelvers', 'is_active': True, 'order': 1}, |
|||
{'sect_type': 'sunni', 'title': 'Sunni', 'is_active': True, 'order': 2}, |
|||
] |
|||
|
|||
sects = [] |
|||
|
|||
# Process each sect individually with delay |
|||
for i, data in enumerate(sects_data): |
|||
sect_type = data['sect_type'] |
|||
self.stdout.write(f" 📋 Processing sect {i+1}/{len(sects_data)}: {sect_type}") |
|||
|
|||
# Add small delay between operations to prevent locks |
|||
if i > 0: |
|||
time.sleep(0.5) |
|||
|
|||
sect = self.safe_execute_with_retry( |
|||
f"Create sect {sect_type}", |
|||
self.create_single_sect, |
|||
data |
|||
) |
|||
|
|||
if sect: |
|||
sects.append(sect) |
|||
|
|||
self.stdout.write(f"✅ Successfully processed {len(sects)} sects") |
|||
return sects |
|||
|
|||
def assign_xmind_file(self, category): |
|||
"""Assign XMind file to category""" |
|||
if not self.xmind_file_path.exists(): |
|||
return False |
|||
|
|||
try: |
|||
with open(self.xmind_file_path, 'rb') as f: |
|||
file_content = f.read() |
|||
|
|||
# Create unique filename for each category |
|||
filename = f"category_{category.id}_{category.title[:20]}.xmind" |
|||
category.xmind_file.save( |
|||
filename, |
|||
ContentFile(file_content), |
|||
save=True |
|||
) |
|||
return True |
|||
except Exception as e: |
|||
self.stdout.write( |
|||
self.style.WARNING(f"Could not assign XMind file to {category.title}: {e}") |
|||
) |
|||
return False |
|||
|
|||
def create_single_category(self, sect, source_type, title, order, parent=None): |
|||
"""Create a single category with proper MPTT handling""" |
|||
try: |
|||
# Check if category already exists |
|||
existing_category = HadisCategory.objects.get( |
|||
sect=sect, |
|||
source_type=source_type, |
|||
title=title, |
|||
parent=parent |
|||
) |
|||
self.stdout.write(f" ✓ Category already exists: {title}") |
|||
return existing_category |
|||
except HadisCategory.DoesNotExist: |
|||
pass |
|||
|
|||
# Create new category (MPTT will handle tree fields automatically) |
|||
self.stdout.write(f" 🔨 Creating category: {title}") |
|||
category = HadisCategory.objects.create( |
|||
sect=sect, |
|||
source_type=source_type, |
|||
title=title, |
|||
order=order, |
|||
parent=parent |
|||
) |
|||
self.stdout.write(f" ✅ Created category: {title}") |
|||
return category |
|||
|
|||
def seed_hadis_categories(self, sects): |
|||
"""Create HadisCategory records with hierarchical structure - MPTT safe creation""" |
|||
self.stdout.write("Creating Hadis Categories...") |
|||
|
|||
categories = [] |
|||
|
|||
for sect in sects: |
|||
self.stdout.write(f" 📋 Creating categories for {sect.title}...") |
|||
|
|||
# Quran categories - create one by one to avoid MPTT issues |
|||
quran_categories_data = [ |
|||
{'title': 'Quran Interpretation', 'order': 1}, |
|||
{'title': 'Verses of Rulings', 'order': 2}, |
|||
{'title': 'Quran Stories', 'order': 3}, |
|||
{'title': 'Virtues of Surahs', 'order': 4}, |
|||
{'title': 'Quran Miracles', 'order': 5}, |
|||
{'title': 'Quranic Sciences', 'order': 6}, |
|||
] |
|||
|
|||
# Create main Quran categories one by one |
|||
quran_parent_categories = [] |
|||
for i, cat_data in enumerate(quran_categories_data): |
|||
# Add delay between operations |
|||
if i > 0: |
|||
time.sleep(0.3) |
|||
|
|||
category = self.safe_execute_with_retry( |
|||
f"Create Quran category {cat_data['title']}", |
|||
self.create_single_category, |
|||
sect, 'quran', cat_data['title'], cat_data['order'] |
|||
) |
|||
|
|||
if category: |
|||
categories.append(category) |
|||
quran_parent_categories.append(category) |
|||
|
|||
# Create child categories for Quran |
|||
self.stdout.write(" 📂 Creating Quran child categories...") |
|||
for parent_category in quran_parent_categories: |
|||
child_categories_data = [] |
|||
|
|||
if parent_category.title == 'Quran Interpretation': |
|||
child_categories_data = [ |
|||
{'title': 'Surah Al-Fatiha Interpretation', 'order': 1}, |
|||
{'title': 'Surah Al-Baqara Interpretation', 'order': 2}, |
|||
{'title': 'Surah Al Imran Interpretation', 'order': 3}, |
|||
] |
|||
elif parent_category.title == 'Verses of Rulings': |
|||
child_categories_data = [ |
|||
{'title': 'Prayer Verses', 'order': 1}, |
|||
{'title': 'Fasting Verses', 'order': 2}, |
|||
{'title': 'Zakat Verses', 'order': 3}, |
|||
] |
|||
elif parent_category.title == 'Quran Stories': |
|||
child_categories_data = [ |
|||
{'title': 'Prophets Stories', 'order': 1}, |
|||
{'title': 'Righteous People Stories', 'order': 2}, |
|||
] |
|||
|
|||
# Create child categories one by one |
|||
for j, child_data in enumerate(child_categories_data): |
|||
# Add delay between operations |
|||
if j > 0: |
|||
time.sleep(0.2) |
|||
|
|||
child_category = self.safe_execute_with_retry( |
|||
f"Create child category {child_data['title']}", |
|||
self.create_single_category, |
|||
sect, 'quran', child_data['title'], child_data['order'], parent_category |
|||
) |
|||
|
|||
if child_category: |
|||
categories.append(child_category) |
|||
|
|||
# Assign XMind file to some categories |
|||
if random.choice([True, False]) and not parent_category.xmind_file: |
|||
self.assign_xmind_file(parent_category) |
|||
|
|||
# Hadith categories - create one by one |
|||
self.stdout.write(" 📚 Creating Hadith categories...") |
|||
hadith_categories_data = [ |
|||
{'title': 'Book of Purification', 'order': 1}, |
|||
{'title': 'Book of Prayer', 'order': 2}, |
|||
{'title': 'Book of Fasting', 'order': 3}, |
|||
{'title': 'Book of Hajj', 'order': 4}, |
|||
{'title': 'Book of Zakat', 'order': 5}, |
|||
{'title': 'Book of Ethics', 'order': 6}, |
|||
] |
|||
|
|||
# Create main Hadith categories one by one |
|||
hadith_parent_categories = [] |
|||
for i, cat_data in enumerate(hadith_categories_data): |
|||
# Add delay between operations |
|||
if i > 0: |
|||
time.sleep(0.3) |
|||
|
|||
category = self.safe_execute_with_retry( |
|||
f"Create Hadith category {cat_data['title']}", |
|||
self.create_single_category, |
|||
sect, 'hadith', cat_data['title'], cat_data['order'] |
|||
) |
|||
|
|||
if category: |
|||
categories.append(category) |
|||
hadith_parent_categories.append(category) |
|||
|
|||
# Create child categories for Hadith |
|||
self.stdout.write(" 📂 Creating Hadith child categories...") |
|||
for parent_category in hadith_parent_categories: |
|||
child_categories_data = [] |
|||
|
|||
if parent_category.title == 'Book of Purification': |
|||
child_categories_data = [ |
|||
{'title': 'Ablution', 'order': 1}, |
|||
{'title': 'Full Bath', 'order': 2}, |
|||
{'title': 'Dry Ablution', 'order': 3}, |
|||
] |
|||
elif parent_category.title == 'Book of Prayer': |
|||
child_categories_data = [ |
|||
{'title': 'Prayer Times', 'order': 1}, |
|||
{'title': 'Qibla Direction', 'order': 2}, |
|||
{'title': 'Congregational Prayer', 'order': 3}, |
|||
] |
|||
elif parent_category.title == 'Book of Ethics': |
|||
child_categories_data = [ |
|||
{'title': 'Patience and Gratitude', 'order': 1}, |
|||
{'title': 'Justice and Honesty', 'order': 2}, |
|||
] |
|||
|
|||
# Create child categories one by one |
|||
for j, child_data in enumerate(child_categories_data): |
|||
# Add delay between operations |
|||
if j > 0: |
|||
time.sleep(0.2) |
|||
|
|||
child_category = self.safe_execute_with_retry( |
|||
f"Create child category {child_data['title']}", |
|||
self.create_single_category, |
|||
sect, 'hadith', child_data['title'], child_data['order'], parent_category |
|||
) |
|||
|
|||
if child_category: |
|||
categories.append(child_category) |
|||
|
|||
# Assign XMind file to some categories |
|||
if random.choice([True, False]) and not parent_category.xmind_file: |
|||
self.assign_xmind_file(parent_category) |
|||
|
|||
self.stdout.write(f"✅ Successfully processed {len(categories)} categories") |
|||
return categories |
|||
|
|||
def seed_library_data(self): |
|||
"""Create library data (books, categories, collections) for references""" |
|||
self.stdout.write("Creating Library data...") |
|||
|
|||
# Create library categories |
|||
lib_categories_data = [ |
|||
'Книги хадисов', 'Книги фикха', 'Книги толкования', 'Книги нравственности', 'Исторические книги' |
|||
] |
|||
|
|||
lib_categories = [] |
|||
for cat_title in lib_categories_data: |
|||
category, created = LibraryCategory.objects.get_or_create( |
|||
title=cat_title, |
|||
defaults={'status': True} |
|||
) |
|||
lib_categories.append(category) |
|||
if created: |
|||
self.stdout.write(f" Created library category: {category.title}") |
|||
|
|||
# Create book collections |
|||
collections_data = [ |
|||
{'title': 'Шиитские книги хадисов', 'display_position': 'pinned'}, |
|||
{'title': 'Суннитские книги хадисов', 'display_position': 'middle'}, |
|||
{'title': 'Сборник книг по фикху', 'display_position': 'middle'}, |
|||
] |
|||
|
|||
collections = [] |
|||
for coll_data in collections_data: |
|||
collection, created = BookCollection.objects.get_or_create( |
|||
title=coll_data['title'], |
|||
defaults={ |
|||
'summary': f'Коллекция {coll_data["title"]}', |
|||
'display_position': coll_data['display_position'], |
|||
'status': True, |
|||
'order': len(collections) + 1 |
|||
} |
|||
) |
|||
collections.append(collection) |
|||
if created: |
|||
self.stdout.write(f" Created collection: {collection.title}") |
|||
|
|||
# Create books with cover images |
|||
books_data = [ |
|||
{ |
|||
'title': 'Аль-Кафи', |
|||
'summary_title': 'Книга Аль-Кафи шейха Кулейни', |
|||
'summary': 'Одна из важнейших книг хадисов шиитов', |
|||
'description': 'Книга Аль-Кафи, написанная Мухаммадом ибн Якубом Кулейни, является одной из четырех достоверных книг хадисов шиитов.', |
|||
'publisher': 'Дар аль-Кутуб аль-Исламийя', |
|||
'year_of_publication': '1407', |
|||
'isbn': '978-964-372-001-1', |
|||
'pages_count': '2847', |
|||
'file_type': 'pdf' |
|||
}, |
|||
{ |
|||
'title': 'Сахих аль-Бухари', |
|||
'summary_title': 'Сахих аль-Бухари имама Бухари', |
|||
'summary': 'Самая достоверная книга хадисов суннитов', |
|||
'description': 'Сахих аль-Бухари, написанный Мухаммадом ибн Исмаилом Бухари, является самой достоверной книгой хадисов у суннитов.', |
|||
'publisher': 'Дар Тук ан-Наджа', |
|||
'year_of_publication': '1422', |
|||
'isbn': '978-964-372-002-2', |
|||
'pages_count': '1896', |
|||
'file_type': 'pdf' |
|||
}, |
|||
{ |
|||
'title': 'Ман ля яхдуруху аль-факих', |
|||
'summary_title': 'Ман ля яхдуруху аль-факих шейха Садука', |
|||
'summary': 'Важная книга по фикху и хадисам шиитов', |
|||
'description': 'Книга Ман ля яхдуруху аль-факих, написанная шейхом Садуком, является одной из четырех книг шиитов.', |
|||
'publisher': 'Муассаса ан-Нашр аль-Ислами', |
|||
'year_of_publication': '1413', |
|||
'isbn': '978-964-372-003-3', |
|||
'pages_count': '1524', |
|||
'file_type': 'pdf' |
|||
}, |
|||
{ |
|||
'title': 'Сунан Абу Дауд', |
|||
'summary_title': 'Сунан Абу Дауд имама Абу Дауда', |
|||
'summary': 'Одна из шести книг суннитов', |
|||
'description': 'Сунан Абу Дауд, написанная Сулейманом ибн Ашасом Сиджистани, является одной из шести книг суннитов.', |
|||
'publisher': 'Аль-Мактаба аль-Асрийя', |
|||
'year_of_publication': '1430', |
|||
'isbn': '978-964-372-004-4', |
|||
'pages_count': '1342', |
|||
'file_type': 'pdf' |
|||
}, |
|||
] |
|||
|
|||
books = [] |
|||
for book_data in books_data: |
|||
# Get random image for book cover |
|||
image_file = random.choice(self.image_files) |
|||
|
|||
book, created = Book.objects.get_or_create( |
|||
title=book_data['title'], |
|||
defaults=book_data |
|||
) |
|||
|
|||
if created: |
|||
# Assign cover image |
|||
try: |
|||
with open(image_file, 'rb') as f: |
|||
book.thumbnail.save( |
|||
f"book_cover_{book.id}.png", |
|||
File(f), |
|||
save=True |
|||
) |
|||
self.stdout.write(f" Created book: {book.title} with cover image") |
|||
except Exception as e: |
|||
self.stdout.write(f" Created book: {book.title} (no cover image: {e})") |
|||
|
|||
# Assign to categories and collections |
|||
if lib_categories: |
|||
book.categories.add(random.choice(lib_categories)) |
|||
if collections: |
|||
book.collections.add(random.choice(collections)) |
|||
|
|||
books.append(book) |
|||
|
|||
return books, lib_categories, collections |
|||
|
|||
def seed_transmitters(self): |
|||
"""Create Transmitters records""" |
|||
self.stdout.write("Creating Transmitters...") |
|||
|
|||
transmitters_data = [ |
|||
{ |
|||
'full_name': 'Мухаммад ибн Якуб Кулейни', |
|||
'birth_year_hijri': 250, |
|||
'death_year_hijri': 329, |
|||
'description': 'Шейх Кулейни, автор книги Аль-Кафи и один из великих мухаддисов шиитов' |
|||
}, |
|||
{ |
|||
'full_name': 'Мухаммад ибн Али ибн Бабавейх (Шейх Садук)', |
|||
'birth_year_hijri': 306, |
|||
'death_year_hijri': 381, |
|||
'description': 'Шейх Садук, автор книги Ман ля яхдуруху аль-факих' |
|||
}, |
|||
{ |
|||
'full_name': 'Мухаммад ибн аль-Хасан ат-Туси', |
|||
'birth_year_hijri': 385, |
|||
'death_year_hijri': 460, |
|||
'description': 'Шейх Туси, автор книг Тахзиб аль-Ахкам и аль-Истибсар' |
|||
}, |
|||
{ |
|||
'full_name': 'Мухаммад ибн Исмаил аль-Бухари', |
|||
'birth_year_hijri': 194, |
|||
'death_year_hijri': 256, |
|||
'description': 'Имам Бухари, автор Сахих аль-Бухари' |
|||
}, |
|||
{ |
|||
'full_name': 'Муслим ибн аль-Хаджжадж ан-Нишапури', |
|||
'birth_year_hijri': 206, |
|||
'death_year_hijri': 261, |
|||
'description': 'Имам Муслим, автор Сахих Муслим' |
|||
}, |
|||
{ |
|||
'full_name': 'Абу Дауд ас-Сиджистани', |
|||
'birth_year_hijri': 202, |
|||
'death_year_hijri': 275, |
|||
'description': 'Имам Абу Дауд, автор Сунан Абу Дауд' |
|||
}, |
|||
{ |
|||
'full_name': 'Джафар ибн Мухаммад ас-Садик', |
|||
'birth_year_hijri': 83, |
|||
'death_year_hijri': 148, |
|||
'description': 'Имам Джафар Садик (мир ему), шестой имам шиитов' |
|||
}, |
|||
{ |
|||
'full_name': 'Мухаммад ибн Али аль-Бакир', |
|||
'birth_year_hijri': 57, |
|||
'death_year_hijri': 114, |
|||
'description': 'Имам Мухаммад Бакир (мир ему), пятый имам шиитов' |
|||
}, |
|||
{ |
|||
'full_name': 'Али ибн аль-Хусейн ас-Саджжад', |
|||
'birth_year_hijri': 38, |
|||
'death_year_hijri': 95, |
|||
'description': 'Имам Али ибн аль-Хусейн (мир ему), четвертый имам шиитов' |
|||
}, |
|||
{ |
|||
'full_name': 'Мухаммад ибн Муслим', |
|||
'birth_year_hijri': 70, |
|||
'death_year_hijri': 150, |
|||
'description': 'Мухаммад ибн Муслим, из сподвижников имама Бакира и имама Садика (мир им)' |
|||
}, |
|||
] |
|||
|
|||
transmitters = [] |
|||
for trans_data in transmitters_data: |
|||
transmitter, created = Transmitters.objects.get_or_create( |
|||
full_name=trans_data['full_name'], |
|||
defaults=trans_data |
|||
) |
|||
transmitters.append(transmitter) |
|||
if created: |
|||
self.stdout.write(f" Created transmitter: {transmitter.full_name}") |
|||
|
|||
return transmitters |
|||
|
|||
def seed_hadis_records(self, categories, statuses, tags, transmitters, books): |
|||
"""Create Hadis records with proper relationships - optimized batch creation""" |
|||
self.stdout.write("Creating Hadis records...") |
|||
|
|||
# Get only leaf categories (categories without children) - optimized query |
|||
from django.db import models |
|||
leaf_categories = HadisCategory.objects.filter( |
|||
id__in=[cat.id for cat in categories] |
|||
).annotate( |
|||
children_count=models.Count('children') |
|||
).filter(children_count=0) |
|||
|
|||
self.stdout.write(f"Found {len(leaf_categories)} leaf categories for hadis creation") |
|||
|
|||
# Comprehensive hadis samples with longer texts |
|||
hadis_samples = { |
|||
'prayer': [ |
|||
{ |
|||
'title': 'Достоинство молитвы и ее место в религии', |
|||
'text': '''قال رسول الله صلى الله عليه وآله: الصلاة عمود الدين، إن قبلت قبل ما سواها، وإن ردت رد ما سواها. وهي أول ما يحاسب عليه العبد يوم القيامة، فإن صلحت صلح سائر عمله، وإن فسدت فسد سائر عمله. |
|||
|
|||
والصلاة معراج المؤمن، وهي قربان كل تقي، وهي حب الله تعالى. من أحبها وأقامها في أوقاتها وحافظ على حدودها رفعه الله إلى درجة الأبرار. ومن استخف بها وضيعها وتركها فقد استخف بدين الله، ولا نصيب له في الإسلام. |
|||
|
|||
إن الله تعالى فرض خمس صلوات في اليوم والليلة، وجعل لكل صلاة وقتاً معلوماً، فمن صلاها في وقتها وأتم ركوعها وسجودها وخشوعها، كانت له نوراً وبرهاناً ونجاة يوم القيامة.''', |
|||
'translation': [ |
|||
{'language_code': 'ru', 'title': '''Сказал Посланник Аллаха (да благословит Аллах его и его семейство): Молитва - столп религии, если она принята, то принято и остальное, а если отвергнута, то отвергнуто и остальное. Это первое, за что будет спрошен раб в День Воскресения, и если она будет правильной, то правильными будут и остальные его дела, а если испорчена, то испорчены и остальные его дела. |
|||
|
|||
Молитва - это вознесение верующего, она - приношение каждого богобоязненного, она - любовь Всевышнего Аллаха. Кто полюбил ее и совершал ее в установленные времена и соблюдал ее границы, того Аллах возвысит до степени праведников. А кто пренебрег ею, потерял ее и оставил, тот пренебрег религией Аллаха, и нет ему доли в Исламе. |
|||
|
|||
Поистине, Всевышний Аллах предписал пять молитв в сутки и установил для каждой молитвы определенное время. Кто совершал их в свое время и завершал их поклоны, земные поклоны и смирение, для того они станут светом, доказательством и спасением в День Воскресения.'''}, |
|||
{'language_code': 'fa', 'title': '''رسول خدا فرمود: نماز ستون دین است، اگر پذیرفته شود غیر آن نیز پذیرفته میشود و اگر رد شود غیر آن نیز رد میشود. و این اولین چیزی است که بنده در روز قیامت از آن بازخواست میشود، پس اگر درست باشد تمام اعمالش درست است و اگر فاسد باشد تمام اعمالش فاسد است. |
|||
|
|||
نماز معراج مؤمن است و قربانی هر پرهیزکار و محبت خداوند متعال است. هر کس آن را دوست بدارد و در اوقاتش برپا دارد و حدودش را نگه دارد، خداوند او را به درجه نیکان بالا میبرد. و هر کس آن را سبک بشمارد و ضایع کند و ترک کند، دین خدا را سبک شمرده و بهرهای در اسلام ندارد. |
|||
|
|||
خداوند متعال پنج نماز در شبانهروز واجب کرده و برای هر نماز وقت معینی قرار داده، پس هر کس آنها را در وقتشان بخواند و رکوع و سجود و خشوعشان را کامل کند، برایش نور و برهان و نجات در روز قیامت خواهد بود.'''}, |
|||
{'language_code': 'en', 'title': '''The Messenger of Allah said: Prayer is the pillar of religion, if it is accepted, other deeds are accepted, and if it is rejected, other deeds are rejected. It is the first thing for which a servant will be held accountable on the Day of Judgment, and if it is sound, all his other deeds will be sound, and if it is corrupted, all his other deeds will be corrupted. |
|||
|
|||
Prayer is the ascension of the believer, it is the offering of every God-fearing person, and it is the love of Allah the Almighty. Whoever loves it and establishes it at its times and maintains its boundaries, Allah will raise him to the rank of the righteous. And whoever takes it lightly, wastes it and abandons it, has taken Allah's religion lightly, and has no share in Islam. |
|||
|
|||
Indeed, Allah the Almighty has prescribed five prayers in a day and night, and has appointed a specific time for each prayer. Whoever prays them at their time and completes their bowing, prostration and humility, they will be light, proof and salvation for him on the Day of Judgment.'''} |
|||
], |
|||
'explanation': '''Этот обширный хадис представляет собой фундаментальное учение о молитве в Исламе. Он раскрывает несколько ключевых аспектов: |
|||
|
|||
Во-первых, молитва описывается как "столп религии" (عمود الدين), что указывает на ее центральную роль в исламской вере. Это метафора подчеркивает, что как здание не может стоять без столпов, так и религиозная жизнь мусульманина не может быть полноценной без молитвы. |
|||
|
|||
Во-вторых, хадис устанавливает принцип, согласно которому принятие или отвержение молитвы Аллахом определяет судьбу всех остальных деяний верующего. Это подчеркивает качественный аспект молитвы - важна не только ее форма, но и искренность, концентрация и правильное выполнение. |
|||
|
|||
В-третьих, молитва представлена как "معراج المؤمن" (вознесение верующего), что отсылает к ночному путешествию Пророка (мир ему) и подчеркивает духовное измерение молитвы как средства приближения к Всевышнему. |
|||
|
|||
Хадис также подчеркивает важность своевременного совершения молитв и соблюдения их внешних и внутренних условий, обещая великую награду тем, кто относится к молитве с должным вниманием и уважением.''' |
|||
}, |
|||
], |
|||
'fasting': [ |
|||
{ |
|||
'title': 'Достоинство поста и его духовные плоды', |
|||
'text': '''قال النبي صلى الله عليه وآله: الصوم جنة من النار، وهو زكاة البدن، وصوم شهر الصبر وثلاثة أيام من كل شهر يذهبن وحر الصدر ووساوس الشيطان. ومن صام يوماً في سبيل الله باعد الله وجهه عن النار سبعين خريفاً. |
|||
|
|||
إن الصائم في عبادة وإن كان نائماً على فراشه، وإن دعاءه مستجاب حتى يفطر، وإن الملائكة تستغفر له حتى يفطر. وللصائم فرحتان: فرحة عند فطره، وفرحة عند لقاء ربه. |
|||
|
|||
يا معشر الشباب، من استطاع منكم الباءة فليتزوج، ومن لم يستطع فعليه بالصوم فإنه له وجاء. والصوم يكسر الشهوة ويطهر النفس ويقرب إلى الله تعالى.''', |
|||
'translation': [ |
|||
{'language_code': 'ru', 'title': '''Сказал Пророк (да благословит Аллах его и его семейство): Пост - щит от огня, и он закят тела, и пост месяца терпения и трех дней каждого месяца устраняют жар груди и наущения шайтана. И кто постился день на пути Аллаха, Аллах отдалит его лицо от огня на семьдесят осеней. |
|||
|
|||
Поистине, постящийся находится в поклонении, даже если он спит на своей постели, и его мольба принимается до тех пор, пока он не разговеется, и ангелы просят прощения для него до тех пор, пока он не разговеется. И у постящегося две радости: радость при разговении и радость при встрече со своим Господом. |
|||
|
|||
О молодежь! Кто из вас способен жениться, пусть женится, а кто не способен, пусть постится, ибо это для него защита. Пост ломает страсть, очищает душу и приближает к Всевышнему Аллаху.'''} |
|||
], |
|||
'explanation': '''Этот многогранный хадис раскрывает глубокие духовные и практические аспекты поста в Исламе.''' |
|||
}, |
|||
], |
|||
'ethics': [ |
|||
{ |
|||
'title': 'Благородный нрав', |
|||
'text': 'قال رسول الله صلى الله عليه وآله: إنما بعثت لأتمم مكارم الأخلاق.', |
|||
'translation': [ |
|||
{'language_code': 'ru', 'title': 'Сказал Посланник Аллаха (да благословит Аллах его и его семейство): Поистине, я послан, чтобы довести до совершенства благородные нравы.'} |
|||
], |
|||
'explanation': 'Этот хадис подчеркивает важность благородного нрава в Исламе.' |
|||
}, |
|||
] |
|||
} |
|||
|
|||
# Create hadis records for each leaf category |
|||
hadis_created_count = 0 |
|||
for category in leaf_categories: |
|||
# Determine hadis type based on category title |
|||
hadis_type = 'prayer' |
|||
if any(word in category.title.lower() for word in ['пост', 'рамадан']): |
|||
hadis_type = 'fasting' |
|||
elif any(word in category.title.lower() for word in ['нрав', 'терпение', 'справедливость']): |
|||
hadis_type = 'ethics' |
|||
|
|||
# Get sample hadis for this type |
|||
samples = hadis_samples.get(hadis_type, hadis_samples['prayer']) |
|||
|
|||
# Create 10 hadis per category |
|||
for i in range(10): |
|||
sample = random.choice(samples) |
|||
|
|||
# Create unique title |
|||
hadis_title = f"{sample['title']} - {category.title} ({i+1})" |
|||
|
|||
# Check if hadis already exists |
|||
if Hadis.objects.filter(title=hadis_title, category=category).exists(): |
|||
continue |
|||
|
|||
# Create hadis record |
|||
hadis = Hadis.objects.create( |
|||
category=category, |
|||
title=hadis_title, |
|||
text=sample['text'], |
|||
translation=sample['translation'], |
|||
explanation=sample['explanation'], |
|||
status=True, # Boolean field for visibility |
|||
hadis_status=random.choice(statuses), # ForeignKey to HadisStatus |
|||
links=[ |
|||
{'title': 'Source 1', 'link': 'https://example.com/source1'}, |
|||
{'title': 'Source 2', 'link': 'https://example.com/source2'}, |
|||
] |
|||
) |
|||
|
|||
# Add tags |
|||
selected_tags = random.sample(tags, min(3, len(tags))) |
|||
hadis.tags.set(selected_tags) |
|||
|
|||
# Create transmission chain (5 transmitters with one gap) |
|||
selected_transmitters = random.sample(transmitters, min(5, len(transmitters))) |
|||
gap_position = random.randint(0, len(selected_transmitters) - 1) |
|||
|
|||
for j, transmitter in enumerate(selected_transmitters): |
|||
HadisTransmitter.objects.create( |
|||
hadis=hadis, |
|||
transmitter=transmitter, |
|||
order=j + 1, |
|||
is_gap=(j == gap_position) |
|||
) |
|||
|
|||
# Create reference |
|||
reference_book = random.choice(books) |
|||
reference = HadisReference.objects.create( |
|||
hadis=hadis, |
|||
book=reference_book, |
|||
description=f"Volume {random.randint(1, 5)}, Page {random.randint(1, 1000)}, Hadis #{random.randint(1, 9999)}" |
|||
) |
|||
|
|||
# Add reference image |
|||
if self.image_files: |
|||
image_file = random.choice(self.image_files) |
|||
try: |
|||
with open(image_file, 'rb') as f: |
|||
ReferenceImage.objects.create( |
|||
reference=reference, |
|||
thumbnail=File(f, name=f"ref_{reference.id}.png") |
|||
) |
|||
except Exception as e: |
|||
self.stdout.write( |
|||
self.style.WARNING(f"Could not add reference image: {e}") |
|||
) |
|||
|
|||
hadis_created_count += 1 |
|||
|
|||
if hadis_created_count % 50 == 0: |
|||
self.stdout.write(f" Created {hadis_created_count} hadis records...") |
|||
|
|||
self.stdout.write(f"Successfully created {hadis_created_count} hadis records") |
|||
@ -0,0 +1,45 @@ |
|||
from django.core.management.base import BaseCommand |
|||
from apps.hadis.models import HadisSect |
|||
|
|||
|
|||
class Command(BaseCommand): |
|||
help = 'Test sects creation' |
|||
|
|||
def handle(self, **options): |
|||
_ = options # Suppress unused variable warning |
|||
self.stdout.write("Testing sects creation...") |
|||
|
|||
try: |
|||
# Check existing sects |
|||
existing_sects = HadisSect.objects.all() |
|||
self.stdout.write(f"Found {existing_sects.count()} existing sects:") |
|||
for sect in existing_sects: |
|||
self.stdout.write(f" - {sect.sect_type}: {sect.title}") |
|||
|
|||
# Try to create sunni sect using direct create |
|||
self.stdout.write("Attempting to create sunni sect...") |
|||
|
|||
# Check if sunni exists |
|||
try: |
|||
sunni_sect = HadisSect.objects.get(sect_type='sunni') |
|||
self.stdout.write(f"Sunni sect already exists: {sunni_sect.title}") |
|||
except HadisSect.DoesNotExist: |
|||
# Create sunni sect |
|||
self.stdout.write("Creating new sunni sect...") |
|||
sunni_sect = HadisSect( |
|||
sect_type='sunni', |
|||
title='Сунниты', |
|||
is_active=True, |
|||
order=2 |
|||
) |
|||
sunni_sect.save() |
|||
self.stdout.write(self.style.SUCCESS(f"Created sunni sect: {sunni_sect.title}")) |
|||
|
|||
# Final count |
|||
final_count = HadisSect.objects.count() |
|||
self.stdout.write(f"Total sects after operation: {final_count}") |
|||
|
|||
except Exception as e: |
|||
self.stdout.write(self.style.ERROR(f"Error: {str(e)}")) |
|||
import traceback |
|||
self.stdout.write(self.style.ERROR(traceback.format_exc())) |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue