Browse Source

fixed referene image script

master
Mohsen Taba 4 months ago
parent
commit
69e80ada37
  1. 6
      apps/hadis/apps.py
  2. 144
      apps/hadis/management/commands/populate_refrence_images.py
  3. 2
      entrypoint.sh

6
apps/hadis/apps.py

@ -4,6 +4,6 @@ from django.apps import AppConfig
class HadisConfig(AppConfig): class HadisConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.hadis' name = 'apps.hadis'
def ready(self):
# Import the signals module when the app starts
import apps.hadis.signals
# def ready(self):
# # Import the signals module when the app starts
# # import apps.hadis.signals

144
apps/hadis/management/commands/populate_refrence_images.py

@ -2,22 +2,21 @@ import os
import random import random
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.core.files import File from django.core.files import File
from django.core.files.base import ContentFile
from django.conf import settings from django.conf import settings
from django.db import transaction
# REMEMBER: Change 'your_app' to your actual app name # REMEMBER: Change 'your_app' to your actual app name
from apps.hadis.models.hadis import Hadis, HadisReference, ReferenceImage from apps.hadis.models.hadis import Hadis, HadisReference, ReferenceImage
from apps.hadis.models.reference import BookReference from apps.hadis.models.reference import BookReference
class Command(BaseCommand): class Command(BaseCommand):
help = 'Wipes old reference data and seeds new HadisReference and ReferenceImages'
help = 'Seeds HadisReferences ensuring every Book has 2+ hadiths AND every Hadith has 1+ reference.'
def handle(self, *args, **kwargs): def handle(self, *args, **kwargs):
self.stdout.write(self.style.WARNING('--- Starting Cleanup ---')) self.stdout.write(self.style.WARNING('--- Starting Cleanup ---'))
# 1. DELETE PREVIOUS DATA # 1. DELETE PREVIOUS DATA
# We delete HadisReference. Because of on_delete=models.CASCADE in ReferenceImage,
# deleting the reference will automatically delete the associated images.
# However, we can delete both explicitly to be sure and show counts.
deleted_imgs_count, _ = ReferenceImage.objects.all().delete() deleted_imgs_count, _ = ReferenceImage.objects.all().delete()
deleted_refs_count, _ = HadisReference.objects.all().delete() deleted_refs_count, _ = HadisReference.objects.all().delete()
@ -25,69 +24,110 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS(f'Deleted {deleted_refs_count} old HadisReferences.')) self.stdout.write(self.style.SUCCESS(f'Deleted {deleted_refs_count} old HadisReferences.'))
self.stdout.write('------------------------') self.stdout.write('------------------------')
# 2. Setup Paths for Seeding
base_image_path = os.path.join(settings.BASE_DIR, 'seeds', 'images')
# We look for ref1.png, ref2.png, ref3.png, ref4.png
image_files = [f'ref{i}.png' for i in range(1, 5)]
# 2. Setup Paths
self.base_image_path = os.path.join(settings.BASE_DIR, 'seeds', 'images')
self.image_files = [f'ref{i}.png' for i in range(1, 5)]
# Verify images exist locally before starting
for img_name in image_files:
full_path = os.path.join(base_image_path, img_name)
# Verify images
for img_name in self.image_files:
full_path = os.path.join(self.base_image_path, img_name)
if not os.path.exists(full_path): if not os.path.exists(full_path):
self.stdout.write(self.style.ERROR(f'CRITICAL ERROR: Image not found at {full_path}')) self.stdout.write(self.style.ERROR(f'CRITICAL ERROR: Image not found at {full_path}'))
return return
# 3. Fetch Parents
# 3. Fetch Data
books = list(BookReference.objects.all()) books = list(BookReference.objects.all())
hadiths = list(Hadis.objects.all()) hadiths = list(Hadis.objects.all())
if len(hadiths) < 2:
self.stdout.write(self.style.ERROR('Not enough Hadiths in DB (need at least 2).'))
return
if not books:
self.stdout.write(self.style.ERROR('No BookReferences found in DB.'))
if not books or not hadiths:
self.stdout.write(self.style.ERROR('Missing Books or Hadiths in DB.'))
return return
self.stdout.write('--- Starting Seeding ---') self.stdout.write('--- Starting Seeding ---')
counter_refs = 0
counter_imgs = 0
self.counter_refs = 0
self.counter_imgs = 0
# Track which Hadith IDs have been covered
covered_hadith_ids = set()
# 4. Iterate Books (Constraint 1: Each book must relate to at least 2 hadith)
# ==========================================
# PHASE 1: Satisfy Book Constraint
# "Each book must relate to at least 2 hadith"
# ==========================================
self.stdout.write("Phase 1: Linking Books to Hadiths...")
for book in books: for book in books:
# Pick 2 random hadiths for this book # Pick 2 random hadiths for this book
selected_hadiths = random.sample(hadiths, 2)
# We use distinct logic if we want to ensure we don't pick the same one twice for one book
selected_hadiths = random.sample(hadiths, k=min(len(hadiths), 2))
for hadis_obj in selected_hadiths: for hadis_obj in selected_hadiths:
# Create the Link (HadisReference)
hadis_ref = HadisReference.objects.create(
hadis=hadis_obj,
book_reference=book,
description=[
{'language_code': 'en', 'text': f'Reference for {book.title[0].get("text", "Book")} - Hadith {hadis_obj.number}'},
{'language_code': 'ar', 'text': 'وصف مرجعي'}
]
)
counter_refs += 1
# 5. Connect Images (Constraint 2: Each hadith ref must have 2 images)
# We pick 2 random images from our list of 4
selected_images = random.sample(image_files, 2)
for priority_index, img_name in enumerate(selected_images):
img_path = os.path.join(base_image_path, img_name)
with open(img_path, 'rb') as f:
# Create ReferenceImage
ref_img = ReferenceImage(
reference=hadis_ref,
priority=priority_index # 0 and 1
)
# Save file to the ImageField
ref_img.thumbnail.save(img_name, File(f), save=True)
counter_imgs += 1
self._create_reference_chain(hadis_obj, book)
covered_hadith_ids.add(hadis_obj.id)
# ==========================================
# PHASE 2: Satisfy Hadith Constraint
# "Each hadith must have a hadith reference object"
# ==========================================
self.stdout.write("Phase 2: Checking for orphan Hadiths...")
for hadis_obj in hadiths:
if hadis_obj.id not in covered_hadith_ids:
# This hadith was skipped in Phase 1.
# We must assign it to a Book (Reference).
# Pick a random book to associate with
random_book = random.choice(books)
self._create_reference_chain(hadis_obj, random_book)
covered_hadith_ids.add(hadis_obj.id)
self.stdout.write(self.style.SUCCESS( self.stdout.write(self.style.SUCCESS(
f'DONE: Created {counter_refs} HadisReferences and {counter_imgs} ReferenceImages.'
))
f'DONE: Created {self.counter_refs} HadisReferences (covering {len(covered_hadith_ids)} Hadiths) and {self.counter_imgs} Images.'
))
def _create_reference_chain(self, hadis_obj, book_obj):
"""
Helper to create the Reference and its Images
"""
# Create the HadisReference
hadis_ref = HadisReference.objects.create(
hadis=hadis_obj,
book_reference=book_obj,
description=[
{'language_code': 'en', 'text': f'Reference for {book_obj.title[0].get("text", "Book")} - Hadith {hadis_obj.number}'},
{'language_code': 'ar', 'text': 'وصف مرجعي'}
]
)
self.counter_refs += 1
# Create Images for this Reference
self._create_images_for_ref(hadis_ref)
def _create_images_for_ref(self, hadis_ref):
"""
Helper to create 2 images for a specific HadisReference
"""
selected_images = random.sample(self.image_files, 2)
for priority_index, img_name in enumerate(selected_images):
img_path = os.path.join(self.base_image_path, img_name)
# Read file safely
with open(img_path, 'rb') as f:
file_content = f.read()
ref_img = ReferenceImage(
reference=hadis_ref,
priority=priority_index
)
# Assign content without auto-saving
ref_img.thumbnail.save(img_name, ContentFile(file_content), save=False)
try:
# Explicit save to handle your custom model logic / signals
ref_img.save()
self.counter_imgs += 1
except Exception as e:
self.stdout.write(self.style.ERROR(f"Failed to save image {img_name}: {e}"))

2
entrypoint.sh

@ -7,6 +7,6 @@ python manage.py collectstatic --noinput
# python manage.py populate_books # python manage.py populate_books
# python manage.py populate_book_reference # python manage.py populate_book_reference
python manage.py populate_reference_images
python manage.py populate_refrence_images
exec "$@" exec "$@"
Loading…
Cancel
Save