diff --git a/apps/hadis/management/commands/seed_hadis_2.py b/apps/hadis/management/commands/seed_hadis_2.py index 8341218..0f1f8b9 100644 --- a/apps/hadis/management/commands/seed_hadis_2.py +++ b/apps/hadis/management/commands/seed_hadis_2.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") \ No newline at end of file + self.stdout.write(self.style.SUCCESS("--- Hadis Extras Seeding Complete ---")) \ No newline at end of file diff --git a/apps/hadis/serializers/hadis.py b/apps/hadis/serializers/hadis.py index 5ac6c21..9eb534a 100644 --- a/apps/hadis/serializers/hadis.py +++ b/apps/hadis/serializers/hadis.py @@ -500,8 +500,7 @@ class HadisBasicSerializer(serializers.ModelSerializer): title = LocalizedField() title_narrator = LocalizedField() - text = LocalizedField() - explanation = LocalizedField() + explanation = LocalizedField() class Meta: model = Hadis diff --git a/apps/hadis/serializers/reference.py b/apps/hadis/serializers/reference.py index 4d9c432..a5ee461 100644 --- a/apps/hadis/serializers/reference.py +++ b/apps/hadis/serializers/reference.py @@ -1,4 +1,3 @@ -from turtle import title from rest_framework import serializers from django.utils.translation import get_language from .category import get_localized_text