import uuid import random from datetime import date, timedelta from django.core.management.base import BaseCommand from django.utils import timezone from faker import Faker from recruitment.models import JobPosting, Candidate, Source, FormTemplate class Command(BaseCommand): help = 'Seeds the database with initial JobPosting and Candidate data using Faker.' def add_arguments(self, parser): # Add argument for the number of jobs to create, default is 5 parser.add_argument( '--jobs', type=int, help='The number of JobPostings to create.', default=5, ) # Add argument for the number of candidates to create, default is 20 parser.add_argument( '--candidates', type=int, help='The number of Candidate applications to create.', default=20, ) def handle(self, *args, **options): # Get the desired counts from command line arguments jobs_count = options['jobs'] candidates_count = options['candidates'] # Initialize Faker fake = Faker('en_US') # Using en_US for general data, can be changed if needed self.stdout.write("--- Starting Database Seeding ---") self.stdout.write(f"Preparing to create {jobs_count} jobs and {candidates_count} candidates.") # 1. Clear existing data (Optional, but useful for clean seeding) Candidate.objects.all().delete() JobPosting.objects.all().delete() Source.objects.all().delete() self.stdout.write(self.style.WARNING("Existing JobPostings and Candidates cleared.")) # 2. Create Foreign Key dependency: Source default_source, created = Source.objects.get_or_create( name="Career Website", defaults={'name': 'Career Website'} ) self.stdout.write(f"Using Source: {default_source.name}") # --- Helper Chooser Lists --- JOB_TYPES = [choice[0] for choice in JobPosting.JOB_TYPES] WORKPLACE_TYPES = [choice[0] for choice in JobPosting.WORKPLACE_TYPES] STATUS_CHOICES = [choice[0] for choice in JobPosting.STATUS_CHOICES] DEPARTMENTS = ["Technology", "Marketing", "Finance", "HR", "Sales", "Research", "Operations"] REPORTING_TO = ["CTO", "HR Manager", "Department Head", "VP of Sales"] # 3. Generate JobPostings created_jobs = [] for i in range(jobs_count): # Dynamic job details title = fake.job() department = random.choice(DEPARTMENTS) is_faculty = random.random() < 0.1 # 10% chance of being a faculty job job_type = "FACULTY" if is_faculty else random.choice([t for t in JOB_TYPES if t != "FACULTY"]) # Generate realistic salary range base_salary = random.randint(50, 200) * 1000 salary_range = f"${base_salary:,.0f} - ${base_salary + random.randint(10, 50) * 1000:,.0f}" # Random dates start_date = fake.date_object() deadline_date = start_date + timedelta(days=random.randint(14, 60)) joining_date = deadline_date + timedelta(days=random.randint(30, 90)) # Use Faker's HTML generation for CKEditor5 fields description_html = f"
{fake.paragraph(nb_sentences=3, variable_nb_sentences=True)}
" for _ in range(3)) qualifications_html = "Standard benefits include: {fake.sentence(nb_words=8)}
" instructions_html = f"To apply, visit: {fake.url()} and follow the steps below.
" job_data = { "title": title, "department": department, "job_type": job_type, "workplace_type": random.choice(WORKPLACE_TYPES), "location_city": fake.city(), "location_state": fake.state_abbr(), "location_country": "Saudia Arabia", "description": description_html, "qualifications": qualifications_html, "salary_range": salary_range, "benefits": benefits_html, "application_url": fake.url(), "application_start_date": start_date, "application_deadline": deadline_date, "application_instructions": instructions_html, "created_by": "Faker Script", "status": random.choice(STATUS_CHOICES), "hash_tags": f"#{department.lower().replace(' ', '')},#jobopening,#{fake.word()}", "position_number": f"{department[:3].upper()}{random.randint(100, 999)}", "reporting_to": random.choice(REPORTING_TO), "joining_date": joining_date, "open_positions": random.randint(1, 5), "source": default_source, "published_at": timezone.now() if random.random() < 0.7 else None, } job = JobPosting.objects.create( **job_data ) FormTemplate.objects.create(job=job, name=f"{job.title} Form", description=f"Form for {job.title}",is_active=True) created_jobs.append(job) self.stdout.write(self.style.SUCCESS(f'Created JobPosting {i+1}/{jobs_count}: {job.title}')) # 4. Generate Candidates if created_jobs: for i in range(candidates_count): # Link candidate to a random job target_job = random.choice(created_jobs) first_name = fake.first_name() last_name = fake.last_name() candidate_data = { "first_name": first_name, "last_name": last_name, # Create a plausible email based on name "email": f"{first_name.lower()}.{last_name.lower()}@{fake.domain_name()}", "phone": fake.phone_number(), "address": fake.address(), # Placeholder resume path 'match_score': random.randint(0, 100), "resume": f"resumes/{last_name.lower()}_{target_job.internal_job_id}_{fake.file_name(extension='pdf')}", "job": target_job, } Candidate.objects.create(**candidate_data) self.stdout.write(self.style.NOTICE( f'Created Candidate {i+1}/{candidates_count}: {first_name} for {target_job.title[:30]}...' )) else: self.stdout.write(self.style.WARNING("No jobs created, skipping candidate generation.")) self.stdout.write(self.style.SUCCESS('\n--- Database Seeding Complete! ---')) # Summary output self.stdout.write(f"Total JobPostings created: {JobPosting.objects.count()}") self.stdout.write(f"Total Candidates created: {Candidate.objects.count()}")