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.
265 lines
13 KiB
265 lines
13 KiB
import os
|
|
import random
|
|
import urllib.request
|
|
from django.core.management.base import BaseCommand
|
|
from django.db import transaction
|
|
from django.core.files.base import ContentFile
|
|
from apps.hadis.models import (
|
|
BookReference,
|
|
BookAuthor,
|
|
BookEdition,
|
|
BookVolume,
|
|
BookResearcher,
|
|
BookEditor,
|
|
)
|
|
|
|
class Command(BaseCommand):
|
|
help = 'Generates randomized Editions and Volumes (with sample cover image and PDF file) for all BookReferences.'
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
'--clear',
|
|
action='store_true',
|
|
default=True,
|
|
help='Clear existing BookEditions and BookVolumes before generating (default: True)',
|
|
)
|
|
parser.add_argument(
|
|
'--keep-existing',
|
|
action='store_true',
|
|
help='Do not clear existing data, only add/modify',
|
|
)
|
|
|
|
def _fetch_sample_assets(self):
|
|
"""
|
|
Downloads a lightweight Islamic cover image and sample PDF from the web.
|
|
Falls back to generated placeholder bytes if network request fails.
|
|
"""
|
|
self.stdout.write("Downloading sample Islamic book image and sample PDF...")
|
|
|
|
image_url = "https://images.unsplash.com/photo-1609599006353-e629aaabfeae?w=500&auto=format&fit=crop&q=80"
|
|
image_bytes = None
|
|
|
|
try:
|
|
req = urllib.request.Request(image_url, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'})
|
|
with urllib.request.urlopen(req, timeout=15) as resp:
|
|
image_bytes = resp.read()
|
|
self.stdout.write(self.style.SUCCESS(f"Downloaded sample cover image ({len(image_bytes)} bytes)."))
|
|
except Exception as e:
|
|
self.stdout.write(self.style.WARNING(f"Failed to download image ({e}), generating a local fallback image..."))
|
|
from PIL import Image, ImageDraw
|
|
import io
|
|
img = Image.new('RGB', (400, 600), color='#1e293b')
|
|
draw = ImageDraw.Draw(img)
|
|
draw.rectangle([20, 20, 380, 580], outline='#e2e8f0', width=3)
|
|
buf = io.BytesIO()
|
|
img.save(buf, format='JPEG')
|
|
image_bytes = buf.getvalue()
|
|
|
|
pdf_url = "https://raw.githubusercontent.com/mozilla/pdf.js/master/examples/learning/helloworld.pdf"
|
|
pdf_bytes = None
|
|
|
|
try:
|
|
req = urllib.request.Request(pdf_url, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'})
|
|
with urllib.request.urlopen(req, timeout=15) as resp:
|
|
pdf_bytes = resp.read()
|
|
self.stdout.write(self.style.SUCCESS(f"Downloaded sample PDF document ({len(pdf_bytes)} bytes)."))
|
|
except Exception as e:
|
|
self.stdout.write(self.style.WARNING(f"Failed to download PDF ({e}), generating a fallback PDF..."))
|
|
from reportlab.pdfgen import canvas
|
|
import io
|
|
buf = io.BytesIO()
|
|
p = canvas.Canvas(buf)
|
|
p.drawString(100, 750, "Sample Islamic Hadith Reference Document")
|
|
p.drawString(100, 720, "This is a lightweight sample volume file.")
|
|
p.showPage()
|
|
p.save()
|
|
pdf_bytes = buf.getvalue()
|
|
|
|
return image_bytes, pdf_bytes
|
|
|
|
def handle(self, *args, **options):
|
|
clear_existing = not options.get('keep_existing', False)
|
|
|
|
references = list(BookReference.objects.all())
|
|
authors = list(BookAuthor.objects.all())
|
|
|
|
if not references:
|
|
self.stdout.write(self.style.ERROR("No BookReference found in the database."))
|
|
return
|
|
|
|
self.stdout.write(f"Found {len(references)} BookReferences and {len(authors)} BookAuthors.")
|
|
|
|
if clear_existing:
|
|
self.stdout.write(self.style.WARNING("Clearing existing BookEditions and BookVolumes..."))
|
|
BookVolume.objects.all().delete()
|
|
BookEdition.objects.all().delete()
|
|
BookResearcher.objects.all().delete()
|
|
BookEditor.objects.all().delete()
|
|
|
|
# Download or prepare sample assets
|
|
image_bytes, pdf_bytes = self._fetch_sample_assets()
|
|
|
|
# Publishers pool
|
|
publishers_pool = [
|
|
[
|
|
{"language_code": "fa", "text": "دار الحديث"},
|
|
{"language_code": "ar", "text": "دار الحديث للطباعة والنشر"},
|
|
{"language_code": "en", "text": "Dar al-Hadith Publications"},
|
|
],
|
|
[
|
|
{"language_code": "fa", "text": "مؤسسة آل البيت (ع) لإحياء التراث"},
|
|
{"language_code": "ar", "text": "مؤسسة آل البيت عليهم السلام لإحياء التراث"},
|
|
{"language_code": "en", "text": "Aal al-Bayt Institute for Heritage Revival"},
|
|
],
|
|
[
|
|
{"language_code": "fa", "text": "دار الكتب الإسلامية"},
|
|
{"language_code": "ar", "text": "دار الكتب الإسلامية"},
|
|
{"language_code": "en", "text": "Dar al-Kutub al-Islamiyya"},
|
|
],
|
|
[
|
|
{"language_code": "fa", "text": "منشورات الشريف الرضي"},
|
|
{"language_code": "ar", "text": "منشورات الشريف الرضي"},
|
|
{"language_code": "en", "text": "Al-Sharif al-Razi Publications"},
|
|
],
|
|
[
|
|
{"language_code": "fa", "text": "مؤسسة النشر الإسلامي"},
|
|
{"language_code": "ar", "text": "مؤسسة النشر الإسلامي التابعة لجماعة المدرسين"},
|
|
{"language_code": "en", "text": "Islamic Publishing Foundation"},
|
|
],
|
|
[
|
|
{"language_code": "fa", "text": "مؤسسة البلاغ"},
|
|
{"language_code": "ar", "text": "مؤسسة البلاغ للطباعة والنشر والتوزيع"},
|
|
{"language_code": "en", "text": "Al-Balagh Foundation"},
|
|
],
|
|
]
|
|
|
|
cities_pool = [
|
|
[{"language_code": "fa", "text": "قم"}, {"language_code": "ar", "text": "قم المقدسة"}, {"language_code": "en", "text": "Qom"}],
|
|
[{"language_code": "fa", "text": "بیروت"}, {"language_code": "ar", "text": "بيروت"}, {"language_code": "en", "text": "Beirut"}],
|
|
[{"language_code": "fa", "text": "نجف"}, {"language_code": "ar", "text": "النجف الأشرف"}, {"language_code": "en", "text": "Najaf"}],
|
|
[{"language_code": "fa", "text": "تهران"}, {"language_code": "ar", "text": "طهران"}, {"language_code": "en", "text": "Tehran"}],
|
|
[{"language_code": "fa", "text": "مشهد"}, {"language_code": "ar", "text": "مشهد المقدسة"}, {"language_code": "en", "text": "Mashhad"}],
|
|
]
|
|
|
|
countries_pool = [
|
|
[{"language_code": "fa", "text": "ایران"}, {"language_code": "ar", "text": "إيران"}, {"language_code": "en", "text": "Iran"}],
|
|
[{"language_code": "fa", "text": "لبنان"}, {"language_code": "ar", "text": "لبنان"}, {"language_code": "en", "text": "Lebanon"}],
|
|
[{"language_code": "fa", "text": "عراق"}, {"language_code": "ar", "text": "العراق"}, {"language_code": "en", "text": "Iraq"}],
|
|
]
|
|
|
|
edition_names = ["چاپ اول", "چاپ دوم", "چاپ سوم", "طبعة ثانية منقحة", "طبعة أولى محققة", "First Revised Edition", "Second Edition"]
|
|
years_pool = ["1418 هـ.ق", "1422 هـ.ق", "1429 هـ.ق", "1436 هـ.ق", "1441 هـ.ق", "1385 ش", "1392 ش", "1398 ش", "1402 ش"]
|
|
|
|
total_editions_created = 0
|
|
total_volumes_created = 0
|
|
total_researchers_created = 0
|
|
total_editors_created = 0
|
|
|
|
self.stdout.write("Generating Editions and Volumes for BookReferences...")
|
|
|
|
with transaction.atomic():
|
|
for ref in references:
|
|
# Random choice: whether this reference has editions or only direct volumes
|
|
has_editions = random.choice([True, False])
|
|
ref.has_editions = has_editions
|
|
ref.save(update_fields=['has_editions'])
|
|
|
|
if has_editions:
|
|
num_editions = random.randint(1, 3)
|
|
for ed_idx in range(1, num_editions + 1):
|
|
num_volumes = random.randint(3, 5)
|
|
pub = random.choice(publishers_pool)
|
|
city = random.choice(cities_pool)
|
|
country = random.choice(countries_pool)
|
|
ed_num = random.choice(edition_names)
|
|
year = random.choice(years_pool)
|
|
isbn = f"978-964-{random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(0, 9)}"
|
|
|
|
edition = BookEdition.objects.create(
|
|
book_reference=ref,
|
|
publisher=pub,
|
|
city_of_publication=city,
|
|
country_of_publication=country,
|
|
edition_number=f"{ed_num} ({ed_idx})",
|
|
year_of_publication=year,
|
|
number_of_volumes=num_volumes,
|
|
isbn=isbn,
|
|
notes=[
|
|
{"language_code": "fa", "text": f"نسخه معتبر تصحیح شده با مقابله با نسخ خطی {ed_idx}"},
|
|
{"language_code": "en", "text": f"Verified critical edition compared against manuscripts {ed_idx}"}
|
|
],
|
|
source_url=f"https://lib.eshia.ir/{ref.id}/{edition_names[0]}"
|
|
)
|
|
total_editions_created += 1
|
|
|
|
# Assign random researchers and editors from existing authors
|
|
if authors:
|
|
sample_researchers = random.sample(authors, min(len(authors), random.randint(1, 2)))
|
|
for author in sample_researchers:
|
|
BookResearcher.objects.create(
|
|
book_edition=edition,
|
|
author=author
|
|
)
|
|
total_researchers_created += 1
|
|
|
|
sample_editors = random.sample(authors, min(len(authors), random.randint(1, 2)))
|
|
for author in sample_editors:
|
|
BookEditor.objects.create(
|
|
book_edition=edition,
|
|
author=author
|
|
)
|
|
total_editors_created += 1
|
|
|
|
# Create 3 to 5 volumes for this edition
|
|
for vol_idx in range(1, num_volumes + 1):
|
|
vol = BookVolume(
|
|
book_reference=ref,
|
|
edition=edition,
|
|
title=f"جلد {vol_idx}",
|
|
)
|
|
vol.image.save(
|
|
f"ref_{ref.id}_ed_{edition.id}_vol_{vol_idx}_cover.jpg",
|
|
ContentFile(image_bytes),
|
|
save=False
|
|
)
|
|
vol.file.save(
|
|
f"ref_{ref.id}_ed_{edition.id}_vol_{vol_idx}.pdf",
|
|
ContentFile(pdf_bytes),
|
|
save=False
|
|
)
|
|
vol.save()
|
|
total_volumes_created += 1
|
|
|
|
else:
|
|
# Direct volumes without editions
|
|
num_volumes = random.randint(3, 5)
|
|
for vol_idx in range(1, num_volumes + 1):
|
|
vol = BookVolume(
|
|
book_reference=ref,
|
|
edition=None,
|
|
title=f"جلد {vol_idx}",
|
|
)
|
|
vol.image.save(
|
|
f"ref_{ref.id}_vol_{vol_idx}_cover.jpg",
|
|
ContentFile(image_bytes),
|
|
save=False
|
|
)
|
|
vol.file.save(
|
|
f"ref_{ref.id}_vol_{vol_idx}.pdf",
|
|
ContentFile(pdf_bytes),
|
|
save=False
|
|
)
|
|
vol.save()
|
|
total_volumes_created += 1
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f"\n--- Seeding Completed Successfully ---\n"
|
|
f"Processed {len(references)} BookReferences:\n"
|
|
f" - Total BookEditions created: {total_editions_created}\n"
|
|
f" - Total BookVolumes created: {total_volumes_created}\n"
|
|
f" - Total Researchers assigned: {total_researchers_created}\n"
|
|
f" - Total Editors assigned: {total_editors_created}\n"
|
|
f" - Cover image & PDF attached to all volumes."
|
|
)
|
|
)
|