14 changed files with 2115 additions and 20 deletions
-
8apps/hadis/docs.py
-
276apps/hadis/management/commands/seed_books.py
-
497apps/hadis/management/commands/seed_category_data.py
-
432apps/hadis/management/commands/seed_hadis_2.py
-
613apps/hadis/management/commands/seed_transmitters.py
-
29apps/hadis/serializers/hadis.py
-
4apps/hadis/views/hadis.py
-
0scripts/__init__.py
-
276scripts/seed_books.py
-
BINseeds/images/image 1208.png
-
BINseeds/images/ref1.png
-
BINseeds/images/ref2.png
-
BINseeds/images/ref3.png
-
BINseeds/images/ref4.png
@ -0,0 +1,276 @@ |
|||||
|
""" |
||||
|
Django management command to seed mock data for hadith book references. |
||||
|
Place this file in: yourapp/management/commands/seed_books.py |
||||
|
|
||||
|
Usage: python manage.py seed_books |
||||
|
""" |
||||
|
|
||||
|
import os |
||||
|
from pathlib import Path |
||||
|
from django.core.management.base import BaseCommand |
||||
|
from django.core.files.base import ContentFile |
||||
|
from django.utils.text import slugify |
||||
|
from apps.hadis.models.reference import ( |
||||
|
BookReference, |
||||
|
BookReferenceImage, |
||||
|
BookAuthor, |
||||
|
BookAttribute |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class Command(BaseCommand): |
||||
|
help = 'Seed the database with mock hadith book reference data' |
||||
|
|
||||
|
def add_arguments(self, parser): |
||||
|
parser.add_argument( |
||||
|
'--clear', |
||||
|
action='store_true', |
||||
|
help='Clear existing data before seeding', |
||||
|
) |
||||
|
|
||||
|
def handle(self, *args, **options): |
||||
|
if options['clear']: |
||||
|
self.stdout.write(self.style.WARNING('Clearing existing data...')) |
||||
|
BookAttribute.objects.all().delete() |
||||
|
BookReferenceImage.objects.all().delete() |
||||
|
BookAuthor.objects.all().delete() |
||||
|
BookReference.objects.all().delete() |
||||
|
self.stdout.write(self.style.SUCCESS('Data cleared successfully!')) |
||||
|
|
||||
|
# Create authors first |
||||
|
authors_data = [ |
||||
|
{"name": "Imam Muhammad al-Bukhari"}, |
||||
|
{"name": "Imam Muslim ibn al-Hajjaj"}, |
||||
|
{"name": "Imam Abu Dawood as-Sijistani"}, |
||||
|
{"name": "Imam At-Tirmidhi"}, |
||||
|
{"name": "Imam Ibn Majah"}, |
||||
|
{"name": "Imam Ahmad ibn Hanbal"}, |
||||
|
{"name": "Imam Al-Hakim"}, |
||||
|
{"name": "Imam Ad-Daraqutni"}, |
||||
|
] |
||||
|
|
||||
|
authors = {} |
||||
|
for author_data in authors_data: |
||||
|
author, created = BookAuthor.objects.get_or_create( |
||||
|
name=author_data['name'] |
||||
|
) |
||||
|
authors[author_data['name']] = author |
||||
|
if created: |
||||
|
self.stdout.write(self.style.SUCCESS(f'Created author: {author.name}')) |
||||
|
|
||||
|
# Create book references |
||||
|
books_data = [ |
||||
|
{ |
||||
|
"title": "Sahih al-Bukhari", |
||||
|
"description": "The most authentic collection of hadith, compiled by Imam Muhammad al-Bukhari. Contains 7,563 ahadith.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-009-6", |
||||
|
"volume": "9 volumes", |
||||
|
"year_of_publication": "1870", |
||||
|
"number_page": 1200, |
||||
|
"publisher": "Dar al-Kutub al-Ilmiyah", |
||||
|
"rate": 5.00, |
||||
|
"authors": ["Imam Muhammad al-Bukhari"], |
||||
|
"image_order": 1, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Hadith Compilation", |
||||
|
"Number of Hadith": "7,563", |
||||
|
"Classification": "6 Books", |
||||
|
"Authenticity Grade": "Sahih (Authentic)", |
||||
|
"Compilation Period": "16 years", |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"title": "Sahih Muslim", |
||||
|
"description": "Second most authentic hadith collection compiled by Imam Muslim ibn al-Hajjaj. Contains 9,200 traditions.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-010-2", |
||||
|
"volume": "5 volumes", |
||||
|
"year_of_publication": "1875", |
||||
|
"number_page": 1500, |
||||
|
"publisher": "Dar Ihya at-Turath al-Arabi", |
||||
|
"rate": 4.95, |
||||
|
"authors": ["Imam Muslim ibn al-Hajjaj"], |
||||
|
"image_order": 2, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Hadith Compilation", |
||||
|
"Number of Hadith": "9,200", |
||||
|
"Classification": "43 Books", |
||||
|
"Authenticity Grade": "Sahih (Authentic)", |
||||
|
"Unique Hadith": "Approximately 4,000", |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"title": "Sunan Abu Dawood", |
||||
|
"description": "A comprehensive collection of hadith containing jurisprudential material, compiled by Imam Abu Dawood as-Sijistani.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-011-9", |
||||
|
"volume": "4 volumes", |
||||
|
"year_of_publication": "1880", |
||||
|
"number_page": 1400, |
||||
|
"publisher": "Islamic Digital Library", |
||||
|
"rate": 4.80, |
||||
|
"authors": ["Imam Abu Dawood as-Sijistani"], |
||||
|
"image_order": 3, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Sunan (Practice)", |
||||
|
"Number of Hadith": "5,274", |
||||
|
"Focus": "Jurisprudential Traditions", |
||||
|
"Number of Books": "43", |
||||
|
"Authenticity Grade": "Hasan to Sahih", |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"title": "Jami' at-Tirmidhi", |
||||
|
"description": "A major collection of hadith compiled by Imam At-Tirmidhi with his commentary and grading of narrations.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-012-6", |
||||
|
"volume": "5 volumes", |
||||
|
"year_of_publication": "1892", |
||||
|
"number_page": 1350, |
||||
|
"publisher": "Dar ar-Risalah al-Alamiyah", |
||||
|
"rate": 4.85, |
||||
|
"authors": ["Imam At-Tirmidhi"], |
||||
|
"image_order": 4, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Jami (Comprehensive)", |
||||
|
"Number of Hadith": "3,956", |
||||
|
"Notable Feature": "Grades each hadith", |
||||
|
"Categories": "63 Chapters", |
||||
|
"Authenticity Grade": "Various Grades", |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"title": "Sunan Ibn Majah", |
||||
|
"description": "A collection of hadith compiled by Imam Ibn Majah, one of the Six Canonical Hadith Collections.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-013-3", |
||||
|
"volume": "2 volumes", |
||||
|
"year_of_publication": "1888", |
||||
|
"number_page": 900, |
||||
|
"publisher": "Dar Ihya al-Kutub al-Arabiyah", |
||||
|
"rate": 4.75, |
||||
|
"authors": ["Imam Ibn Majah"], |
||||
|
"image_order": 5, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Sunan (Practice)", |
||||
|
"Number of Hadith": "4,341", |
||||
|
"Number of Books": "32", |
||||
|
"Notable Content": "Includes rare narrations", |
||||
|
"Authenticity Grade": "Mixed - requires verification", |
||||
|
} |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
books = {} |
||||
|
for book_data in books_data: |
||||
|
# Extract author names |
||||
|
author_names = book_data.pop('authors', []) |
||||
|
image_order = book_data.pop('image_order', 1) |
||||
|
attributes_dict = book_data.pop('attributes', {}) |
||||
|
|
||||
|
# Create or get the book |
||||
|
book, created = BookReference.objects.get_or_create( |
||||
|
title=book_data['title'], |
||||
|
defaults=book_data |
||||
|
) |
||||
|
|
||||
|
if created: |
||||
|
self.stdout.write(self.style.SUCCESS(f'Created book: {book.title}')) |
||||
|
else: |
||||
|
# Update existing book |
||||
|
for key, value in book_data.items(): |
||||
|
setattr(book, key, value) |
||||
|
book.save() |
||||
|
self.stdout.write(self.style.WARNING(f'Updated book: {book.title}')) |
||||
|
|
||||
|
books[book.title] = book |
||||
|
|
||||
|
# Add authors to book |
||||
|
for author_name in author_names: |
||||
|
author = authors.get(author_name) |
||||
|
if author: |
||||
|
book.authors.add(author) |
||||
|
|
||||
|
# Add book image |
||||
|
image_path = self._get_image_path(image_order) |
||||
|
if image_path and os.path.exists(image_path): |
||||
|
# Check if image already exists for this book |
||||
|
if not book.images.exists(): |
||||
|
with open(image_path, 'rb') as img_file: |
||||
|
image_name = f'book{image_order}.png' |
||||
|
book_image = BookReferenceImage.objects.create( |
||||
|
book_reference=book, |
||||
|
order=1, |
||||
|
description=f"Cover image for {book.title}" |
||||
|
) |
||||
|
book_image.image.save( |
||||
|
image_name, |
||||
|
ContentFile(img_file.read()), |
||||
|
save=True |
||||
|
) |
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS(f'Added image to: {book.title}') |
||||
|
) |
||||
|
else: |
||||
|
self.stdout.write( |
||||
|
self.style.WARNING( |
||||
|
f'Image not found at {image_path} for {book.title}' |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
# Add attributes |
||||
|
for attr_title, attr_value in attributes_dict.items(): |
||||
|
attribute, created = BookAttribute.objects.get_or_create( |
||||
|
book_reference=book, |
||||
|
title=attr_title, |
||||
|
defaults={'value': attr_value} |
||||
|
) |
||||
|
if created: |
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f'Added attribute: {attr_title} to {book.title}' |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f'\n✓ Successfully seeded {len(books)} books with all relations!' |
||||
|
) |
||||
|
) |
||||
|
self._print_summary() |
||||
|
|
||||
|
def _get_image_path(self, book_number): |
||||
|
""" |
||||
|
Find the image file for the given book number. |
||||
|
Checks multiple possible locations. |
||||
|
""" |
||||
|
possible_paths = [ |
||||
|
Path('seeds/images') / f'book{book_number}.png', |
||||
|
Path('seed_data/images') / f'book{book_number}.png', |
||||
|
Path('static/images') / f'book{book_number}.png', |
||||
|
Path('.') / 'seeds' / 'images' / f'book{book_number}.png', |
||||
|
] |
||||
|
|
||||
|
for path in possible_paths: |
||||
|
if path.exists(): |
||||
|
return path |
||||
|
|
||||
|
return None |
||||
|
|
||||
|
def _print_summary(self): |
||||
|
"""Print a summary of created data""" |
||||
|
self.stdout.write("\n" + "="*60) |
||||
|
self.stdout.write(self.style.SUCCESS("DATABASE SUMMARY")) |
||||
|
self.stdout.write("="*60) |
||||
|
|
||||
|
books_count = BookReference.objects.count() |
||||
|
authors_count = BookAuthor.objects.count() |
||||
|
images_count = BookReferenceImage.objects.count() |
||||
|
attributes_count = BookAttribute.objects.count() |
||||
|
|
||||
|
self.stdout.write(f"📚 Total Books: {books_count}") |
||||
|
self.stdout.write(f"✍️ Total Authors: {authors_count}") |
||||
|
self.stdout.write(f"🖼️ Total Images: {images_count}") |
||||
|
self.stdout.write(f"🏷️ Total Attributes: {attributes_count}") |
||||
|
self.stdout.write("="*60 + "\n") |
||||
@ -0,0 +1,497 @@ |
|||||
|
""" |
||||
|
Django management command to seed mock HadisCategory trees and new Hadis |
||||
|
for history, fatwa and quote sources. |
||||
|
|
||||
|
Place this file in: hadis/management/commands/seed_categories.py |
||||
|
|
||||
|
Usage: |
||||
|
python manage.py seed_categories |
||||
|
python manage.py seed_categories --clear |
||||
|
""" |
||||
|
|
||||
|
from django.core.management.base import BaseCommand |
||||
|
from django.utils.text import slugify |
||||
|
from django.conf import settings |
||||
|
|
||||
|
from apps.hadis.models.category import HadisCategory, HadisSect |
||||
|
from apps.hadis.models.hadis import Hadis, HadisStatus, HadisTag |
||||
|
|
||||
|
|
||||
|
class Command(BaseCommand): |
||||
|
help = "Seed HadisCategory trees (history, fatwa, quote) and new Hadis connected to them." |
||||
|
|
||||
|
def add_arguments(self, parser): |
||||
|
parser.add_argument( |
||||
|
'--clear', |
||||
|
action='store_true', |
||||
|
help='Clear ONLY categories & hadises created by this command (history/fatwa/quote).', |
||||
|
) |
||||
|
|
||||
|
def handle(self, *args, **options): |
||||
|
if options['clear']: |
||||
|
self._clear_seeded_data() |
||||
|
|
||||
|
# Ensure sects exist |
||||
|
try: |
||||
|
shia_sect = HadisSect.objects.get(sect_type=HadisSect.SectType.SHIA) |
||||
|
except HadisSect.DoesNotExist: |
||||
|
shia_sect = HadisSect.objects.create( |
||||
|
sect_type=HadisSect.SectType.SHIA, |
||||
|
title="Shia", |
||||
|
description="Default Shia sect" |
||||
|
) |
||||
|
|
||||
|
try: |
||||
|
sunni_sect = HadisSect.objects.get(sect_type=HadisSect.SectType.SUNNI) |
||||
|
except HadisSect.DoesNotExist: |
||||
|
sunni_sect = HadisSect.objects.create( |
||||
|
sect_type=HadisSect.SectType.SUNNI, |
||||
|
title="Sunni", |
||||
|
description="Default Sunni sect" |
||||
|
) |
||||
|
|
||||
|
# Optional: ensure a couple of HadisStatus entries exist |
||||
|
default_status, _ = HadisStatus.objects.get_or_create( |
||||
|
title="Authentic / Accepted", |
||||
|
defaults={"color": HadisStatus.ColorChoices.GREEN, "order": 1}, |
||||
|
) |
||||
|
weak_status, _ = HadisStatus.objects.get_or_create( |
||||
|
title="Weak / Needs Review", |
||||
|
defaults={"color": HadisStatus.ColorChoices.YELLOW, "order": 2}, |
||||
|
) |
||||
|
|
||||
|
# Ensure some tags exist |
||||
|
tags = self._ensure_tags() |
||||
|
|
||||
|
# 1) Seed HISTORY categories & hadises |
||||
|
self.stdout.write(self.style.SUCCESS("\n📚 Creating HISTORY categories and hadiths...")) |
||||
|
self._seed_history_tree(sunni_sect, default_status, tags) |
||||
|
|
||||
|
# 2) Seed FATWA categories & hadises |
||||
|
self.stdout.write(self.style.SUCCESS("\n📜 Creating FATWA categories and hadiths...")) |
||||
|
self._seed_fatwa_tree(sunni_sect, default_status, weak_status, tags) |
||||
|
|
||||
|
# 3) Seed QUOTE categories & hadises |
||||
|
self.stdout.write(self.style.SUCCESS("\n💬 Creating QUOTE categories and hadiths...")) |
||||
|
self._seed_quote_tree(shia_sect, default_status, tags) |
||||
|
|
||||
|
self._print_summary() |
||||
|
|
||||
|
# ------------------------------------------------------------------ # |
||||
|
# Helpers |
||||
|
# ------------------------------------------------------------------ # |
||||
|
|
||||
|
def _clear_seeded_data(self): |
||||
|
""" |
||||
|
Clear only categories with source_type in (history, fatwa, quote) |
||||
|
and hadises that are attached to those categories. |
||||
|
""" |
||||
|
self.stdout.write(self.style.WARNING("Clearing previously seeded history/fatwa/quote data...")) |
||||
|
leaf_categories = HadisCategory.objects.filter( |
||||
|
source_type__in=[ |
||||
|
HadisCategory.SourceType.HISTORY, |
||||
|
HadisCategory.SourceType.FATWA, |
||||
|
HadisCategory.SourceType.QUOTE, |
||||
|
] |
||||
|
) |
||||
|
Hadis.objects.filter(category__in=leaf_categories).delete() |
||||
|
# Delete categories (MPTT will handle tree structure) |
||||
|
HadisCategory.objects.filter( |
||||
|
source_type__in=[ |
||||
|
HadisCategory.SourceType.HISTORY, |
||||
|
HadisCategory.SourceType.FATWA, |
||||
|
HadisCategory.SourceType.QUOTE, |
||||
|
] |
||||
|
).delete() |
||||
|
self.stdout.write(self.style.SUCCESS("✓ Cleared seeded history/fatwa/quote categories and hadiths.")) |
||||
|
|
||||
|
def _ensure_tags(self): |
||||
|
base_titles = [ |
||||
|
"history", |
||||
|
"biography", |
||||
|
"battle", |
||||
|
"ethics", |
||||
|
"jurisprudence", |
||||
|
"family", |
||||
|
"wisdom", |
||||
|
"short quote", |
||||
|
] |
||||
|
tags = [] |
||||
|
for title in base_titles: |
||||
|
tag, _ = HadisTag.objects.get_or_create(title=title) |
||||
|
tags.append(tag) |
||||
|
return tags |
||||
|
|
||||
|
# ---------------- HISTORY ---------------- # |
||||
|
|
||||
|
def _seed_history_tree(self, sect, default_status, tags): |
||||
|
""" |
||||
|
Create a small HISTORY tree: |
||||
|
History of Islam |
||||
|
├─ Early Caliphate (leaf) |
||||
|
└─ Battles (leaf) |
||||
|
And add several hadith-like historical reports. |
||||
|
""" |
||||
|
root, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.HISTORY, |
||||
|
title="History of Islam", |
||||
|
defaults={ |
||||
|
"description": "High-level historical themes related to early Islamic history.", |
||||
|
"order": 1, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
early_caliphate, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.HISTORY, |
||||
|
parent=root, |
||||
|
title="Early Caliphate", |
||||
|
defaults={ |
||||
|
"description": "Events and reports from the period of the first caliphs.", |
||||
|
"order": 1, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
battles, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.HISTORY, |
||||
|
parent=root, |
||||
|
title="Battles and Expeditions", |
||||
|
defaults={ |
||||
|
"description": "Key battles and expeditions in early Islamic history.", |
||||
|
"order": 2, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
# Create some historical “hadith” entries (reports) |
||||
|
# For simplicity, use new numbers starting from 1900+ |
||||
|
self._create_hadis( |
||||
|
number=1900, |
||||
|
category=early_caliphate, |
||||
|
title="The Consultation of the Companions", |
||||
|
text=( |
||||
|
"It is reported in historical works that the companions would gather and " |
||||
|
"consult one another regarding major affairs of the community." |
||||
|
), |
||||
|
translation_en=( |
||||
|
"Historical reports mention that the companions would consult one another " |
||||
|
"on major communal matters." |
||||
|
), |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["history", "biography"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1901, |
||||
|
category=early_caliphate, |
||||
|
title="Establishment of the Public Treasury", |
||||
|
text=( |
||||
|
"Some historians narrate that during the early caliphate a public treasury " |
||||
|
"was organized to administer charity and public funds." |
||||
|
), |
||||
|
translation_en=( |
||||
|
"Historical sources state that a public treasury was set up to manage " |
||||
|
"charity and communal funds." |
||||
|
), |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["history", "jurisprudence"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1910, |
||||
|
category=battles, |
||||
|
title="Report of the Battle Preparations", |
||||
|
text=( |
||||
|
"Chronicles record that the believers prepared carefully before major battles, " |
||||
|
"ensuring justice and discipline in their ranks." |
||||
|
), |
||||
|
translation_en=( |
||||
|
"Historical chronicles record careful preparations and discipline before major battles." |
||||
|
), |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["history", "battle"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1911, |
||||
|
category=battles, |
||||
|
title="Mercy Shown After Victory", |
||||
|
text=( |
||||
|
"Historical narrations mention that after some victories, clemency and mercy were " |
||||
|
"shown to prisoners and civilians." |
||||
|
), |
||||
|
translation_en=( |
||||
|
"Historical narrations mention mercy and clemency after some military victories." |
||||
|
), |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["history", "ethics"]], |
||||
|
) |
||||
|
|
||||
|
# ---------------- FATWA ---------------- # |
||||
|
|
||||
|
def _seed_fatwa_tree(self, sect, default_status, weak_status, tags): |
||||
|
""" |
||||
|
Create a FATWA tree like: |
||||
|
Contemporary Fatwas |
||||
|
├─ Worship (leaf) |
||||
|
└─ Family Issues (leaf) |
||||
|
Plus a second root: |
||||
|
Financial Fatwas |
||||
|
└─ Trade and Contracts (leaf) |
||||
|
""" |
||||
|
root_contemporary, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.FATWA, |
||||
|
title="Contemporary Fatwas", |
||||
|
defaults={ |
||||
|
"description": "Modern juristic responses to contemporary questions.", |
||||
|
"order": 1, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
worship, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.FATWA, |
||||
|
parent=root_contemporary, |
||||
|
title="Worship and Rituals", |
||||
|
defaults={ |
||||
|
"description": "Fatwas about prayer, fasting and other acts of worship.", |
||||
|
"order": 1, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
family_issues, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.FATWA, |
||||
|
parent=root_contemporary, |
||||
|
title="Family Issues", |
||||
|
defaults={ |
||||
|
"description": "Fatwas regarding marriage, divorce and family obligations.", |
||||
|
"order": 2, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
financial_root, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.FATWA, |
||||
|
title="Financial Fatwas", |
||||
|
defaults={ |
||||
|
"description": "Juristic rulings about trade, contracts and modern finance.", |
||||
|
"order": 2, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
trade_contracts, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.FATWA, |
||||
|
parent=financial_root, |
||||
|
title="Trade and Contracts", |
||||
|
defaults={ |
||||
|
"description": "Fatwas related to buying, selling and contractual agreements.", |
||||
|
"order": 1, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
# Create some “fatwa-style” hadith entries (answers / rulings) |
||||
|
self._create_hadis( |
||||
|
number=1920, |
||||
|
category=worship, |
||||
|
title="Fatwa on Combining Prayers While Traveling", |
||||
|
text=( |
||||
|
"A contemporary juristic council has ruled that combining prayers while traveling " |
||||
|
"is permitted when hardship is present, following classical precedents." |
||||
|
), |
||||
|
translation_en=( |
||||
|
"A modern fatwa allows combining prayers during travel where hardship exists, " |
||||
|
"based on earlier jurisprudence." |
||||
|
), |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["jurisprudence", "ethics"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1921, |
||||
|
category=worship, |
||||
|
title="Fatwa on Using Local Calculations for Prayer Times", |
||||
|
text=( |
||||
|
"Modern scholars have issued fatwas permitting the use of accurate astronomical " |
||||
|
"calculations for determining prayer times." |
||||
|
), |
||||
|
translation_en=( |
||||
|
"Contemporary fatwas permit using precise astronomical calculations for prayer times." |
||||
|
), |
||||
|
status=weak_status, |
||||
|
tags=[t for t in tags if t.title in ["jurisprudence", "knowledge"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1930, |
||||
|
category=family_issues, |
||||
|
title="Fatwa on Upholding Family Ties", |
||||
|
text=( |
||||
|
"A fatwa committee emphasized that maintaining family ties is obligatory and that " |
||||
|
"cutting off relatives without valid reason is sinful." |
||||
|
), |
||||
|
translation_en=( |
||||
|
"A fatwa stresses that keeping family ties is obligatory and severing them without cause is sinful." |
||||
|
), |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["family", "ethics"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1940, |
||||
|
category=trade_contracts, |
||||
|
title="Fatwa on Transparent Business Contracts", |
||||
|
text=( |
||||
|
"Scholars have ruled that contracts must be transparent and free from deception in order " |
||||
|
"to be valid in Islamic law." |
||||
|
), |
||||
|
translation_en=( |
||||
|
"A modern fatwa requires transparency and absence of deception in business contracts." |
||||
|
), |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["business", "jurisprudence"]] if any( |
||||
|
t.title == "business" for t in tags |
||||
|
) else [t for t in tags if t.title in ["jurisprudence"]], |
||||
|
) |
||||
|
|
||||
|
# ---------------- QUOTE ---------------- # |
||||
|
|
||||
|
def _seed_quote_tree(self, sect, default_status, tags): |
||||
|
""" |
||||
|
Create a QUOTE tree: |
||||
|
Wisdom Quotes |
||||
|
├─ Short Wisdom (leaf) |
||||
|
└─ On Knowledge (leaf) |
||||
|
""" |
||||
|
root, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.QUOTE, |
||||
|
title="Wisdom Quotes", |
||||
|
defaults={ |
||||
|
"description": "Short wise sayings and inspirational quotes.", |
||||
|
"order": 1, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
short_wisdom, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.QUOTE, |
||||
|
parent=root, |
||||
|
title="Short Wisdom", |
||||
|
defaults={ |
||||
|
"description": "Very short, memorable quotes on character and behavior.", |
||||
|
"order": 1, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
on_knowledge, _ = HadisCategory.objects.get_or_create( |
||||
|
sect=sect, |
||||
|
source_type=HadisCategory.SourceType.QUOTE, |
||||
|
parent=root, |
||||
|
title="On Knowledge", |
||||
|
defaults={ |
||||
|
"description": "Quotes emphasizing the virtue of knowledge and learning.", |
||||
|
"order": 2, |
||||
|
}, |
||||
|
) |
||||
|
|
||||
|
# Short quote-style entries |
||||
|
self._create_hadis( |
||||
|
number=1950, |
||||
|
category=short_wisdom, |
||||
|
title="The Measure of a Heart", |
||||
|
text="It is said: The worth of a person is in what their heart carries of mercy and truth.", |
||||
|
translation_en="It is said: A person’s value is measured by the mercy and truth in their heart.", |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["wisdom", "short quote", "ethics"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1951, |
||||
|
category=short_wisdom, |
||||
|
title="Silence and Wisdom", |
||||
|
text="One of the wise said: Many people would be considered wise if they knew when to remain silent.", |
||||
|
translation_en="A wise saying: Many would be counted wise if they knew when to be silent.", |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["wisdom", "short quote"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1960, |
||||
|
category=on_knowledge, |
||||
|
title="Seeking Knowledge as Light", |
||||
|
text="It is narrated from the scholars: Knowledge is a light that guides the heart towards what benefits it.", |
||||
|
translation_en="Scholars say: Knowledge is a light guiding the heart to what benefits it.", |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["knowledge", "wisdom"]], |
||||
|
) |
||||
|
|
||||
|
self._create_hadis( |
||||
|
number=1961, |
||||
|
category=on_knowledge, |
||||
|
title="Learning until the End", |
||||
|
text="One sage said: Continue to seek knowledge until the last day of your life, for ignorance is a darkness.", |
||||
|
translation_en="A sage said: Seek knowledge until your last day, for ignorance is darkness.", |
||||
|
status=default_status, |
||||
|
tags=[t for t in tags if t.title in ["knowledge", "wisdom"]], |
||||
|
) |
||||
|
|
||||
|
# ---------------- utility to create Hadis ---------------- # |
||||
|
|
||||
|
def _create_hadis(self, number, category, title, text, translation_en, status, tags): |
||||
|
""" |
||||
|
Create or update a Hadis with the given number and category. |
||||
|
Translation uses {'en': '...'} structure as requested. |
||||
|
""" |
||||
|
hadis, created = Hadis.objects.get_or_create( |
||||
|
number=number, |
||||
|
category=category, |
||||
|
defaults={ |
||||
|
"title": title, |
||||
|
"title_narrator": None, |
||||
|
"description": "", |
||||
|
"text": text, |
||||
|
"translation": {"en": translation_en}, |
||||
|
"status": True, |
||||
|
"hadis_status": status, |
||||
|
"hadis_status_text": status.title if status else "", |
||||
|
"address": "", |
||||
|
"links": {}, |
||||
|
"explanation": "", |
||||
|
}, |
||||
|
) |
||||
|
if not created: |
||||
|
hadis.title = title |
||||
|
hadis.text = text |
||||
|
hadis.translation = {"en": translation_en} |
||||
|
hadis.hadis_status = status |
||||
|
hadis.hadis_status_text = status.title if status else "" |
||||
|
hadis.category = category |
||||
|
hadis.save() |
||||
|
|
||||
|
if tags: |
||||
|
hadis.tags.set(tags) |
||||
|
return hadis |
||||
|
|
||||
|
def _print_summary(self): |
||||
|
from apps.hadis.models import HadisCategory, Hadis |
||||
|
|
||||
|
self.stdout.write("\n" + "=" * 70) |
||||
|
self.stdout.write(self.style.SUCCESS("CATEGORY & HADIS SUMMARY")) |
||||
|
self.stdout.write("=" * 70) |
||||
|
|
||||
|
history_count = HadisCategory.objects.filter(source_type=HadisCategory.SourceType.HISTORY).count() |
||||
|
fatwa_count = HadisCategory.objects.filter(source_type=HadisCategory.SourceType.FATWA).count() |
||||
|
quote_count = HadisCategory.objects.filter(source_type=HadisCategory.SourceType.QUOTE).count() |
||||
|
|
||||
|
history_hadis = Hadis.objects.filter(category__source_type=HadisCategory.SourceType.HISTORY).count() |
||||
|
fatwa_hadis = Hadis.objects.filter(category__source_type=HadisCategory.SourceType.FATWA).count() |
||||
|
quote_hadis = Hadis.objects.filter(category__source_type=HadisCategory.SourceType.QUOTE).count() |
||||
|
|
||||
|
self.stdout.write(f"📂 HISTORY categories: {history_count} | hadith-like records: {history_hadis}") |
||||
|
self.stdout.write(f"📂 FATWA categories: {fatwa_count} | fatwa records: {fatwa_hadis}") |
||||
|
self.stdout.write(f"📂 QUOTE categories: {quote_count} | quote records: {quote_hadis}") |
||||
|
self.stdout.write("=" * 70 + "\n") |
||||
@ -0,0 +1,432 @@ |
|||||
|
""" |
||||
|
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 |
||||
|
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 ( |
||||
|
HadisCollection, |
||||
|
HadisInCollection, |
||||
|
HadisReference, |
||||
|
ReferenceImage, |
||||
|
HadisCorrection, |
||||
|
Hadis |
||||
|
) |
||||
|
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', |
||||
|
) |
||||
|
|
||||
|
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!')) |
||||
|
|
||||
|
# 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": "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...") |
||||
|
) |
||||
|
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] |
||||
|
|
||||
|
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)] |
||||
|
} |
||||
|
) |
||||
|
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") |
||||
|
|
||||
|
# Step 5: Create Hadis In Collection |
||||
|
self.stdout.write(self.style.SUCCESS('\n📋 Adding Hadis to Collections...')) |
||||
|
|
||||
|
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], |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
hadis_in_collection_count = 0 |
||||
|
for assignment in collection_assignments: |
||||
|
collection = collections.get(assignment['collection_title']) |
||||
|
if not collection: |
||||
|
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 |
||||
|
|
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f'\n✓ Successfully seeded hadith data!' |
||||
|
) |
||||
|
) |
||||
|
self._print_summary( |
||||
|
collections, |
||||
|
hadis_in_collection_count, |
||||
|
len(hadis_references), |
||||
|
ref_images_added, |
||||
|
corrections_count |
||||
|
) |
||||
|
|
||||
|
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 |
||||
|
|
||||
|
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 |
||||
|
|
||||
|
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) |
||||
|
|
||||
|
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() |
||||
|
|
||||
|
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") |
||||
@ -0,0 +1,613 @@ |
|||||
|
""" |
||||
|
Django management command to seed mock data for hadith transmitters and related models. |
||||
|
Place this file in: yourapp/management/commands/seed_transmitters.py |
||||
|
|
||||
|
Usage: python manage.py seed_transmitters |
||||
|
python manage.py seed_transmitters --clear |
||||
|
""" |
||||
|
|
||||
|
import json |
||||
|
from django.core.management.base import BaseCommand |
||||
|
from django.utils.text import slugify |
||||
|
from apps.hadis.models.transmitter import ( |
||||
|
NarratorLayer, |
||||
|
Transmitters, |
||||
|
HadisTransmitter, |
||||
|
TransmitterOpinion, |
||||
|
TransmitterOriginalText |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class Command(BaseCommand): |
||||
|
help = 'Seed the database with mock hadith transmitter data' |
||||
|
|
||||
|
def add_arguments(self, parser): |
||||
|
parser.add_argument( |
||||
|
'--clear', |
||||
|
action='store_true', |
||||
|
help='Clear existing data before seeding', |
||||
|
) |
||||
|
|
||||
|
def handle(self, *args, **options): |
||||
|
if options['clear']: |
||||
|
self.stdout.write(self.style.WARNING('Clearing existing transmitter data...')) |
||||
|
TransmitterOriginalText.objects.all().delete() |
||||
|
TransmitterOpinion.objects.all().delete() |
||||
|
HadisTransmitter.objects.all().delete() |
||||
|
Transmitters.objects.all().delete() |
||||
|
NarratorLayer.objects.all().delete() |
||||
|
self.stdout.write(self.style.SUCCESS('Data cleared successfully!')) |
||||
|
|
||||
|
# Step 1: Create Narrator Layers (Tabaqat) |
||||
|
self.stdout.write(self.style.SUCCESS('\n📚 Creating Narrator Layers...')) |
||||
|
layers_data = [ |
||||
|
{ |
||||
|
"name": "Sahaba (Companions)", |
||||
|
"number": 1, |
||||
|
"description": "The companions of Prophet Muhammad (PBUH) who heard directly from him." |
||||
|
}, |
||||
|
{ |
||||
|
"name": "Tabi'un (Successors)", |
||||
|
"number": 2, |
||||
|
"description": "Narrators who lived after the Prophet's era and heard from the companions." |
||||
|
}, |
||||
|
{ |
||||
|
"name": "Taba' Tabi'in (Followers of Successors)", |
||||
|
"number": 3, |
||||
|
"description": "Narrators who heard from the Successors." |
||||
|
}, |
||||
|
{ |
||||
|
"name": "Later Generations", |
||||
|
"number": 4, |
||||
|
"description": "Narrators from later Islamic centuries, known for their scholarship." |
||||
|
}, |
||||
|
{ |
||||
|
"name": "Modern Era Scholars", |
||||
|
"number": 5, |
||||
|
"description": "Contemporary scholars who have specialized knowledge of hadith narration." |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
layers = {} |
||||
|
for layer_data in layers_data: |
||||
|
layer, created = NarratorLayer.objects.get_or_create( |
||||
|
number=layer_data['number'], |
||||
|
defaults={ |
||||
|
'name': layer_data['name'], |
||||
|
'description': layer_data['description'], |
||||
|
'slug': slugify(layer_data['name']) |
||||
|
} |
||||
|
) |
||||
|
layers[layer_data['number']] = layer |
||||
|
status = '✓ Created' if created else '• Updated' |
||||
|
self.stdout.write(f"{status}: {layer.name} (Layer {layer.number})") |
||||
|
|
||||
|
# Step 2: Create Transmitters (Hadith Narrators) |
||||
|
self.stdout.write(self.style.SUCCESS('\n👥 Creating Transmitters...')) |
||||
|
transmitters_data = [ |
||||
|
{ |
||||
|
"full_name": "Abu Hurayrah", |
||||
|
"kunya": "Abu Hurayrah", |
||||
|
"known_as": "Abd al-Rahman ibn Sakhr", |
||||
|
"nickname": "Father of the Kitten", |
||||
|
"origin": "Yamama, Arabia", |
||||
|
"lived_in": "Medina, Syria", |
||||
|
"died_in": "Medina", |
||||
|
"birth_year_hijri": 7, |
||||
|
"death_year_hijri": 58, |
||||
|
"age_at_death": 78, |
||||
|
"generation": 1, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "sunni", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "One of the most prolific hadith narrators, reported 5,374 ahadith.", |
||||
|
"narrator_layer": 1, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Aisha bint Abu Bakr", |
||||
|
"kunya": "Umm al-Mu'minin", |
||||
|
"known_as": "Mother of the Believers", |
||||
|
"nickname": "Al-Siddiqa", |
||||
|
"origin": "Medina", |
||||
|
"lived_in": "Medina", |
||||
|
"died_in": "Medina", |
||||
|
"birth_year_hijri": None, |
||||
|
"death_year_hijri": 58, |
||||
|
"age_at_death": 66, |
||||
|
"generation": 1, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "sunni", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "Wife of the Prophet Muhammad (PBUH), a major source of hadith about daily life.", |
||||
|
"narrator_layer": 1, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Jabir ibn Abdullah al-Ansari", |
||||
|
"kunya": "Abu Abdullah", |
||||
|
"known_as": "Jabir", |
||||
|
"nickname": "Al-Ansari", |
||||
|
"origin": "Medina", |
||||
|
"lived_in": "Medina", |
||||
|
"died_in": "Medina", |
||||
|
"birth_year_hijri": 10, |
||||
|
"death_year_hijri": 74, |
||||
|
"age_at_death": 94, |
||||
|
"generation": 1, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "sunni", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "One of the long-lived companions, reported numerous ahadith on various topics.", |
||||
|
"narrator_layer": 1, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Imam Malik ibn Anas", |
||||
|
"kunya": "Abu Abdullah", |
||||
|
"known_as": "Malik", |
||||
|
"nickname": "Imam of Imams", |
||||
|
"origin": "Medina", |
||||
|
"lived_in": "Medina", |
||||
|
"died_in": "Medina", |
||||
|
"birth_year_hijri": 93, |
||||
|
"death_year_hijri": 179, |
||||
|
"age_at_death": 86, |
||||
|
"generation": 3, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "maliki", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "Founder of the Maliki school of Islamic jurisprudence, compiler of Al-Muwatta.", |
||||
|
"narrator_layer": 3, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Al-Qasim ibn Muhammad", |
||||
|
"kunya": "Abu Muhammad", |
||||
|
"known_as": "Al-Qasim", |
||||
|
"nickname": "Son of the Rightly Guided", |
||||
|
"origin": "Medina", |
||||
|
"lived_in": "Medina", |
||||
|
"died_in": "Medina", |
||||
|
"birth_year_hijri": 38, |
||||
|
"death_year_hijri": 106, |
||||
|
"age_at_death": 68, |
||||
|
"generation": 2, |
||||
|
"reliability": "reliable", |
||||
|
"madhhab": "sunni", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "Son of Amir al-Mu'minin, known for his knowledge of Islamic jurisprudence.", |
||||
|
"narrator_layer": 2, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Urwa ibn al-Zubayr", |
||||
|
"kunya": "Abu Abdullah", |
||||
|
"known_as": "Urwa", |
||||
|
"nickname": "The Jurist", |
||||
|
"origin": "Medina", |
||||
|
"lived_in": "Medina, Mecca", |
||||
|
"died_in": "Medina", |
||||
|
"birth_year_hijri": 23, |
||||
|
"death_year_hijri": 94, |
||||
|
"age_at_death": 71, |
||||
|
"generation": 2, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "sunni", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "Prominent Tabi'un scholar and transmitter of hadith from Aisha.", |
||||
|
"narrator_layer": 2, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Abdullah ibn Abbas", |
||||
|
"kunya": "Abu Abbas", |
||||
|
"known_as": "Ibn Abbas", |
||||
|
"nickname": "Hibr al-Ummah (The Learned Scholar of the Nation)", |
||||
|
"origin": "Medina", |
||||
|
"lived_in": "Medina, Mecca, Basra", |
||||
|
"died_in": "Taif", |
||||
|
"birth_year_hijri": 3, |
||||
|
"death_year_hijri": 68, |
||||
|
"age_at_death": 71, |
||||
|
"generation": 1, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "sunni", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "Cousin of the Prophet (PBUH), famous for Quranic exegesis and hadith knowledge.", |
||||
|
"narrator_layer": 1, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Nafi' (Mawla of Ibn Umar)", |
||||
|
"kunya": "Abu Abdullah", |
||||
|
"known_as": "Nafi'", |
||||
|
"nickname": "The Freed Slave", |
||||
|
"origin": "Ethiopia", |
||||
|
"lived_in": "Medina", |
||||
|
"died_in": "Medina", |
||||
|
"birth_year_hijri": 25, |
||||
|
"death_year_hijri": 117, |
||||
|
"age_at_death": 92, |
||||
|
"generation": 2, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "sunni", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "Freed slave of Abdullah ibn Umar, transmitted numerous hadith from him.", |
||||
|
"narrator_layer": 2, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Imam Ahmad ibn Hanbal", |
||||
|
"kunya": "Abu Abdullah", |
||||
|
"known_as": "Ahmad", |
||||
|
"nickname": "Shaykh al-Islam", |
||||
|
"origin": "Khorasan", |
||||
|
"lived_in": "Baghdad", |
||||
|
"died_in": "Baghdad", |
||||
|
"birth_year_hijri": 164, |
||||
|
"death_year_hijri": 241, |
||||
|
"age_at_death": 77, |
||||
|
"generation": 4, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "hanbali", |
||||
|
"in_sahih_muslim": False, |
||||
|
"in_sahih_bukhari": False, |
||||
|
"description": "Founder of the Hanbali school, compiler of Musnad Ahmad with 40,000+ hadith.", |
||||
|
"narrator_layer": 3, |
||||
|
}, |
||||
|
{ |
||||
|
"full_name": "Sufyan ibn Uyayna", |
||||
|
"kunya": "Abu Muhammad", |
||||
|
"known_as": "Sufyan", |
||||
|
"nickname": "Amir al-Mu'minin fil-Hadith", |
||||
|
"origin": "Kufa", |
||||
|
"lived_in": "Mecca, Kufa", |
||||
|
"died_in": "Mecca", |
||||
|
"birth_year_hijri": 107, |
||||
|
"death_year_hijri": 198, |
||||
|
"age_at_death": 91, |
||||
|
"generation": 3, |
||||
|
"reliability": "very_reliable", |
||||
|
"madhhab": "shafii", |
||||
|
"in_sahih_muslim": True, |
||||
|
"in_sahih_bukhari": True, |
||||
|
"description": "Great hadith scholar and judge, known for his exceptional memory.", |
||||
|
"narrator_layer": 3, |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
transmitters = {} |
||||
|
for trans_data in transmitters_data: |
||||
|
narrator_layer_num = trans_data.pop('narrator_layer') |
||||
|
narrator_layer = layers.get(narrator_layer_num) |
||||
|
|
||||
|
transmitter, created = Transmitters.objects.get_or_create( |
||||
|
full_name=trans_data['full_name'], |
||||
|
defaults=trans_data |
||||
|
) |
||||
|
transmitters[trans_data['full_name']] = transmitter |
||||
|
status = '✓ Created' if created else '• Updated' |
||||
|
self.stdout.write(f"{status}: {transmitter.full_name}") |
||||
|
|
||||
|
# Step 3: Create Transmitter Opinions |
||||
|
self.stdout.write(self.style.SUCCESS('\n💬 Creating Transmitter Opinions...')) |
||||
|
opinions_data = [ |
||||
|
{ |
||||
|
"transmitter_name": "Abu Hurayrah", |
||||
|
"scholar_name": "Imam al-Bukhari", |
||||
|
"opinion_text": "Abu Hurayrah is one of the most reliable narrators with a perfect memory and integrity.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Abu Hurayrah", |
||||
|
"scholar_name": "Imam Muslim", |
||||
|
"opinion_text": "His narrations are authentic and widely accepted in the Islamic jurisprudence.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Aisha bint Abu Bakr", |
||||
|
"scholar_name": "Imam al-Bukhari", |
||||
|
"opinion_text": "The Mother of the Believers is the most reliable source for hadith about the Prophet's household.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Jabir ibn Abdullah al-Ansari", |
||||
|
"scholar_name": "Ibn Hajar al-Asqalani", |
||||
|
"opinion_text": "His longevity allowed him to transmit from many companions and successors.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Imam Malik ibn Anas", |
||||
|
"scholar_name": "Imam ash-Shafi'i", |
||||
|
"opinion_text": "Malik is among the most knowledgeable of the Medinese scholars in jurisprudence.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Imam Malik ibn Anas", |
||||
|
"scholar_name": "Imam Ahmad ibn Hanbal", |
||||
|
"opinion_text": "Malik's narrations form the basis of sound Islamic jurisprudence.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Al-Qasim ibn Muhammad", |
||||
|
"scholar_name": "Ibn Hajar al-Asqalani", |
||||
|
"opinion_text": "Al-Qasim is a trustworthy narrator from the Tabi'un generation with reliable traditions.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Urwa ibn al-Zubayr", |
||||
|
"scholar_name": "Imam al-Bukhari", |
||||
|
"opinion_text": "Urwa is among the most knowledgeable about the traditions of the Prophet's household.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Abdullah ibn Abbas", |
||||
|
"scholar_name": "Imam at-Tirmidhi", |
||||
|
"opinion_text": "Ibn Abbas has exceptional knowledge in Quranic interpretation and hadith narration.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Nafi' (Mawla of Ibn Umar)", |
||||
|
"scholar_name": "Imam Muslim", |
||||
|
"opinion_text": "Nafi' is one of the most reliable freed slaves who transmitted authentic traditions.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Imam Ahmad ibn Hanbal", |
||||
|
"scholar_name": "Ibn Hajar al-Asqalani", |
||||
|
"opinion_text": "Ahmad ibn Hanbal's knowledge of hadith is unparalleled in his era.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Sufyan ibn Uyayna", |
||||
|
"scholar_name": "Imam al-Bukhari", |
||||
|
"opinion_text": "Sufyan is a highly reliable hadith scholar with exceptional memory.", |
||||
|
"status": "confirmed" |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
for opinion_data in opinions_data: |
||||
|
transmitter_name = opinion_data.pop('transmitter_name') |
||||
|
transmitter = transmitters.get(transmitter_name) |
||||
|
if transmitter: |
||||
|
opinion, created = TransmitterOpinion.objects.get_or_create( |
||||
|
transmitter=transmitter, |
||||
|
scholar_name=opinion_data['scholar_name'], |
||||
|
defaults=opinion_data |
||||
|
) |
||||
|
if created: |
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f"✓ Opinion added: {opinion_data['scholar_name']} on {transmitter_name}" |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
# Step 4: Create Original Texts |
||||
|
self.stdout.write(self.style.SUCCESS('\n📜 Creating Transmitter Original Texts...')) |
||||
|
original_texts_data = [ |
||||
|
{ |
||||
|
"transmitter_name": "Abu Hurayrah", |
||||
|
"title": "His Narration on Zakat", |
||||
|
"text": "حدثنا أبو هريرة قال: قال رسول الله صلى الله عليه وسلم: من آمن بالله واليوم الآخر فليؤد الزكاة", |
||||
|
"translation": [ |
||||
|
{"language_code": "en", "text": "Abu Hurayrah narrated: The Messenger of Allah (PBUH) said: Whoever believes in Allah and the Last Day, let him pay the Zakat (alms)."}, |
||||
|
{"language_code": "ar", "text": "أبو هريرة: من آمن بالله واليوم الآخر فليؤد الزكاة"} |
||||
|
], |
||||
|
"share_link": "https://hadith.example.com/abu-hurayrah/zakat-1" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Aisha bint Abu Bakr", |
||||
|
"title": "Her Account of the Prophet's Night Prayer", |
||||
|
"text": "قالت عائشة: كان النبي صلى الله عليه وسلم يقوم الليل فيصلي ثلاث عشرة ركعة", |
||||
|
"translation": [ |
||||
|
{"language_code": "en", "text": "Aisha said: The Prophet (PBUH) used to pray at night thirteen rak'ahs."}, |
||||
|
{"language_code": "ar", "text": "عائشة: كان النبي يقوم الليل بثلاث عشرة ركعة"} |
||||
|
], |
||||
|
"share_link": "https://hadith.example.com/aisha/night-prayer-1" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Jabir ibn Abdullah al-Ansari", |
||||
|
"title": "The Farewell Hajj Narration", |
||||
|
"text": "قال جابر: خرجنا مع رسول الله صلى الله عليه وسلم في حجة الوداع", |
||||
|
"translation": [ |
||||
|
{"language_code": "en", "text": "Jabir narrated: We went out with the Messenger of Allah (PBUH) for the Farewell Hajj."}, |
||||
|
{"language_code": "ar", "text": "جابر: خرجنا مع رسول الله في حجة الوداع"} |
||||
|
], |
||||
|
"share_link": "https://hadith.example.com/jabir/farewell-hajj-1" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Imam Malik ibn Anas", |
||||
|
"title": "Narration on Purity and Prayer", |
||||
|
"text": "قال مالك: الطهارة شرط من شروط الصلاة", |
||||
|
"translation": [ |
||||
|
{"language_code": "en", "text": "Malik said: Purification is a condition for the validity of prayer."}, |
||||
|
{"language_code": "ar", "text": "مالك: الطهارة من شروط صحة الصلاة"} |
||||
|
], |
||||
|
"share_link": "https://hadith.example.com/malik/purity-1" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Abdullah ibn Abbas", |
||||
|
"title": "His Commentary on Divine Justice", |
||||
|
"text": "قال ابن عباس: إن الله تعالى عدل لا يظلم أحدا", |
||||
|
"translation": [ |
||||
|
{"language_code": "en", "text": "Ibn Abbas said: Truly Allah is Just and does not oppress anyone."}, |
||||
|
{"language_code": "ar", "text": "ابن عباس: الله عدل لا يظلم أحدا"} |
||||
|
], |
||||
|
"share_link": "https://hadith.example.com/ibn-abbas/justice-1" |
||||
|
}, |
||||
|
{ |
||||
|
"transmitter_name": "Sufyan ibn Uyayna", |
||||
|
"title": "Teaching on Knowledge Seeking", |
||||
|
"text": "قال سفيان بن عيينة: طلب العلم فريضة على كل مسلم", |
||||
|
"translation": [ |
||||
|
{"language_code": "en", "text": "Sufyan ibn Uyayna said: Seeking knowledge is an obligation for every Muslim."}, |
||||
|
{"language_code": "ar", "text": "سفيان: طلب العلم فريضة على كل مسلم"} |
||||
|
], |
||||
|
"share_link": "https://hadith.example.com/sufyan/knowledge-1" |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
for text_data in original_texts_data: |
||||
|
transmitter_name = text_data.pop('transmitter_name') |
||||
|
transmitter = transmitters.get(transmitter_name) |
||||
|
if transmitter: |
||||
|
original_text, created = TransmitterOriginalText.objects.get_or_create( |
||||
|
transmitter=transmitter, |
||||
|
title=text_data['title'], |
||||
|
defaults=text_data |
||||
|
) |
||||
|
if created: |
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f"✓ Original text added: {text_data['title']} by {transmitter_name}" |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
# Step 5: Create Hadis Transmitters (Chain of narration) |
||||
|
self.stdout.write(self.style.SUCCESS('\n⛓️ Creating Hadis Transmitters (Chains)...')) |
||||
|
|
||||
|
# Sample hadis IDs to use (you can have any ID from 1800 to 1852) |
||||
|
hadis_ids = list(range(1800, 1853)) |
||||
|
|
||||
|
# Create chains for different hadis |
||||
|
chains_data = [ |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[0], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Abu Hurayrah", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Imam Malik ibn Anas", "order": 2, "layer": 3, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[1], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Aisha bint Abu Bakr", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Urwa ibn al-Zubayr", "order": 2, "layer": 2, "status": "reliable"}, |
||||
|
{"transmitter_name": "Imam Malik ibn Anas", "order": 3, "layer": 3, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[2], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Jabir ibn Abdullah al-Ansari", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Al-Qasim ibn Muhammad", "order": 2, "layer": 2, "status": "reliable"}, |
||||
|
{"transmitter_name": "Sufyan ibn Uyayna", "order": 3, "layer": 3, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[3], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Abdullah ibn Abbas", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Nafi' (Mawla of Ibn Umar)", "order": 2, "layer": 2, "status": "reliable"}, |
||||
|
{"transmitter_name": "Imam Ahmad ibn Hanbal", "order": 3, "layer": 3, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[4], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Abu Hurayrah", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Sufyan ibn Uyayna", "order": 2, "layer": 3, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[5], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Aisha bint Abu Bakr", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Al-Qasim ibn Muhammad", "order": 2, "layer": 2, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[6], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Jabir ibn Abdullah al-Ansari", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Nafi' (Mawla of Ibn Umar)", "order": 2, "layer": 2, "status": "reliable"}, |
||||
|
{"transmitter_name": "Imam Malik ibn Anas", "order": 3, "layer": 3, "status": "reliable"}, |
||||
|
{"transmitter_name": "Sufyan ibn Uyayna", "order": 4, "layer": 3, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[7], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Abdullah ibn Abbas", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Urwa ibn al-Zubayr", "order": 2, "layer": 2, "status": "reliable"}, |
||||
|
{"transmitter_name": "Imam Ahmad ibn Hanbal", "order": 3, "layer": 3, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[8], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Abu Hurayrah", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Al-Qasim ibn Muhammad", "order": 2, "layer": 2, "status": "reliable"}, |
||||
|
{"transmitter_name": "Imam Malik ibn Anas", "order": 3, "layer": 3, "status": "reliable"}, |
||||
|
{"transmitter_name": "Sufyan ibn Uyayna", "order": 4, "layer": 3, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
{ |
||||
|
"hadis_id": hadis_ids[9], |
||||
|
"chain": [ |
||||
|
{"transmitter_name": "Aisha bint Abu Bakr", "order": 1, "layer": 1, "status": "reliable"}, |
||||
|
{"transmitter_name": "Nafi' (Mawla of Ibn Umar)", "order": 2, "layer": 2, "status": "reliable"}, |
||||
|
] |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
hadis_transmitter_count = 0 |
||||
|
for chain_data in chains_data: |
||||
|
hadis_id = chain_data['hadis_id'] |
||||
|
chain = chain_data['chain'] |
||||
|
|
||||
|
for item in chain: |
||||
|
transmitter = transmitters.get(item['transmitter_name']) |
||||
|
layer = layers.get(item['layer']) |
||||
|
|
||||
|
if transmitter and layer: |
||||
|
hadis_trans, created = HadisTransmitter.objects.get_or_create( |
||||
|
hadis_id=hadis_id, |
||||
|
transmitter=transmitter, |
||||
|
order=item['order'], |
||||
|
defaults={ |
||||
|
'narrator_layer': layer, |
||||
|
'status': item['status'], |
||||
|
'is_gap': False |
||||
|
} |
||||
|
) |
||||
|
if created: |
||||
|
hadis_transmitter_count += 1 |
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f"✓ Chain link: Hadis {hadis_id} <- {item['transmitter_name']} (Order {item['order']})" |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f'\n✓ Successfully seeded transmitter data!' |
||||
|
) |
||||
|
) |
||||
|
self._print_summary(transmitters, hadis_transmitter_count) |
||||
|
|
||||
|
def _print_summary(self, transmitters, hadis_transmitter_count): |
||||
|
"""Print a summary of created data""" |
||||
|
self.stdout.write("\n" + "="*70) |
||||
|
self.stdout.write(self.style.SUCCESS("TRANSMITTER DATABASE SUMMARY")) |
||||
|
self.stdout.write("="*70) |
||||
|
|
||||
|
layers_count = NarratorLayer.objects.count() |
||||
|
transmitters_count = Transmitters.objects.count() |
||||
|
opinions_count = TransmitterOpinion.objects.count() |
||||
|
original_texts_count = TransmitterOriginalText.objects.count() |
||||
|
|
||||
|
self.stdout.write(f"📚 Narrator Layers: {layers_count}") |
||||
|
self.stdout.write(f"👥 Total Transmitters: {transmitters_count}") |
||||
|
self.stdout.write(f"💬 Transmitter Opinions: {opinions_count}") |
||||
|
self.stdout.write(f"📜 Original Texts: {original_texts_count}") |
||||
|
self.stdout.write(f"⛓️ Hadis Transmitter Chains: {hadis_transmitter_count}") |
||||
|
|
||||
|
self.stdout.write("\n" + "="*70) |
||||
|
self.stdout.write(self.style.WARNING("Notable Transmitters Created:")) |
||||
|
self.stdout.write("="*70) |
||||
|
for name in list(transmitters.keys())[:5]: |
||||
|
self.stdout.write(f" • {name}") |
||||
|
self.stdout.write(f" ... and {max(0, len(transmitters) - 5)} more") |
||||
|
self.stdout.write("="*70 + "\n") |
||||
@ -0,0 +1,276 @@ |
|||||
|
""" |
||||
|
Django management command to seed mock data for hadith book references. |
||||
|
Place this file in: yourapp/management/commands/seed_books.py |
||||
|
|
||||
|
Usage: python manage.py seed_books |
||||
|
""" |
||||
|
|
||||
|
import os |
||||
|
from pathlib import Path |
||||
|
from django.core.management.base import BaseCommand |
||||
|
from django.core.files.base import ContentFile |
||||
|
from django.utils.text import slugify |
||||
|
from apps.hadis.models.reference import ( |
||||
|
BookReference, |
||||
|
BookReferenceImage, |
||||
|
BookAuthor, |
||||
|
BookAttribute |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class Command(BaseCommand): |
||||
|
help = 'Seed the database with mock hadith book reference data' |
||||
|
|
||||
|
def add_arguments(self, parser): |
||||
|
parser.add_argument( |
||||
|
'--clear', |
||||
|
action='store_true', |
||||
|
help='Clear existing data before seeding', |
||||
|
) |
||||
|
|
||||
|
def handle(self, *args, **options): |
||||
|
if options['clear']: |
||||
|
self.stdout.write(self.style.WARNING('Clearing existing data...')) |
||||
|
BookAttribute.objects.all().delete() |
||||
|
BookReferenceImage.objects.all().delete() |
||||
|
BookAuthor.objects.all().delete() |
||||
|
BookReference.objects.all().delete() |
||||
|
self.stdout.write(self.style.SUCCESS('Data cleared successfully!')) |
||||
|
|
||||
|
# Create authors first |
||||
|
authors_data = [ |
||||
|
{"name": "Imam Muhammad al-Bukhari"}, |
||||
|
{"name": "Imam Muslim ibn al-Hajjaj"}, |
||||
|
{"name": "Imam Abu Dawood as-Sijistani"}, |
||||
|
{"name": "Imam At-Tirmidhi"}, |
||||
|
{"name": "Imam Ibn Majah"}, |
||||
|
{"name": "Imam Ahmad ibn Hanbal"}, |
||||
|
{"name": "Imam Al-Hakim"}, |
||||
|
{"name": "Imam Ad-Daraqutni"}, |
||||
|
] |
||||
|
|
||||
|
authors = {} |
||||
|
for author_data in authors_data: |
||||
|
author, created = BookAuthor.objects.get_or_create( |
||||
|
name=author_data['name'] |
||||
|
) |
||||
|
authors[author_data['name']] = author |
||||
|
if created: |
||||
|
self.stdout.write(self.style.SUCCESS(f'Created author: {author.name}')) |
||||
|
|
||||
|
# Create book references |
||||
|
books_data = [ |
||||
|
{ |
||||
|
"title": "Sahih al-Bukhari", |
||||
|
"description": "The most authentic collection of hadith, compiled by Imam Muhammad al-Bukhari. Contains 7,563 ahadith.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-009-6", |
||||
|
"volume": "9 volumes", |
||||
|
"year_of_publication": "1870", |
||||
|
"number_page": 1200, |
||||
|
"publisher": "Dar al-Kutub al-Ilmiyah", |
||||
|
"rate": 5.00, |
||||
|
"authors": ["Imam Muhammad al-Bukhari"], |
||||
|
"image_order": 1, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Hadith Compilation", |
||||
|
"Number of Hadith": "7,563", |
||||
|
"Classification": "6 Books", |
||||
|
"Authenticity Grade": "Sahih (Authentic)", |
||||
|
"Compilation Period": "16 years", |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"title": "Sahih Muslim", |
||||
|
"description": "Second most authentic hadith collection compiled by Imam Muslim ibn al-Hajjaj. Contains 9,200 traditions.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-010-2", |
||||
|
"volume": "5 volumes", |
||||
|
"year_of_publication": "1875", |
||||
|
"number_page": 1500, |
||||
|
"publisher": "Dar Ihya at-Turath al-Arabi", |
||||
|
"rate": 4.95, |
||||
|
"authors": ["Imam Muslim ibn al-Hajjaj"], |
||||
|
"image_order": 2, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Hadith Compilation", |
||||
|
"Number of Hadith": "9,200", |
||||
|
"Classification": "43 Books", |
||||
|
"Authenticity Grade": "Sahih (Authentic)", |
||||
|
"Unique Hadith": "Approximately 4,000", |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"title": "Sunan Abu Dawood", |
||||
|
"description": "A comprehensive collection of hadith containing jurisprudential material, compiled by Imam Abu Dawood as-Sijistani.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-011-9", |
||||
|
"volume": "4 volumes", |
||||
|
"year_of_publication": "1880", |
||||
|
"number_page": 1400, |
||||
|
"publisher": "Islamic Digital Library", |
||||
|
"rate": 4.80, |
||||
|
"authors": ["Imam Abu Dawood as-Sijistani"], |
||||
|
"image_order": 3, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Sunan (Practice)", |
||||
|
"Number of Hadith": "5,274", |
||||
|
"Focus": "Jurisprudential Traditions", |
||||
|
"Number of Books": "43", |
||||
|
"Authenticity Grade": "Hasan to Sahih", |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"title": "Jami' at-Tirmidhi", |
||||
|
"description": "A major collection of hadith compiled by Imam At-Tirmidhi with his commentary and grading of narrations.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-012-6", |
||||
|
"volume": "5 volumes", |
||||
|
"year_of_publication": "1892", |
||||
|
"number_page": 1350, |
||||
|
"publisher": "Dar ar-Risalah al-Alamiyah", |
||||
|
"rate": 4.85, |
||||
|
"authors": ["Imam At-Tirmidhi"], |
||||
|
"image_order": 4, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Jami (Comprehensive)", |
||||
|
"Number of Hadith": "3,956", |
||||
|
"Notable Feature": "Grades each hadith", |
||||
|
"Categories": "63 Chapters", |
||||
|
"Authenticity Grade": "Various Grades", |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"title": "Sunan Ibn Majah", |
||||
|
"description": "A collection of hadith compiled by Imam Ibn Majah, one of the Six Canonical Hadith Collections.", |
||||
|
"language": "Arabic", |
||||
|
"isbn": "978-1-86043-013-3", |
||||
|
"volume": "2 volumes", |
||||
|
"year_of_publication": "1888", |
||||
|
"number_page": 900, |
||||
|
"publisher": "Dar Ihya al-Kutub al-Arabiyah", |
||||
|
"rate": 4.75, |
||||
|
"authors": ["Imam Ibn Majah"], |
||||
|
"image_order": 5, |
||||
|
"attributes": { |
||||
|
"Collection Type": "Sunan (Practice)", |
||||
|
"Number of Hadith": "4,341", |
||||
|
"Number of Books": "32", |
||||
|
"Notable Content": "Includes rare narrations", |
||||
|
"Authenticity Grade": "Mixed - requires verification", |
||||
|
} |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
books = {} |
||||
|
for book_data in books_data: |
||||
|
# Extract author names |
||||
|
author_names = book_data.pop('authors', []) |
||||
|
image_order = book_data.pop('image_order', 1) |
||||
|
attributes_dict = book_data.pop('attributes', {}) |
||||
|
|
||||
|
# Create or get the book |
||||
|
book, created = BookReference.objects.get_or_create( |
||||
|
title=book_data['title'], |
||||
|
defaults=book_data |
||||
|
) |
||||
|
|
||||
|
if created: |
||||
|
self.stdout.write(self.style.SUCCESS(f'Created book: {book.title}')) |
||||
|
else: |
||||
|
# Update existing book |
||||
|
for key, value in book_data.items(): |
||||
|
setattr(book, key, value) |
||||
|
book.save() |
||||
|
self.stdout.write(self.style.WARNING(f'Updated book: {book.title}')) |
||||
|
|
||||
|
books[book.title] = book |
||||
|
|
||||
|
# Add authors to book |
||||
|
for author_name in author_names: |
||||
|
author = authors.get(author_name) |
||||
|
if author: |
||||
|
book.authors.add(author) |
||||
|
|
||||
|
# Add book image |
||||
|
image_path = self._get_image_path(image_order) |
||||
|
if image_path and os.path.exists(image_path): |
||||
|
# Check if image already exists for this book |
||||
|
if not book.images.exists(): |
||||
|
with open(image_path, 'rb') as img_file: |
||||
|
image_name = f'book{image_order}.png' |
||||
|
book_image = BookReferenceImage.objects.create( |
||||
|
book_reference=book, |
||||
|
order=1, |
||||
|
description=f"Cover image for {book.title}" |
||||
|
) |
||||
|
book_image.image.save( |
||||
|
image_name, |
||||
|
ContentFile(img_file.read()), |
||||
|
save=True |
||||
|
) |
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS(f'Added image to: {book.title}') |
||||
|
) |
||||
|
else: |
||||
|
self.stdout.write( |
||||
|
self.style.WARNING( |
||||
|
f'Image not found at {image_path} for {book.title}' |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
# Add attributes |
||||
|
for attr_title, attr_value in attributes_dict.items(): |
||||
|
attribute, created = BookAttribute.objects.get_or_create( |
||||
|
book_reference=book, |
||||
|
title=attr_title, |
||||
|
defaults={'value': attr_value} |
||||
|
) |
||||
|
if created: |
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f'Added attribute: {attr_title} to {book.title}' |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
self.stdout.write( |
||||
|
self.style.SUCCESS( |
||||
|
f'\n✓ Successfully seeded {len(books)} books with all relations!' |
||||
|
) |
||||
|
) |
||||
|
self._print_summary() |
||||
|
|
||||
|
def _get_image_path(self, book_number): |
||||
|
""" |
||||
|
Find the image file for the given book number. |
||||
|
Checks multiple possible locations. |
||||
|
""" |
||||
|
possible_paths = [ |
||||
|
Path('seeds/images') / f'book{book_number}.png', |
||||
|
Path('seed_data/images') / f'book{book_number}.png', |
||||
|
Path('static/images') / f'book{book_number}.png', |
||||
|
Path('.') / 'seeds' / 'images' / f'book{book_number}.png', |
||||
|
] |
||||
|
|
||||
|
for path in possible_paths: |
||||
|
if path.exists(): |
||||
|
return path |
||||
|
|
||||
|
return None |
||||
|
|
||||
|
def _print_summary(self): |
||||
|
"""Print a summary of created data""" |
||||
|
self.stdout.write("\n" + "="*60) |
||||
|
self.stdout.write(self.style.SUCCESS("DATABASE SUMMARY")) |
||||
|
self.stdout.write("="*60) |
||||
|
|
||||
|
books_count = BookReference.objects.count() |
||||
|
authors_count = BookAuthor.objects.count() |
||||
|
images_count = BookReferenceImage.objects.count() |
||||
|
attributes_count = BookAttribute.objects.count() |
||||
|
|
||||
|
self.stdout.write(f"📚 Total Books: {books_count}") |
||||
|
self.stdout.write(f"✍️ Total Authors: {authors_count}") |
||||
|
self.stdout.write(f"🖼️ Total Images: {images_count}") |
||||
|
self.stdout.write(f"🏷️ Total Attributes: {attributes_count}") |
||||
|
self.stdout.write("="*60 + "\n") |
||||
|
After Width: 126 | Height: 186 | Size: 16 KiB |
|
After Width: 126 | Height: 186 | Size: 59 KiB |
|
After Width: 126 | Height: 186 | Size: 16 KiB |
|
After Width: 126 | Height: 186 | Size: 8.8 KiB |
|
After Width: 126 | Height: 186 | Size: 16 KiB |
Write
Preview
Loading…
Cancel
Save
Reference in new issue