import os import random from django.core.management.base import BaseCommand from django.core.files.base import ContentFile from django.conf import settings from django.utils.text import slugify # REPLACE WITH YOUR ACTUAL APP PATHS from apps.article.models import ( Article, ArticleCategory, ArticleCollection, ArticleInCollection, ArticleContent, ContentPart, TextSection ) class Command(BaseCommand): help = 'Seeds 25 rich Islamic articles (No Atomic Transaction).' def handle(self, *args, **kwargs): self.stdout.write('--- Starting Rich Article Seeding ---') # ========================================== # 1. CONFIGURATION # ========================================== TOTAL_ARTICLES_TO_CREATE = 25 CATEGORY_IDS = [6, 7, 8, 9] PROTECTED_SLUG = "امام-حسین-ع-از-ولادت-تا-جاودانگی-تحلیلی-بر-مبانی-ق" IMAGE_DIR = os.path.join(settings.BASE_DIR, 'seeds', 'images') # Explicit file names based on your folder structure IMAGE_NAMES = ['articl2.jpg', 'articl3.jpg', 'articl4.jpg'] RICH_DATA = [ { 'title_en': 'The Event of Ghadir Khumm: Completion of Religion', 'title_fa': 'واقعه غدیر خم: کمال دین و اتمام نعمت', 'summary': 'An analysis of the sermon of the Prophet (PBUH) at Ghadir Khumm.', 'arabic': 'مَنْ كُنْتُ مَوْلَاهُ فَهَذَا عَلِيٌّ مَوْلَاهُ', 'trans': 'For whomever I am his Master (Mawla), then Ali is his Master.', 'content_body': 'The event of Ghadir is one of the most undeniable historical events in Islam...' }, { 'title_en': 'Lady Fatimah (SA): The Role Model for Women', 'title_fa': 'حضرت فاطمه زهرا (س): الگوی زنان عالم', 'summary': 'Exploring the virtues of the daughter of the Prophet.', 'arabic': 'فَاطِمَةُ بَضْعَةٌ مِنِّي', 'trans': 'Fatimah is a part of me.', 'content_body': 'Lady Fatimah az-Zahra (SA) is not just a role model for women...' }, { 'title_en': 'Nahj al-Balagha: The Peak of Eloquence', 'title_fa': 'نهج البلاغه: قله فصاحت و بلاغت', 'summary': 'A look into the sermons of Imam Ali (AS).', 'arabic': 'سَلُونِي قَبْلَ أَنْ تَفْقِدُونِي', 'trans': 'Ask me before you lose me.', 'content_body': 'Nahj al-Balagha contains deep philosophical guidance...' }, { 'title_en': 'The Significance of Laylat al-Qadr', 'title_fa': 'عظمت شب قدر', 'summary': 'Why is the Night of Power better than a thousand months?', 'arabic': 'إِنَّا أَنزَلْنَاهُ فِي لَيْلَةِ الْقَدْرِ', 'trans': 'Indeed, We sent the Qur\'an down during the Night of Decree.', 'content_body': 'The Night of Qadr is the night where destiny is written...' }, { 'title_en': 'Imam Mahdi (AJ): The Savior', 'title_fa': 'امام مهدی (عج): منجی بشریت', 'summary': 'The concept of the Awaited One in Islamic eschatology.', 'arabic': 'بَقِيَّتُ اللَّهِ خَيْرٌ لَكُمْ', 'trans': 'The remnant of Allah is better for you.', 'content_body': 'The belief in a savior is universal...' }, { 'title_en': 'Rights of Parents', 'title_fa': 'حقوق والدین', 'summary': 'Examining the status of parents.', 'arabic': 'وَبِالْوَالِدَيْنِ إِحْسَانًا', 'trans': 'And be good to parents.', 'content_body': 'Respecting parents is placed immediately after worship of God...' } ] # ========================================== # 2. CLEANUP # ========================================== self.stdout.write("Cleaning old articles (preserving protected one)...") deleted_count, _ = Article.objects.exclude(slug=PROTECTED_SLUG).delete() ArticleCollection.objects.all().delete() self.stdout.write(self.style.WARNING(f"Deleted {deleted_count} articles.")) # ========================================== # 3. PREPARE DEPENDENCIES # ========================================== categories = list(ArticleCategory.objects.filter(id__in=CATEGORY_IDS)) collection_names = [ ("Islamic History", "تاریخ اسلام"), ("Theology & Beliefs", "عقاید و کلام"), ("Ethics & Spirituality", "اخلاق و عرفان"), ("Quran & Hadith", "قرآن و حدیث") ] collections = [] for en_name, fa_name in collection_names: col = ArticleCollection.objects.create( title=en_name, slug=slugify(en_name), summary=f'Collection of {en_name}', display_position=ArticleCollection.DisplayPosition.MIDDLE ) collections.append(col) # ========================================== # 4. MAIN CREATION LOOP (NO ATOMIC TRANSACTION) # ========================================== self.stdout.write("Starting creation loop...") for i in range(1, TOTAL_ARTICLES_TO_CREATE + 1): # Select Data data = RICH_DATA[(i - 1) % len(RICH_DATA)] # Construct Unique Data final_title = f"{data['title_en']} (Vol {i})" short_slug_base = slugify(data['title_en'])[:30] unique_slug = f"{short_slug_base}-{i}" if unique_slug == PROTECTED_SLUG: unique_slug = f"{unique_slug}-generated" # 1. Create Article Object article = Article.objects.create( title=final_title, slug=unique_slug, description=data['summary'], content=data['content_body'], status=True ) # 2. Handle Image img_name = IMAGE_NAMES[(i - 1) % len(IMAGE_NAMES)] img_path = os.path.join(IMAGE_DIR, img_name) if os.path.exists(img_path): try: with open(img_path, 'rb') as f: file_content = f.read() # NOTE: If the script hangs here, check Article.save() signals article.thumbnail.save(img_name, ContentFile(file_content), save=True) except Exception as e: self.stdout.write(self.style.ERROR(f"Error saving image for item {i}: {e}")) else: self.stdout.write(self.style.WARNING(f"Image missing: {img_path}")) # 3. Assign Categories if categories: article.categories.add(*random.sample(categories, k=random.randint(1, 2))) # 4. Assign Collection random_col = random.choice(collections) ArticleInCollection.objects.create( article=article, collection=random_col, order=i ) # 5. Create Content Hierarchy ac = ArticleContent.objects.create( article=article, title=data['title_fa'], content=data['content_body'], priority=1 ) part = ContentPart.objects.create(article_content=ac, order=1) TextSection.objects.create( content_part=part, arabic_text=data['arabic'], translation=data['trans'], order=1 ) TextSection.objects.create( content_part=part, arabic_text=f"شرح: {data['title_fa']}", translation=f"Commentary on {data['title_en']}", order=2 ) self.stdout.write(f"[{i}/{TOTAL_ARTICLES_TO_CREATE}] Created: {unique_slug}") self.stdout.write(self.style.SUCCESS(f'Successfully seeded {TOTAL_ARTICLES_TO_CREATE} rich articles.'))