You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
8.5 KiB
198 lines
8.5 KiB
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.'))
|