import random import time from django.core.management.base import BaseCommand from django.db import transaction from django.db.models import Q # REPLACE 'your_app' with your actual app name from apps.hadis.models import Hadis, Transmitters, NarratorLayer, HadisTransmitter class Command(BaseCommand): help = 'Seeds HadisTransmitter instances with specific constraints' def handle(self, *args, **options): self.stdout.write("Starting HadisTransmitter seeding...") # --------------------------------------------------------- # 1. Fetch the specific Objects # --------------------------------------------------------- layers = list(NarratorLayer.objects.filter(id__range=(11, 15))) transmitters = list(Transmitters.objects.filter(id__range=(84, 91))) # Hadis query hadis_qs = Hadis.objects.filter( Q(id__range=(1800, 1852)) | Q(id__range=(1877, 1889)) ) # --------------------------------------------------------- # 2. Validation # --------------------------------------------------------- if len(layers) < 2: self.stdout.write(self.style.ERROR(f"Need at least 2 NarratorLayers to satisfy constraints, but found {len(layers)}.")) return if not transmitters: self.stdout.write(self.style.ERROR("No Transmitters found in range 84-91.")) return if not hadis_qs.exists(): self.stdout.write(self.style.ERROR("No Hadis found in the specified ranges.")) return total_hadis = hadis_qs.count() self.stdout.write(f"Found {len(layers)} Layers, {len(transmitters)} Transmitters, and {total_hadis} Hadis.") # --------------------------------------------------------- # 3. Creation Loop # --------------------------------------------------------- created_count = 0 self.stdout.write("Beginning processing...") for i, hadis in enumerate(hadis_qs, 1): # Print progress every 5 items so you know it's not frozen if i % 5 == 0: self.stdout.write(f"Processing {i}/{total_hadis} (Hadis ID: {hadis.id})...") # Wrap PER ITEM in transaction to avoid long db locks with transaction.atomic(): # CONSTRAINT 1: Each hadis must have 3-4 transmitters chain_length = random.randint(3, 4) if len(transmitters) < chain_length: self.stdout.write(self.style.WARNING(f"Not enough transmitters. Skipping Hadis {hadis.id}.")) continue # Pick unique transmitters selected_transmitters = random.sample(transmitters, chain_length) # CONSTRAINT 2: Transmitters must be separated to at least 2 narrator layers # LOGIC FIX: Instead of a while loop, we force the condition explicitly. # Step A: Pick 2 DISTINCT layers guaranteed guaranteed_layers = random.sample(layers, 2) # Step B: Fill the remaining slots (1 or 2 slots) with random layers remaining_slots = chain_length - 2 other_layers = [random.choice(layers) for _ in range(remaining_slots)] # Step C: Combine and Shuffle so the distinct ones aren't always first final_layers = guaranteed_layers + other_layers random.shuffle(final_layers) # Create the connections for index, transmitter in enumerate(selected_transmitters): HadisTransmitter.objects.create( hadis=hadis, transmitter=transmitter, narrator_layer=final_layers[index], order=index, status=transmitter.reliability if hasattr(transmitter, 'reliability') else None ) created_count += 1 self.stdout.write(self.style.SUCCESS(f"Done! Successfully created {created_count} HadisTransmitter instances."))