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."))