3 changed files with 100 additions and 406 deletions
-
502apps/hadis/management/commands/seed_hadis_2.py
-
3apps/hadis/serializers/hadis.py
-
1apps/hadis/serializers/reference.py
@ -1,432 +1,128 @@ |
|||
""" |
|||
Django management command to seed mock data for hadith collections, references, and corrections. |
|||
Place this file in: yourapp/management/commands/seed_hadis.py |
|||
|
|||
Usage: python manage.py seed_hadis |
|||
python manage.py seed_hadis --clear |
|||
""" |
|||
|
|||
import os |
|||
from pathlib import Path |
|||
import random |
|||
from django.core.management.base import BaseCommand |
|||
from django.core.files.base import ContentFile |
|||
from django.utils.text import slugify |
|||
from django.conf import settings |
|||
from apps.hadis.models.hadis import ( |
|||
from django.core.exceptions import ObjectDoesNotExist |
|||
# Ensure these imports match your actual app structure |
|||
from apps.hadis.models import ( |
|||
Hadis, |
|||
HadisCollection, |
|||
HadisInCollection, |
|||
HadisReference, |
|||
ReferenceImage, |
|||
HadisCorrection, |
|||
Hadis |
|||
HadisCorrection |
|||
) |
|||
from apps.hadis.models.reference import BookReference |
|||
|
|||
|
|||
class Command(BaseCommand): |
|||
help = 'Seed the database with mock hadith collection and reference data' |
|||
|
|||
def add_arguments(self, parser): |
|||
parser.add_argument( |
|||
'--clear', |
|||
action='store_true', |
|||
help='Clear existing data before seeding', |
|||
) |
|||
help = 'Seeds Hadis Collections and Corrections for Hadis IDs 1877-1888' |
|||
|
|||
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"} |
|||
] |
|||
|
|||
def handle(self, *args, **options): |
|||
if options['clear']: |
|||
self.stdout.write(self.style.WARNING('Clearing existing hadith data...')) |
|||
ReferenceImage.objects.all().delete() |
|||
HadisCorrection.objects.all().delete() |
|||
HadisReference.objects.all().delete() |
|||
HadisInCollection.objects.all().delete() |
|||
HadisCollection.objects.all().delete() |
|||
self.stdout.write(self.style.SUCCESS('Data cleared successfully!')) |
|||
self.stdout.write("--- Starting Hadis Extras Seeding ---") |
|||
|
|||
# --------------------------------------------------------- |
|||
# 1. Create Hadis Collections |
|||
# --------------------------------------------------------- |
|||
self.stdout.write("Creating Hadis Collections...") |
|||
|
|||
# Step 1: Create Hadis Collections |
|||
self.stdout.write(self.style.SUCCESS('\n📚 Creating Hadis Collections...')) |
|||
collections_data = [ |
|||
{ |
|||
"title": "Purification & Prayer", |
|||
"summary": "Collection of ahadith related to purification (Wudu, Ghusl) and prayer rituals.", |
|||
"status": True, |
|||
"order": 1, |
|||
}, |
|||
{ |
|||
"title": "Zakat & Charity", |
|||
"summary": "Ahadith discussing the obligation of zakat and charitable giving in Islam.", |
|||
"status": True, |
|||
"order": 2, |
|||
}, |
|||
{ |
|||
"title": "Fasting & Ramadan", |
|||
"summary": "Collection of authentic ahadith about fasting, its virtues, and Ramadan practices.", |
|||
"status": True, |
|||
"order": 3, |
|||
}, |
|||
{ |
|||
"title": "Hajj & Umrah", |
|||
"summary": "Ahadith related to the pilgrimage to Mecca and the spiritual practices involved.", |
|||
"status": True, |
|||
"order": 4, |
|||
}, |
|||
{ |
|||
"title": "Ethics & Morality", |
|||
"summary": "Ahadith emphasizing Islamic ethics, good character, and moral conduct.", |
|||
"status": True, |
|||
"order": 5, |
|||
}, |
|||
{ |
|||
"title": "Knowledge & Learning", |
|||
"summary": "Collection emphasizing the importance of seeking knowledge in Islam.", |
|||
"status": True, |
|||
"order": 6, |
|||
}, |
|||
{ |
|||
"title": "Family & Relations", |
|||
"summary": "Ahadith about family relationships, rights of parents, spouses, and children.", |
|||
"status": True, |
|||
"order": 7, |
|||
"title": ("The Book of Intellect and Ignorance", "کتاب عقل و جهل", "Книга разума и невежества"), |
|||
"summary": ( |
|||
"A collection of narrations regarding the importance of reason.", |
|||
"مجموعهای از روایات درباره اهمیت عقل و خرد.", |
|||
"Сборник преданий о важности разума." |
|||
) |
|||
}, |
|||
{ |
|||
"title": "Business & Trade", |
|||
"summary": "Ahadith related to ethical business practices and commerce in Islam.", |
|||
"status": True, |
|||
"order": 8, |
|||
}, |
|||
] |
|||
|
|||
collections = {} |
|||
for collection_data in collections_data: |
|||
collection, created = HadisCollection.objects.get_or_create( |
|||
title=collection_data['title'], |
|||
defaults=collection_data |
|||
) |
|||
collections[collection_data['title']] = collection |
|||
status = '✓ Created' if created else '• Updated' |
|||
self.stdout.write(f"{status}: {collection.title}") |
|||
|
|||
# Step 2: Get book references (we'll use all available books) |
|||
self.stdout.write(self.style.SUCCESS('\n📖 Getting Book References...')) |
|||
book_references = BookReference.objects.all() |
|||
if not book_references.exists(): |
|||
self.stdout.write(self.style.WARNING('⚠️ No book references found. Run seed_books first!')) |
|||
return |
|||
|
|||
book_references_list = list(book_references) |
|||
self.stdout.write(f"✓ Found {len(book_references_list)} book references") |
|||
|
|||
# Step 3: Create Hadis References |
|||
self.stdout.write(self.style.SUCCESS('\n🔗 Creating Hadis References...')) |
|||
|
|||
hadis_ids = list(range(1800, 1853)) |
|||
reference_descriptions = [ |
|||
"This hadith is recorded in the collection with full chain of narration.", |
|||
"The narration is found in multiple reliable sources with slight variations.", |
|||
"This is a widely transmitted hadith with consistent narration across sources.", |
|||
"The hadith is reported with authentic chain and acceptable wording.", |
|||
"This tradition appears in the primary sources with confirmed authenticity.", |
|||
"The narration demonstrates the scholarly consensus on this issue.", |
|||
"The hadith is part of the foundational traditions in this category.", |
|||
"This is one of the most frequently cited ahadith on this topic.", |
|||
] |
|||
|
|||
hadis_references = {} |
|||
reference_counter = 0 |
|||
|
|||
for idx, hadis_id in enumerate(hadis_ids): |
|||
# Get or create Hadis object |
|||
try: |
|||
hadis = Hadis.objects.get(pk=hadis_id) |
|||
except Hadis.DoesNotExist: |
|||
self.stdout.write( |
|||
self.style.WARNING(f"⚠️ Hadis with ID {hadis_id} not found, skipping...") |
|||
"title": ("The Book of Monotheism", "کتاب التوحید", "Книга Единобожия"), |
|||
"summary": ( |
|||
"Hadiths explaining the oneness of God.", |
|||
"احادیثی که یگانگی خداوند را توضیح میدهند.", |
|||
"Хадисы, объясняющие единство Бога." |
|||
) |
|||
continue |
|||
} |
|||
] |
|||
|
|||
# Randomly assign 1-3 book references per hadith |
|||
num_refs = (idx % 3) + 1 |
|||
selected_books = book_references_list[idx % len(book_references_list):(idx % len(book_references_list)) + num_refs] |
|||
created_collections = [] |
|||
for c_data in collections_data: |
|||
# We use the English title as a loose identifier to prevent duplicates |
|||
slug_base = c_data["title"][0].lower().replace(" ", "-") |
|||
|
|||
for book_idx, book_ref in enumerate(selected_books): |
|||
hadis_ref, created = HadisReference.objects.get_or_create( |
|||
hadis=hadis, |
|||
book_reference=book_ref, |
|||
defaults={ |
|||
'description': reference_descriptions[reference_counter % len(reference_descriptions)] |
|||
} |
|||
# Simple check if exists to avoid duplication in multiple runs |
|||
if HadisCollection.objects.filter(slug__startswith=slug_base).exists(): |
|||
collection = HadisCollection.objects.filter(slug__startswith=slug_base).first() |
|||
self.stdout.write(f"Collection '{c_data['title'][0]}' already exists.") |
|||
else: |
|||
collection = HadisCollection.objects.create( |
|||
title=self.create_json_field(*c_data["title"]), |
|||
summary=self.create_json_field(*c_data["summary"]), |
|||
status=True |
|||
) |
|||
if created: |
|||
hadis_references[hadis_id] = hadis_ref |
|||
reference_counter += 1 |
|||
self.stdout.write( |
|||
self.style.SUCCESS( |
|||
f"✓ Reference: Hadis {hadis_id} <- {book_ref.title}" |
|||
) |
|||
) |
|||
|
|||
# Step 4: Add Reference Images |
|||
self.stdout.write(self.style.SUCCESS('\n🖼️ Adding Reference Images...')) |
|||
ref_images_added = self._add_reference_images(hadis_references) |
|||
self.stdout.write(f"✓ Added {ref_images_added} reference images") |
|||
self.stdout.write(self.style.SUCCESS(f"Created Collection: {c_data['title'][0]}")) |
|||
|
|||
created_collections.append(collection) |
|||
|
|||
# Step 5: Create Hadis In Collection |
|||
self.stdout.write(self.style.SUCCESS('\n📋 Adding Hadis to Collections...')) |
|||
# --------------------------------------------------------- |
|||
# 2. Process Hadis (1877 - 1888) |
|||
# --------------------------------------------------------- |
|||
self.stdout.write("Processing Hadis IDs 1877-1888...") |
|||
|
|||
collection_assignments = [ |
|||
{ |
|||
"collection_title": "Purification & Prayer", |
|||
"hadis_ids": [1800, 1801, 1802, 1803, 1804], |
|||
}, |
|||
{ |
|||
"collection_title": "Zakat & Charity", |
|||
"hadis_ids": [1805, 1806, 1807, 1808], |
|||
}, |
|||
{ |
|||
"collection_title": "Fasting & Ramadan", |
|||
"hadis_ids": [1809, 1810, 1811, 1812, 1813], |
|||
}, |
|||
{ |
|||
"collection_title": "Hajj & Umrah", |
|||
"hadis_ids": [1814, 1815, 1816, 1817], |
|||
}, |
|||
{ |
|||
"collection_title": "Ethics & Morality", |
|||
"hadis_ids": [1818, 1819, 1820, 1821, 1822, 1823], |
|||
}, |
|||
{ |
|||
"collection_title": "Knowledge & Learning", |
|||
"hadis_ids": [1824, 1825, 1826, 1827], |
|||
}, |
|||
{ |
|||
"collection_title": "Family & Relations", |
|||
"hadis_ids": [1828, 1829, 1830, 1831, 1832, 1833], |
|||
}, |
|||
{ |
|||
"collection_title": "Business & Trade", |
|||
"hadis_ids": [1834, 1835, 1836, 1837, 1838], |
|||
}, |
|||
] |
|||
target_ids = range(1877, 1889) |
|||
|
|||
hadis_in_collection_count = 0 |
|||
for assignment in collection_assignments: |
|||
collection = collections.get(assignment['collection_title']) |
|||
if not collection: |
|||
for hadis_id in target_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 |
|||
|
|||
for order, hadis_id in enumerate(assignment['hadis_ids']): |
|||
try: |
|||
hadis = Hadis.objects.get(pk=hadis_id) |
|||
hic, created = HadisInCollection.objects.get_or_create( |
|||
hadis=hadis, |
|||
collection=collection, |
|||
defaults={'order': order} |
|||
) |
|||
if created: |
|||
hadis_in_collection_count += 1 |
|||
self.stdout.write( |
|||
self.style.SUCCESS( |
|||
f"✓ Added Hadis {hadis_id} to {collection.title} (Order {order})" |
|||
) |
|||
) |
|||
except Hadis.DoesNotExist: |
|||
pass |
|||
|
|||
# Step 6: Create Hadis Corrections |
|||
self.stdout.write(self.style.SUCCESS('\n✏️ Creating Hadis Corrections...')) |
|||
|
|||
corrections_data = [ |
|||
{ |
|||
"hadis_id": 1800, |
|||
"title": "Clarification on Wudu Sequence", |
|||
"description": "Some scholars differ on the exact sequence of washing body parts during ablution.", |
|||
"translation": [ |
|||
{"lang": "en", "text": "The order of washing in wudu should follow the established practice."}, |
|||
{"lang": "ar", "text": "ترتيب غسل الأعضاء في الوضوء يجب أن يتبع السنة المثبتة."} |
|||
], |
|||
}, |
|||
{ |
|||
"hadis_id": 1802, |
|||
"title": "Prayer Time Variations", |
|||
"description": "Different schools of thought have varying opinions on prayer times.", |
|||
"translation": [ |
|||
{"lang": "en", "text": "Prayer times may vary slightly depending on geographical location."}, |
|||
{"lang": "ar", "text": "أوقات الصلاة قد تختلف قليلاً حسب الموقع الجغرافي."} |
|||
], |
|||
}, |
|||
{ |
|||
"hadis_id": 1805, |
|||
"title": "Zakat Calculation Methods", |
|||
"description": "Various methods exist for calculating zakat on different types of wealth.", |
|||
"translation": [ |
|||
{"lang": "en", "text": "The calculation of zakat follows specific rules for different assets."}, |
|||
{"lang": "ar", "text": "حساب الزكاة يتبع قواعد محددة لأنواع مختلفة من الأموال."} |
|||
], |
|||
}, |
|||
{ |
|||
"hadis_id": 1810, |
|||
"title": "Fasting in Different Climates", |
|||
"description": "Scholars discuss fasting practices in regions with extreme daylight variations.", |
|||
"translation": [ |
|||
{"lang": "en", "text": "Fasting guidelines adapt to extreme daylight conditions in certain regions."}, |
|||
{"lang": "ar", "text": "تتكيف إرشادات الصيام مع ظروف الإضاءة الشديدة في بعض المناطق."} |
|||
], |
|||
}, |
|||
{ |
|||
"hadis_id": 1815, |
|||
"title": "Hajj Routes and Methods", |
|||
"description": "Multiple routes and methods for performing Hajj rituals are recognized.", |
|||
"translation": [ |
|||
{"lang": "en", "text": "Different schools recognize various methods for performing Hajj rituals."}, |
|||
{"lang": "ar", "text": "تعترف المذاهب المختلفة بطرق متعددة لأداء مناسك الحج."} |
|||
], |
|||
}, |
|||
{ |
|||
"hadis_id": 1820, |
|||
"title": "Ethical Conduct in Commerce", |
|||
"description": "Islamic principles of honesty and fairness in business transactions.", |
|||
"translation": [ |
|||
{"lang": "en", "text": "Islamic business ethics emphasize honesty and mutual fairness."}, |
|||
{"lang": "ar", "text": "تؤكد أخلاقيات الأعمال الإسلامية على الصدق والإنصاف المتبادل."} |
|||
], |
|||
}, |
|||
{ |
|||
"hadis_id": 1825, |
|||
"title": "Hadith Authentication Methods", |
|||
"description": "Scholars use various methodologies for authenticating hadith narrations.", |
|||
"translation": [ |
|||
{"lang": "en", "text": "Hadith scholars employ rigorous methodology in authentication."}, |
|||
{"lang": "ar", "text": "يستخدم علماء الحديث منهجية صارمة في التحقق من الصحة."} |
|||
], |
|||
}, |
|||
{ |
|||
"hadis_id": 1830, |
|||
"title": "Family Rights and Obligations", |
|||
"description": "The Islamic framework defines rights and responsibilities within families.", |
|||
"translation": [ |
|||
{"lang": "en", "text": "Islam defines clear rights and obligations for family members."}, |
|||
{"lang": "ar", "text": "يحدد الإسلام حقوقاً والتزامات واضحة لأفراد الأسرة."} |
|||
], |
|||
}, |
|||
] |
|||
|
|||
corrections_count = 0 |
|||
for correction_data in corrections_data: |
|||
hadis_id = correction_data.pop('hadis_id') |
|||
try: |
|||
hadis = Hadis.objects.get(pk=hadis_id) |
|||
correction, created = HadisCorrection.objects.get_or_create( |
|||
hadis=hadis, |
|||
title=correction_data['title'], |
|||
defaults=correction_data |
|||
) |
|||
if created: |
|||
corrections_count += 1 |
|||
self.stdout.write( |
|||
self.style.SUCCESS( |
|||
f"✓ Correction created: {correction_data['title']} for Hadis {hadis_id}" |
|||
) |
|||
) |
|||
except Hadis.DoesNotExist: |
|||
pass |
|||
# --- A. Add to Collection --- |
|||
# Clear previous collection links for this hadis to avoid clutter |
|||
HadisInCollection.objects.filter(hadis=hadis_obj).delete() |
|||
|
|||
self.stdout.write( |
|||
self.style.SUCCESS( |
|||
f'\n✓ Successfully seeded hadith data!' |
|||
# Assign to a random collection from our list |
|||
target_collection = random.choice(created_collections) |
|||
|
|||
HadisInCollection.objects.create( |
|||
hadis=hadis_obj, |
|||
collection=target_collection, |
|||
order=hadis_id # Just using ID as order for simplicity |
|||
) |
|||
) |
|||
self._print_summary( |
|||
collections, |
|||
hadis_in_collection_count, |
|||
len(hadis_references), |
|||
ref_images_added, |
|||
corrections_count |
|||
) |
|||
self.stdout.write(f" -> Linked Hadis {hadis_id} to '{target_collection}'") |
|||
|
|||
def _add_reference_images(self, hadis_references): |
|||
"""Add reference images from seeds/images folder""" |
|||
images_added = 0 |
|||
ref_images = ['ref1.png', 'ref2.png', 'ref3.png', 'ref4.png'] |
|||
image_counter = 0 |
|||
|
|||
for hadis_id, hadis_ref in hadis_references.items(): |
|||
# Add 1-2 images per reference |
|||
num_images = (image_counter % 2) + 1 |
|||
# --- B. Create Correction --- |
|||
# Mocking a correction entry |
|||
# We'll assume these are translation corrections or scholarly notes |
|||
|
|||
for img_idx in range(num_images): |
|||
image_name = ref_images[image_counter % len(ref_images)] |
|||
image_path = self._get_image_path(image_name) |
|||
|
|||
if image_path and os.path.exists(image_path): |
|||
# Check if image already exists |
|||
existing_images_count = hadis_ref.images.count() |
|||
|
|||
with open(image_path, 'rb') as img_file: |
|||
ref_image, created = ReferenceImage.objects.get_or_create( |
|||
reference=hadis_ref, |
|||
priority=existing_images_count + img_idx, |
|||
defaults={ |
|||
'thumbnail': None |
|||
} |
|||
) |
|||
if created: |
|||
# Save the image file |
|||
ref_image.thumbnail.save( |
|||
image_name, |
|||
ContentFile(img_file.read()), |
|||
save=True |
|||
) |
|||
images_added += 1 |
|||
self.stdout.write( |
|||
self.style.SUCCESS( |
|||
f"✓ Image added: {image_name} to Hadis {hadis_id} reference" |
|||
) |
|||
) |
|||
|
|||
image_counter += 1 |
|||
|
|||
return images_added |
|||
|
|||
def _get_image_path(self, image_name): |
|||
"""Find the image file for the given image name""" |
|||
possible_paths = [ |
|||
Path('seeds/images') / image_name, |
|||
Path('seed_data/images') / image_name, |
|||
Path('static/images') / image_name, |
|||
Path('.') / 'seeds' / 'images' / image_name, |
|||
] |
|||
|
|||
for path in possible_paths: |
|||
if path.exists(): |
|||
return path |
|||
|
|||
return None |
|||
correction_title = ( |
|||
f"Correction for Hadis {hadis_id}", |
|||
f"اصلاحیه برای حدیث {hadis_id}", |
|||
f"Исправление для хадиса {hadis_id}" |
|||
) |
|||
|
|||
correction_desc = ( |
|||
"The word 'Wali' here implies authority, not just friendship.", |
|||
"کلمه «ولی» در اینجا دلالت بر ولایت دارد، نه صرفاً دوستی.", |
|||
"Слово «Вали» здесь означает власть, а не просто дружбу." |
|||
) |
|||
|
|||
def _print_summary(self, collections, hadis_in_collection_count, references_count, images_count, corrections_count): |
|||
"""Print a summary of created data""" |
|||
self.stdout.write("\n" + "="*70) |
|||
self.stdout.write(self.style.SUCCESS("HADITH DATABASE SUMMARY")) |
|||
self.stdout.write("="*70) |
|||
correction_trans = ( |
|||
"Verily, I am the authority over the believers...", |
|||
"همانا من ولی و سرپرست مؤمنان هستم...", |
|||
"Воистину, я — покровитель верующих..." |
|||
) |
|||
|
|||
collections_count = HadisCollection.objects.count() |
|||
total_hadis_in_collection = HadisInCollection.objects.count() |
|||
total_references = HadisReference.objects.count() |
|||
total_ref_images = ReferenceImage.objects.count() |
|||
total_corrections = HadisCorrection.objects.count() |
|||
HadisCorrection.objects.create( |
|||
hadis=hadis_obj, |
|||
title=self.create_json_field(*correction_title), |
|||
description=self.create_json_field(*correction_desc), |
|||
translation=self.create_json_field(*correction_trans), |
|||
share_link=f"https://example.com/corrections/{hadis_id}" |
|||
) |
|||
self.stdout.write(f" -> Created Correction for Hadis {hadis_id}") |
|||
|
|||
self.stdout.write(f"📚 Hadis Collections: {collections_count}") |
|||
self.stdout.write(f"📋 Hadis in Collections: {total_hadis_in_collection}") |
|||
self.stdout.write(f"🔗 Hadis References: {total_references}") |
|||
self.stdout.write(f"🖼️ Reference Images: {total_ref_images}") |
|||
self.stdout.write(f"✏️ Hadis Corrections: {total_corrections}") |
|||
|
|||
self.stdout.write("\n" + "="*70) |
|||
self.stdout.write(self.style.WARNING("Collections Created:")) |
|||
self.stdout.write("="*70) |
|||
for collection_title in list(collections.keys()): |
|||
hadis_count = HadisInCollection.objects.filter( |
|||
collection__title=collection_title |
|||
).count() |
|||
self.stdout.write(f" • {collection_title} ({hadis_count} ahadith)") |
|||
|
|||
self.stdout.write("="*70 + "\n") |
|||
self.stdout.write(self.style.SUCCESS("--- Hadis Extras Seeding Complete ---")) |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue