import json import os import shutil from django.core.management.base import BaseCommand from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.core.files.temp import NamedTemporaryFile from django.core.files import File import requests from parks.models import Park from rides.models import Ride, RollerCoasterStats from companies.models import Company, Manufacturer from reviews.models import Review from media.models import Photo from django.contrib.auth.models import Permission from datetime import datetime, timedelta import secrets User = get_user_model() # Park coordinates mapping PARK_COORDINATES = { "Walt Disney World Magic Kingdom": { "latitude": "28.418778", "longitude": "-81.581212", "street_address": "1180 Seven Seas Dr", "city": "Orlando", "state": "Florida", "postal_code": "32836" }, "Cedar Point": { "latitude": "41.482207", "longitude": "-82.683523", "street_address": "1 Cedar Point Dr", "city": "Sandusky", "state": "Ohio", "postal_code": "44870" }, "Universal's Islands of Adventure": { "latitude": "28.470891", "longitude": "-81.471756", "street_address": "6000 Universal Blvd", "city": "Orlando", "state": "Florida", "postal_code": "32819" }, "Alton Towers": { "latitude": "52.988889", "longitude": "-1.892778", "street_address": "Farley Ln", "city": "Alton", "state": "Staffordshire", "postal_code": "ST10 4DB" }, "Europa-Park": { "latitude": "48.266031", "longitude": "7.722044", "street_address": "Europa-Park-Straße 2", "city": "Rust", "state": "Baden-Württemberg", "postal_code": "77977" } } class Command(BaseCommand): help = "Seeds the database with initial data" def handle(self, *args, **kwargs): self.stdout.write("Starting database seed...") # Clean up media directory self.stdout.write("Cleaning up media directory...") media_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'media') if os.path.exists(media_dir): for item in os.listdir(media_dir): if item != '__init__.py': # Preserve __init__.py item_path = os.path.join(media_dir, item) if os.path.isdir(item_path): shutil.rmtree(item_path) else: os.remove(item_path) # Delete all existing data self.stdout.write("Deleting existing data...") User.objects.exclude(username='admin').delete() # Delete all users except admin Park.objects.all().delete() Ride.objects.all().delete() Company.objects.all().delete() Manufacturer.objects.all().delete() Review.objects.all().delete() Photo.objects.all().delete() # Create users and set permissions self.create_users() self.setup_permissions() # Create parks and rides self.stdout.write("Creating parks and rides from seed data...") self.create_companies() self.create_manufacturers() self.create_parks_and_rides() # Create reviews self.stdout.write("Creating reviews...") self.create_reviews() self.stdout.write("Successfully seeded database") def setup_permissions(self): """Set up photo permissions for all users""" self.stdout.write("Setting up photo permissions...") # Get photo permissions photo_content_type = ContentType.objects.get_for_model(Photo) photo_permissions = Permission.objects.filter(content_type=photo_content_type) # Update all users users = User.objects.all() for user in users: for perm in photo_permissions: user.user_permissions.add(perm) user.save() self.stdout.write(f"Updated permissions for user: {user.username}") def create_users(self): self.stdout.write("Creating users...") # Try to get admin user try: admin = User.objects.get(username="admin") self.stdout.write("Admin user exists, updating permissions...") except User.DoesNotExist: admin = User.objects.create_superuser("admin", "admin@example.com", "admin") self.stdout.write("Created admin user") # Create 10 regular users usernames = [ "thrillseeker1", "coasterrider2", "parkfan3", "adventurer4", "funseeker5", "parkexplorer6", "ridetester7", "themepark8", "coaster9", "parkvisitor10" ] for username in usernames: User.objects.create_user( username=username, email=f"{username}@example.com", [PASSWORD-REMOVED]", ) self.stdout.write(f"Created user: {username}") def create_companies(self): self.stdout.write("Creating companies...") companies = [ "The Walt Disney Company", "Cedar Fair", "NBCUniversal", "Merlin Entertainments", "Mack Rides", ] for name in companies: Company.objects.create(name=name) self.stdout.write(f"Created company: {name}") def create_manufacturers(self): self.stdout.write("Creating manufacturers...") manufacturers = [ "Walt Disney Imagineering", "Bolliger & Mabillard", "Intamin", "Rocky Mountain Construction", "Vekoma", "Mack Rides", "Oceaneering International", ] for name in manufacturers: Manufacturer.objects.create(name=name) self.stdout.write(f"Created manufacturer: {name}") def download_image(self, url): """Download image from URL and return as Django File object""" response = requests.get(url) if response.status_code == 200: img_temp = NamedTemporaryFile(delete=True) img_temp.write(response.content) img_temp.flush() return File(img_temp) return None def create_parks_and_rides(self): # Load seed data with open(os.path.join(os.path.dirname(__file__), "seed_data.json")) as f: data = json.load(f) for park_data in data["parks"]: try: # Create park with location data park_coords = PARK_COORDINATES[park_data["name"]] park = Park.objects.create( name=park_data["name"], country=park_data["country"], opening_date=park_data["opening_date"], status=park_data["status"], description=park_data["description"], website=park_data["website"], owner=Company.objects.get(name=park_data["owner"]), size_acres=park_data["size_acres"], # Add location fields latitude=park_coords["latitude"], longitude=park_coords["longitude"], street_address=park_coords["street_address"], city=park_coords["city"], state=park_coords["state"], postal_code=park_coords["postal_code"] ) # Add park photos for photo_url in park_data["photos"]: img_file = self.download_image(photo_url) if img_file: Photo.objects.create( image=img_file, content_type=ContentType.objects.get_for_model(park), object_id=park.id, is_primary=True, # First photo is primary ) # Create rides for ride_data in park_data["rides"]: ride = Ride.objects.create( name=ride_data["name"], park=park, category=ride_data["category"], opening_date=ride_data["opening_date"], status=ride_data["status"], manufacturer=Manufacturer.objects.get( name=ride_data["manufacturer"] ), description=ride_data["description"], ) # Add ride photos for photo_url in ride_data["photos"]: img_file = self.download_image(photo_url) if img_file: Photo.objects.create( image=img_file, content_type=ContentType.objects.get_for_model(ride), object_id=ride.id, is_primary=True, # First photo is primary ) # Add coaster stats if present if "stats" in ride_data: RollerCoasterStats.objects.create( ride=ride, height_ft=ride_data["stats"]["height_ft"], length_ft=ride_data["stats"]["length_ft"], speed_mph=ride_data["stats"]["speed_mph"], inversions=ride_data["stats"]["inversions"], ride_time_seconds=ride_data["stats"]["ride_time_seconds"], ) self.stdout.write(f"Created park and rides: {park.name}") except Exception as e: self.stdout.write(self.style.ERROR(f"Error creating park {park_data['name']}: {str(e)}")) continue def create_reviews(self): users = list(User.objects.exclude(username="admin")) parks = list(Park.objects.all()) # Generate random dates within the last year today = datetime.now().date() one_year_ago = today - timedelta(days=365) for park in parks: # Create 3-5 reviews per park num_reviews = secrets.SystemRandom().randint(3, 5) for _ in range(num_reviews): # Generate random visit date days_offset = secrets.SystemRandom().randint(0, 365) visit_date = one_year_ago + timedelta(days=days_offset) Review.objects.create( user=secrets.choice(users), content_type=ContentType.objects.get_for_model(park), object_id=park.id, title=f"Great experience at {park.name}", content="Lorem ipsum dolor sit amet, consectetur adipiscing elit.", rating=secrets.SystemRandom().randint(7, 10), visit_date=visit_date, ) self.stdout.write(f"Created reviews for {park.name}")