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.
 
 

93 lines
4.3 KiB

import random
from django.core.management.base import BaseCommand
from django.db import transaction
# REPLACE 'your_app' with your actual app name
from apps.hadis.models import Hadis, Transmitters, NarratorLayer, HadisTransmitter
class Command(BaseCommand):
help = 'Seeds HadisTransmitters: Multiple layers per Hadis, each with an independent chain of 5+ transmitters.'
def handle(self, *args, **options):
self.stdout.write("Starting Global HadisTransmitter seeding (Layer-based Parallel Chains)...")
# 1. Fetch Objects
layers = list(NarratorLayer.objects.all())
transmitters = list(Transmitters.objects.all())
hadis_qs = Hadis.objects.all()
# 2. Critical Validation
# We need enough pool size. Minimum requirement: 2 layers * 5 transmitters = 10 unique people.
if len(layers) < 2:
self.stdout.write(self.style.ERROR(f"Error: Need at least 2 NarratorLayers, found {len(layers)}."))
return
# If you haven't run the transmitter seeder yet, this might fail.
if len(transmitters) < 10:
self.stdout.write(self.style.ERROR(
f"Error: Found only {len(transmitters)} transmitters. "
"To satisfy '2 layers x 5 transmitters', you need at least 10 unique transmitters. "
"Please run the transmitter seeder command first."
))
return
if not hadis_qs.exists():
self.stdout.write(self.style.ERROR("No Hadis found."))
return
total_hadis = hadis_qs.count()
self.stdout.write(f"Found {len(layers)} Layers, {len(transmitters)} Transmitters. Processing {total_hadis} Hadiths...")
# 3. Processing
created_links_count = 0
for i, hadis in enumerate(hadis_qs, 1):
if i % 50 == 0:
self.stdout.write(f"Processing {i}/{total_hadis}...")
with transaction.atomic():
# A. Wipe existing connections for a clean slate
HadisTransmitter.objects.filter(hadis=hadis).delete()
# B. Determine Structure
# Constraint: At least 2-3 layers
num_layers_to_use = random.randint(2, 3)
# Don't try to use more layers than exist in DB
num_layers_to_use = min(num_layers_to_use, len(layers))
selected_layers = random.sample(layers, num_layers_to_use)
# Constraint: At least 5 transmitters per layer (let's say 5 to 7)
# We calculate total needed first to ensure we pick UNIQUE people for this specific Hadith
counts_per_layer = [random.randint(5, 7) for _ in range(num_layers_to_use)]
total_needed = sum(counts_per_layer)
# Safety: Ensure we don't ask for more than we have in the whole DB
if total_needed > len(transmitters):
self.stdout.write(self.style.WARNING(f"Hadis {hadis.id}: Not enough total transmitters for {num_layers_to_use} layers. Skipping."))
continue
# C. Select Transmitters
# We pick a unique pool for this Hadith so the same person isn't in 2 layers
pool = random.sample(transmitters, total_needed)
# D. Distribute and Create
cursor = 0
for layer_idx, layer in enumerate(selected_layers):
count = counts_per_layer[layer_idx]
# Slice the pool for this layer
layer_group = pool[cursor : cursor + count]
cursor += count
# Create Links with Independent Ordering (0, 1, 2...) for THIS layer
for order_index, transmitter in enumerate(layer_group):
HadisTransmitter.objects.create(
hadis=hadis,
transmitter=transmitter,
narrator_layer=layer,
order=order_index, # Resets to 0 for every layer!
status=transmitter.reliability if hasattr(transmitter, 'reliability') else None
)
created_links_count += 1
self.stdout.write(self.style.SUCCESS(f"Done! Created {created_links_count} connections."))