mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 22:31:07 -05:00
- Cleaned up and standardized assertions in ApiTestMixin for API response validation. - Updated ASGI settings to use os.environ for setting the DJANGO_SETTINGS_MODULE. - Removed unused imports and improved formatting in settings.py. - Refactored URL patterns in urls.py for better readability and organization. - Enhanced view functions in views.py for consistency and clarity. - Added .flake8 configuration for linting and style enforcement. - Introduced type stubs for django-environ to improve type checking with Pylance.
1174 lines
50 KiB
Python
1174 lines
50 KiB
Python
from django.core.management.base import BaseCommand
|
|
from django.db import transaction, connection
|
|
import logging
|
|
|
|
from parks.models import Company, Park, ParkArea, ParkReview, ParkLocation
|
|
from rides.models import (
|
|
Company as RideCompany,
|
|
Ride,
|
|
RideModel,
|
|
RideReview,
|
|
RollerCoasterStats,
|
|
)
|
|
from accounts.models import User
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "Seeds comprehensive sample data for the ThrillWiki theme park application"
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.logger = logging.getLogger(__name__)
|
|
|
|
def cleanup_existing_data(self):
|
|
"""Clean up all existing sample data before creating new data"""
|
|
self.stdout.write("Cleaning up existing sample data...")
|
|
|
|
try:
|
|
with transaction.atomic():
|
|
# Count existing data for logging
|
|
park_review_count = ParkReview.objects.count()
|
|
ride_review_count = RideReview.objects.count()
|
|
rollercoaster_stats_count = RollerCoasterStats.objects.count()
|
|
ride_count = Ride.objects.count()
|
|
ride_model_count = RideModel.objects.count()
|
|
park_area_count = ParkArea.objects.count()
|
|
park_location_count = ParkLocation.objects.count()
|
|
park_count = Park.objects.count()
|
|
ride_company_count = RideCompany.objects.count()
|
|
company_count = Company.objects.count()
|
|
test_user_count = User.objects.filter(username="testuser").count()
|
|
|
|
# Log what will be deleted
|
|
self.stdout.write(f" Found {park_review_count} park reviews to delete")
|
|
self.stdout.write(f" Found {ride_review_count} ride reviews to delete")
|
|
self.stdout.write(
|
|
f" Found {rollercoaster_stats_count} roller coaster stats to delete"
|
|
)
|
|
self.stdout.write(f" Found {ride_count} rides to delete")
|
|
self.stdout.write(f" Found {ride_model_count} ride models to delete")
|
|
self.stdout.write(f" Found {park_area_count} park areas to delete")
|
|
self.stdout.write(
|
|
f" Found {park_location_count} park locations to delete"
|
|
)
|
|
self.stdout.write(f" Found {park_count} parks to delete")
|
|
self.stdout.write(
|
|
f" Found {ride_company_count} ride companies to delete"
|
|
)
|
|
self.stdout.write(f" Found {company_count} park companies to delete")
|
|
self.stdout.write(f" Found {test_user_count} test users to delete")
|
|
|
|
# Delete in order to avoid foreign key constraint violations
|
|
# Reviews first (they reference other objects)
|
|
if park_review_count > 0:
|
|
ParkReview.objects.all().delete()
|
|
self.stdout.write(f" Deleted {park_review_count} park reviews")
|
|
|
|
if ride_review_count > 0:
|
|
RideReview.objects.all().delete()
|
|
self.stdout.write(f" Deleted {ride_review_count} ride reviews")
|
|
|
|
# Roller coaster stats (references Ride)
|
|
if rollercoaster_stats_count > 0:
|
|
RollerCoasterStats.objects.all().delete()
|
|
self.stdout.write(
|
|
f" Deleted {rollercoaster_stats_count} roller coaster stats"
|
|
)
|
|
|
|
# Rides (references Park, RideCompany, RideModel)
|
|
if ride_count > 0:
|
|
Ride.objects.all().delete()
|
|
self.stdout.write(f" Deleted {ride_count} rides")
|
|
|
|
# Ride models (referenced by Ride)
|
|
if ride_model_count > 0:
|
|
RideModel.objects.all().delete()
|
|
self.stdout.write(f" Deleted {ride_model_count} ride models")
|
|
|
|
# Park areas (references Park)
|
|
if park_area_count > 0:
|
|
ParkArea.objects.all().delete()
|
|
self.stdout.write(f" Deleted {park_area_count} park areas")
|
|
|
|
# Park locations (references Park)
|
|
if park_location_count > 0:
|
|
ParkLocation.objects.all().delete()
|
|
self.stdout.write(f" Deleted {park_location_count} park locations")
|
|
|
|
# Parks (referenced by many models)
|
|
if park_count > 0:
|
|
Park.objects.all().delete()
|
|
self.stdout.write(f" Deleted {park_count} parks")
|
|
|
|
# Ride companies (referenced by Ride, RideModel)
|
|
if ride_company_count > 0:
|
|
RideCompany.objects.all().delete()
|
|
self.stdout.write(f" Deleted {ride_company_count} ride companies")
|
|
|
|
# Park companies (referenced by Park)
|
|
if company_count > 0:
|
|
Company.objects.all().delete()
|
|
self.stdout.write(f" Deleted {company_count} park companies")
|
|
|
|
# Only delete test user, not all users
|
|
if test_user_count > 0:
|
|
User.objects.filter(username="testuser").delete()
|
|
self.stdout.write(f" Deleted {test_user_count} test users")
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS("Successfully cleaned up existing sample data!")
|
|
)
|
|
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f"Error during data cleanup: {
|
|
str(e)}",
|
|
exc_info=True,
|
|
)
|
|
self.stdout.write(
|
|
self.style.ERROR(f"Failed to clean up existing data: {str(e)}")
|
|
)
|
|
raise
|
|
|
|
def handle(self, *args, **options):
|
|
self.stdout.write("Starting sample data creation...")
|
|
|
|
try:
|
|
# Check if required tables exist
|
|
if not self.check_required_tables():
|
|
self.stdout.write(
|
|
self.style.ERROR(
|
|
"Required database tables are missing. Please run migrations first."
|
|
)
|
|
)
|
|
return
|
|
|
|
# Clean up existing data first
|
|
self.cleanup_existing_data()
|
|
|
|
# Use transaction to ensure data consistency
|
|
with transaction.atomic():
|
|
# Create companies with different roles
|
|
self.create_companies()
|
|
|
|
# Create parks with proper operator relationships
|
|
self.create_parks()
|
|
|
|
# Create rides with manufacturer and designer relationships
|
|
self.create_rides()
|
|
|
|
# Add park areas for variety
|
|
self.create_park_areas()
|
|
|
|
# Add sample reviews for testing
|
|
self.create_reviews()
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS("Successfully created comprehensive sample data!")
|
|
)
|
|
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f"Error during sample data creation: {str(e)}", exc_info=True
|
|
)
|
|
self.stdout.write(
|
|
self.style.ERROR(f"Failed to create sample data: {str(e)}")
|
|
)
|
|
raise
|
|
|
|
def check_required_tables(self):
|
|
"""Check if all required tables exist in the database"""
|
|
required_models = [
|
|
Company,
|
|
Park,
|
|
ParkArea,
|
|
ParkReview,
|
|
ParkLocation,
|
|
RideCompany,
|
|
Ride,
|
|
RideModel,
|
|
RideReview,
|
|
RollerCoasterStats,
|
|
User,
|
|
]
|
|
|
|
missing_tables = []
|
|
for model in required_models:
|
|
try:
|
|
# Check if the table exists by trying to get the table name
|
|
table_name = model._meta.db_table
|
|
with connection.cursor() as cursor:
|
|
cursor.execute(f"SELECT 1 FROM {table_name} LIMIT 1")
|
|
except Exception:
|
|
missing_tables.append(model._meta.label)
|
|
|
|
if missing_tables:
|
|
self.stdout.write(
|
|
self.style.WARNING(
|
|
f'Missing tables for models: {", ".join(missing_tables)}'
|
|
)
|
|
)
|
|
return False
|
|
|
|
self.stdout.write(self.style.SUCCESS("All required tables exist."))
|
|
return True
|
|
|
|
def create_companies(self):
|
|
"""Create companies with different roles (operators, manufacturers, designers)"""
|
|
self.stdout.write("Creating companies...")
|
|
|
|
try:
|
|
# Park Operators
|
|
operators_data = [
|
|
{
|
|
"name": "The Walt Disney Company",
|
|
"roles": ["OPERATOR"],
|
|
"website": "https://www.disney.com/",
|
|
"description": "World's largest entertainment company and theme park operator.",
|
|
"founded_year": 1923,
|
|
},
|
|
{
|
|
"name": "Universal Parks & Resorts",
|
|
"roles": ["OPERATOR"],
|
|
"website": "https://www.universalparks.com/",
|
|
"description": "Division of Comcast NBCUniversal, operating major theme parks worldwide.",
|
|
"founded_year": 1964,
|
|
},
|
|
{
|
|
"name": "Six Flags Entertainment Corporation",
|
|
"roles": ["OPERATOR"],
|
|
"website": "https://www.sixflags.com/",
|
|
"description": "World's largest regional theme park company.",
|
|
"founded_year": 1961,
|
|
},
|
|
{
|
|
"name": "Cedar Fair Entertainment Company",
|
|
"roles": ["OPERATOR"],
|
|
"website": "https://www.cedarfair.com/",
|
|
"description": "One of North America's largest operators of regional amusement parks.",
|
|
"founded_year": 1983,
|
|
},
|
|
{
|
|
"name": "Herschend Family Entertainment",
|
|
"roles": ["OPERATOR"],
|
|
"website": "https://www.hfecorp.com/",
|
|
"description": "Largest family-owned themed attractions corporation in the United States.",
|
|
"founded_year": 1950,
|
|
},
|
|
{
|
|
"name": "Europa-Park GmbH & Co. Mack KG",
|
|
"roles": ["OPERATOR"],
|
|
"website": "https://www.europapark.de/",
|
|
"description": "One of Europe's largest theme parks, located in Germany.",
|
|
"founded_year": 1975,
|
|
},
|
|
]
|
|
|
|
# Ride Manufacturers
|
|
manufacturers_data = [
|
|
{
|
|
"name": "Bolliger & Mabillard",
|
|
"roles": ["MANUFACTURER"],
|
|
"website": "https://www.bolliger-mabillard.com/",
|
|
"description": "Swiss roller coaster manufacturer known for inverted and hyper coasters.",
|
|
"founded_date": "1988-01-01",
|
|
},
|
|
{
|
|
"name": "Intamin Amusement Rides",
|
|
"roles": ["MANUFACTURER"],
|
|
"website": "https://www.intamin.com/",
|
|
"description": "Liechtenstein-based manufacturer of roller coasters and thrill rides.",
|
|
"founded_date": "1967-01-01",
|
|
},
|
|
{
|
|
"name": "Vekoma Rides Manufacturing",
|
|
"roles": ["MANUFACTURER"],
|
|
"website": "https://www.vekoma.com/",
|
|
"description": "Dutch manufacturer specializing in family and steel roller coasters.",
|
|
"founded_date": "1926-01-01",
|
|
},
|
|
{
|
|
"name": "Arrow Dynamics",
|
|
"roles": ["MANUFACTURER"],
|
|
"website": "https://www.arrowdynamics.com/",
|
|
"description": "American manufacturer known for corkscrew and looping coasters.",
|
|
"founded_date": "1946-01-01",
|
|
},
|
|
{
|
|
"name": "Rocky Mountain Construction",
|
|
"roles": ["MANUFACTURER"],
|
|
"website": "https://www.rockymtnconstruction.com/",
|
|
"description": "American manufacturer known for I-Box track and wooden coasters.",
|
|
"founded_date": "2001-01-01",
|
|
},
|
|
{
|
|
"name": "Mack Rides GmbH & Co KG",
|
|
"roles": ["MANUFACTURER"],
|
|
"website": "https://www.mack-rides.com/",
|
|
"description": "German manufacturer of roller coasters and water rides.",
|
|
"founded_date": "1780-01-01",
|
|
},
|
|
]
|
|
|
|
# Ride Designers
|
|
designers_data = [
|
|
{
|
|
"name": "Werner Stengel",
|
|
"roles": ["DESIGNER"],
|
|
"website": "",
|
|
"description": "German roller coaster designer known for complex layouts and inversions.",
|
|
},
|
|
{
|
|
"name": "Alan Schilke",
|
|
"roles": ["DESIGNER"],
|
|
"website": "",
|
|
"description": "American roller coaster designer known for family-friendly coasters.",
|
|
},
|
|
{
|
|
"name": "John Pierce",
|
|
"roles": ["DESIGNER"],
|
|
"website": "",
|
|
"description": "American roller coaster designer and engineer.",
|
|
},
|
|
{
|
|
"name": "The Gravity Group",
|
|
"roles": ["DESIGNER"],
|
|
"website": "https://www.thegravitygroup.com/",
|
|
"description": "American design firm specializing in roller coaster design.",
|
|
},
|
|
]
|
|
|
|
# Create companies in parks app (for operators and property owners)
|
|
self.park_companies = {}
|
|
for data in operators_data:
|
|
try:
|
|
company, created = Company.objects.get_or_create(
|
|
name=data["name"],
|
|
defaults={
|
|
"roles": data["roles"],
|
|
"website": data["website"],
|
|
"description": data["description"],
|
|
"founded_year": data["founded_year"],
|
|
},
|
|
)
|
|
self.park_companies[data["name"]] = company
|
|
self.stdout.write(
|
|
f' {
|
|
"Created" if created else "Found"} park company: {
|
|
company.name}'
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating park company {data["name"]}: {str(e)}'
|
|
)
|
|
raise
|
|
|
|
# Create companies in rides app (for manufacturers and designers)
|
|
self.ride_companies = {}
|
|
for data in manufacturers_data + designers_data:
|
|
try:
|
|
company, created = RideCompany.objects.get_or_create(
|
|
name=data["name"],
|
|
defaults={
|
|
"roles": data["roles"],
|
|
"website": data["website"],
|
|
"description": data["description"],
|
|
"founded_date": data.get("founded_date"),
|
|
},
|
|
)
|
|
self.ride_companies[data["name"]] = company
|
|
self.stdout.write(
|
|
f' {
|
|
"Created" if created else "Found"} ride company: {
|
|
company.name}'
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating ride company {data["name"]}: {str(e)}'
|
|
)
|
|
raise
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error in create_companies: {str(e)}")
|
|
raise
|
|
|
|
def create_parks(self):
|
|
"""Create parks with proper operator relationships"""
|
|
self.stdout.write("Creating parks...")
|
|
|
|
try:
|
|
parks_data = [
|
|
{
|
|
"name": "Magic Kingdom",
|
|
"operator": "The Walt Disney Company",
|
|
"property_owner": "The Walt Disney Company",
|
|
"description": "The first theme park at Walt Disney World Resort in Florida, opened in 1971.",
|
|
"opening_date": "1971-10-01",
|
|
"size_acres": 142,
|
|
"website": "https://disneyworld.disney.go.com/destinations/magic-kingdom/",
|
|
"location": {
|
|
"street_address": "1180 Seven Seas Dr",
|
|
"city": "Lake Buena Vista",
|
|
"state": "Florida",
|
|
"country": "United States",
|
|
"postal_code": "32830",
|
|
"latitude": 28.4177,
|
|
"longitude": -81.5812,
|
|
},
|
|
},
|
|
{
|
|
"name": "Universal Studios Florida",
|
|
"operator": "Universal Parks & Resorts",
|
|
"property_owner": "Universal Parks & Resorts",
|
|
"description": "Movie and television-based theme park in Orlando, Florida.",
|
|
"opening_date": "1990-06-07",
|
|
"size_acres": 108,
|
|
"website": "https://www.universalorlando.com/web/en/us/theme-parks/universal-studios-florida",
|
|
"location": {
|
|
"street_address": "6000 Universal Blvd",
|
|
"city": "Orlando",
|
|
"state": "Florida",
|
|
"country": "United States",
|
|
"postal_code": "32819",
|
|
"latitude": 28.4749,
|
|
"longitude": -81.4687,
|
|
},
|
|
},
|
|
{
|
|
"name": "Cedar Point",
|
|
"operator": "Cedar Fair Entertainment Company",
|
|
"property_owner": "Cedar Fair Entertainment Company",
|
|
"description": 'Known as the "Roller Coaster Capital of the World".',
|
|
"opening_date": "1870-06-01",
|
|
"size_acres": 364,
|
|
"website": "https://www.cedarpoint.com/",
|
|
"location": {
|
|
"street_address": "1 Cedar Point Dr",
|
|
"city": "Sandusky",
|
|
"state": "Ohio",
|
|
"country": "United States",
|
|
"postal_code": "44870",
|
|
"latitude": 41.4822,
|
|
"longitude": -82.6835,
|
|
},
|
|
},
|
|
{
|
|
"name": "Europa-Park",
|
|
"operator": "Europa-Park GmbH & Co. Mack KG",
|
|
"property_owner": "Europa-Park GmbH & Co. Mack KG",
|
|
"description": "One of Europe's largest theme parks, located in Germany.",
|
|
"opening_date": "1975-07-12",
|
|
"size_acres": 235,
|
|
"website": "https://www.europapark.de/",
|
|
"location": {
|
|
"street_address": "Europa-Park-Straße 2",
|
|
"city": "Rust",
|
|
"state": "Baden-Württemberg",
|
|
"country": "Germany",
|
|
"postal_code": "77977",
|
|
"latitude": 48.2667,
|
|
"longitude": 7.7167,
|
|
},
|
|
},
|
|
{
|
|
"name": "Six Flags Magic Mountain",
|
|
"operator": "Six Flags Entertainment Corporation",
|
|
"property_owner": "Six Flags Entertainment Corporation",
|
|
"description": "Known for its world-record 19 roller coasters.",
|
|
"opening_date": "1971-05-29",
|
|
"size_acres": 262,
|
|
"website": "https://www.sixflags.com/magicmountain",
|
|
"location": {
|
|
"street_address": "26101 Magic Mountain Pkwy",
|
|
"city": "Valencia",
|
|
"state": "California",
|
|
"country": "United States",
|
|
"postal_code": "91355",
|
|
"latitude": 34.4253,
|
|
"longitude": -118.5971,
|
|
},
|
|
},
|
|
{
|
|
"name": "Silver Dollar City",
|
|
"operator": "Herschend Family Entertainment",
|
|
"property_owner": "Herschend Family Entertainment",
|
|
"description": "An 1880s-themed park featuring over 40 rides and attractions.",
|
|
"opening_date": "1960-05-01",
|
|
"size_acres": 61,
|
|
"website": "https://www.silverdollarcity.com/",
|
|
"location": {
|
|
"street_address": "399 Silver Dollar City Parkway",
|
|
"city": "Branson",
|
|
"state": "Missouri",
|
|
"country": "United States",
|
|
"postal_code": "65616",
|
|
"latitude": 36.668497,
|
|
"longitude": -93.339074,
|
|
},
|
|
},
|
|
]
|
|
|
|
self.parks = {}
|
|
for park_data in parks_data:
|
|
try:
|
|
operator = self.park_companies[park_data["operator"]]
|
|
property_owner = (
|
|
self.park_companies.get(park_data["property_owner"])
|
|
if park_data["property_owner"]
|
|
else None
|
|
)
|
|
|
|
park, created = Park.objects.get_or_create(
|
|
name=park_data["name"],
|
|
defaults={
|
|
"description": park_data["description"],
|
|
"status": "OPERATING",
|
|
"opening_date": park_data["opening_date"],
|
|
"size_acres": park_data["size_acres"],
|
|
"website": park_data["website"],
|
|
"operator": operator,
|
|
"property_owner": property_owner,
|
|
},
|
|
)
|
|
self.parks[park_data["name"]] = park
|
|
self.stdout.write(
|
|
f' {
|
|
"Created" if created else "Found"} park: {
|
|
park.name}'
|
|
)
|
|
|
|
# Create location for park
|
|
if created:
|
|
try:
|
|
loc_data = park_data["location"]
|
|
park_location = ParkLocation.objects.create(
|
|
park=park,
|
|
street_address=loc_data["street_address"],
|
|
city=loc_data["city"],
|
|
state=loc_data["state"],
|
|
country=loc_data["country"],
|
|
postal_code=loc_data["postal_code"],
|
|
)
|
|
# Set coordinates using the helper method
|
|
park_location.set_coordinates(
|
|
loc_data["latitude"], loc_data["longitude"]
|
|
)
|
|
park_location.save()
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating location for park {
|
|
park_data["name"]}: {
|
|
str(e)}'
|
|
)
|
|
raise
|
|
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating park {park_data["name"]}: {str(e)}'
|
|
)
|
|
raise
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error in create_parks: {str(e)}")
|
|
raise
|
|
|
|
def create_rides(self):
|
|
"""Create rides with manufacturer and designer relationships"""
|
|
self.stdout.write("Creating rides...")
|
|
|
|
try:
|
|
# First create some ride models
|
|
ride_models_data = [
|
|
{
|
|
"name": "Dive Coaster",
|
|
"manufacturer": "Bolliger & Mabillard",
|
|
"category": "RC",
|
|
"description": "Inverted roller coaster with a vertical drop and non-inverting loop",
|
|
},
|
|
{
|
|
"name": "Hyper Coaster",
|
|
"manufacturer": "Bolliger & Mabillard",
|
|
"category": "RC",
|
|
"description": "Steel roller coaster with heights over 200 feet",
|
|
},
|
|
{
|
|
"name": "Boomerang",
|
|
"manufacturer": "Vekoma Rides Manufacturing",
|
|
"category": "RC",
|
|
"description": "Shuttle roller coaster that runs forward and backward",
|
|
},
|
|
{
|
|
"name": "Corkscrew Coaster",
|
|
"manufacturer": "Arrow Dynamics",
|
|
"category": "RC",
|
|
"description": "Early steel coaster design with corkscrew elements",
|
|
},
|
|
{
|
|
"name": "I-Box Track",
|
|
"manufacturer": "Rocky Mountain Construction",
|
|
"category": "RC",
|
|
"description": "Smooth-riding steel track system for wooden coasters",
|
|
},
|
|
{
|
|
"name": "Powered Coaster",
|
|
"manufacturer": "Mack Rides GmbH & Co KG",
|
|
"category": "RC",
|
|
"description": "Family-friendly steel roller coaster",
|
|
},
|
|
]
|
|
|
|
self.ride_models = {}
|
|
for model_data in ride_models_data:
|
|
try:
|
|
manufacturer = self.ride_companies.get(model_data["manufacturer"])
|
|
model, created = RideModel.objects.get_or_create(
|
|
name=model_data["name"],
|
|
manufacturer=manufacturer,
|
|
defaults={
|
|
"description": model_data["description"],
|
|
"category": model_data["category"],
|
|
},
|
|
)
|
|
self.ride_models[model_data["name"]] = model
|
|
self.stdout.write(
|
|
f' {
|
|
"Created" if created else "Found"} ride model: {
|
|
model.name}'
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating ride model {
|
|
model_data["name"]}: {
|
|
str(e)}'
|
|
)
|
|
raise
|
|
|
|
# Create rides
|
|
rides_data = [
|
|
{
|
|
"name": "Millennium Force",
|
|
"park": "Cedar Point",
|
|
"manufacturer": "Bolliger & Mabillard",
|
|
"designer": "Werner Stengel",
|
|
"ride_model": "Hyper Coaster",
|
|
"category": "RC",
|
|
"description": "World's first hyper coaster reaching speeds of 93 mph.",
|
|
"opening_date": "2000-05-13",
|
|
"coaster_stats": {
|
|
"height_ft": 310,
|
|
"length_ft": 6595,
|
|
"speed_mph": 93,
|
|
"inversions": 0,
|
|
"ride_time_seconds": 165,
|
|
"track_material": "STEEL",
|
|
"roller_coaster_type": "SITDOWN",
|
|
"max_drop_height_ft": 300,
|
|
"launch_type": "CHAIN",
|
|
"trains_count": 3,
|
|
"cars_per_train": 9,
|
|
"seats_per_car": 4,
|
|
},
|
|
},
|
|
{
|
|
"name": "Top Thrill Dragster",
|
|
"park": "Cedar Point",
|
|
"manufacturer": "Intamin Amusement Rides",
|
|
"designer": "Werner Stengel",
|
|
"category": "RC",
|
|
"description": "World's first strata coaster reaching 420 feet.",
|
|
"opening_date": "2003-05-04",
|
|
"coaster_stats": {
|
|
"height_ft": 420,
|
|
"length_ft": 2800,
|
|
"speed_mph": 120,
|
|
"inversions": 0,
|
|
"ride_time_seconds": 17,
|
|
"track_material": "STEEL",
|
|
"roller_coaster_type": "SITDOWN",
|
|
"max_drop_height_ft": 400,
|
|
"launch_type": "HYDRAULIC",
|
|
"trains_count": 1,
|
|
"cars_per_train": 1,
|
|
"seats_per_car": 16,
|
|
},
|
|
},
|
|
{
|
|
"name": "Silver Star",
|
|
"park": "Europa-Park",
|
|
"manufacturer": "Bolliger & Mabillard",
|
|
"designer": "Werner Stengel",
|
|
"ride_model": "Dive Coaster",
|
|
"category": "RC",
|
|
"description": "Europe's first dive coaster with a 300-foot drop.",
|
|
"opening_date": "2002-03-23",
|
|
"coaster_stats": {
|
|
"height_ft": 239,
|
|
"length_ft": 5249,
|
|
"speed_mph": 80,
|
|
"inversions": 0,
|
|
"ride_time_seconds": 240,
|
|
"track_material": "STEEL",
|
|
"roller_coaster_type": "SITDOWN",
|
|
"max_drop_height_ft": 197,
|
|
"launch_type": "CHAIN",
|
|
"trains_count": 2,
|
|
"cars_per_train": 10,
|
|
"seats_per_car": 2,
|
|
},
|
|
},
|
|
{
|
|
"name": "Blue Fire",
|
|
"park": "Europa-Park",
|
|
"manufacturer": "Mack Rides GmbH & Co KG",
|
|
"designer": "John Pierce",
|
|
"ride_model": "Powered Coaster",
|
|
"category": "RC",
|
|
"description": "Launched roller coaster with a 124-foot drop.",
|
|
"opening_date": "2009-04-25",
|
|
"coaster_stats": {
|
|
"height_ft": 124,
|
|
"length_ft": 2789,
|
|
"speed_mph": 62,
|
|
"inversions": 0,
|
|
"ride_time_seconds": 120,
|
|
"track_material": "STEEL",
|
|
"roller_coaster_type": "SITDOWN",
|
|
"max_drop_height_ft": 98,
|
|
"launch_type": "HYDRAULIC",
|
|
"trains_count": 2,
|
|
"cars_per_train": 5,
|
|
"seats_per_car": 4,
|
|
},
|
|
},
|
|
{
|
|
"name": "Space Mountain",
|
|
"park": "Magic Kingdom",
|
|
"manufacturer": "Arrow Dynamics",
|
|
"designer": "John Pierce",
|
|
"category": "RC",
|
|
"description": "Indoor space-themed roller coaster.",
|
|
"opening_date": "1975-01-15",
|
|
"coaster_stats": {
|
|
"height_ft": 183,
|
|
"length_ft": 3200,
|
|
"speed_mph": 35,
|
|
"inversions": 0,
|
|
"ride_time_seconds": 180,
|
|
"track_material": "STEEL",
|
|
"roller_coaster_type": "SITDOWN",
|
|
"max_drop_height_ft": 150,
|
|
"launch_type": "CHAIN",
|
|
"trains_count": 2,
|
|
"cars_per_train": 6,
|
|
"seats_per_car": 2,
|
|
},
|
|
},
|
|
{
|
|
"name": "Big Thunder Mountain Railroad",
|
|
"park": "Magic Kingdom",
|
|
"manufacturer": "Arrow Dynamics",
|
|
"designer": "The Gravity Group",
|
|
"category": "RC",
|
|
"description": "Mine train roller coaster themed as a runaway mining train.",
|
|
"opening_date": "1980-11-15",
|
|
"coaster_stats": {
|
|
"height_ft": 146,
|
|
"length_ft": 3280,
|
|
"speed_mph": 35,
|
|
"inversions": 0,
|
|
"ride_time_seconds": 240,
|
|
"track_material": "STEEL",
|
|
"roller_coaster_type": "SITDOWN",
|
|
"max_drop_height_ft": 128,
|
|
"launch_type": "CHAIN",
|
|
"trains_count": 3,
|
|
"cars_per_train": 5,
|
|
"seats_per_car": 4,
|
|
},
|
|
},
|
|
{
|
|
"name": "Maverick",
|
|
"park": "Cedar Point",
|
|
"manufacturer": "Intamin Amusement Rides",
|
|
"designer": "Werner Stengel",
|
|
"category": "RC",
|
|
"description": "Wild mouse coaster with a 100-foot drop.",
|
|
"opening_date": "2007-05-26",
|
|
"coaster_stats": {
|
|
"height_ft": 105,
|
|
"length_ft": 4450,
|
|
"speed_mph": 70,
|
|
"inversions": 0,
|
|
"ride_time_seconds": 180,
|
|
"track_material": "STEEL",
|
|
"roller_coaster_type": "WILD_MOUSE",
|
|
"max_drop_height_ft": 100,
|
|
"launch_type": "CHAIN",
|
|
"trains_count": 2,
|
|
"cars_per_train": 4,
|
|
"seats_per_car": 4,
|
|
},
|
|
},
|
|
{
|
|
"name": "Time Traveler",
|
|
"park": "Silver Dollar City",
|
|
"manufacturer": "Rocky Mountain Construction",
|
|
"designer": "Alan Schilke",
|
|
"ride_model": "I-Box Track",
|
|
"category": "RC",
|
|
"description": "Wooden coaster with steel I-Box track for smooth riding.",
|
|
"opening_date": "2018-04-28",
|
|
"coaster_stats": {
|
|
"height_ft": 165,
|
|
"length_ft": 5832,
|
|
"speed_mph": 72,
|
|
"inversions": 0,
|
|
"ride_time_seconds": 240,
|
|
"track_material": "HYBRID",
|
|
"roller_coaster_type": "SITDOWN",
|
|
"max_drop_height_ft": 155,
|
|
"launch_type": "CHAIN",
|
|
"trains_count": 2,
|
|
"cars_per_train": 6,
|
|
"seats_per_car": 2,
|
|
},
|
|
},
|
|
]
|
|
|
|
self.rides = {}
|
|
for ride_data in rides_data:
|
|
try:
|
|
park = self.parks[ride_data["park"]]
|
|
manufacturer = self.ride_companies.get(
|
|
ride_data.get("manufacturer")
|
|
)
|
|
designer = self.ride_companies.get(ride_data.get("designer"))
|
|
ride_model = self.ride_models.get(ride_data.get("ride_model"))
|
|
|
|
ride, created = Ride.objects.get_or_create(
|
|
name=ride_data["name"],
|
|
park=park,
|
|
defaults={
|
|
"description": ride_data["description"],
|
|
"category": ride_data["category"],
|
|
"status": "OPERATING",
|
|
"opening_date": ride_data["opening_date"],
|
|
"manufacturer": manufacturer,
|
|
"designer": designer,
|
|
"ride_model": ride_model,
|
|
},
|
|
)
|
|
self.rides[ride_data["name"]] = ride
|
|
self.stdout.write(
|
|
f' {
|
|
"Created" if created else "Found"} ride: {
|
|
ride.name}'
|
|
)
|
|
|
|
# Create roller coaster stats if provided
|
|
if created and "coaster_stats" in ride_data:
|
|
try:
|
|
stats_data = ride_data["coaster_stats"]
|
|
RollerCoasterStats.objects.create(ride=ride, **stats_data)
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating stats for ride {
|
|
ride_data["name"]}: {
|
|
str(e)}'
|
|
)
|
|
raise
|
|
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating ride {ride_data["name"]}: {str(e)}'
|
|
)
|
|
raise
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error in create_rides: {str(e)}")
|
|
raise
|
|
|
|
def create_park_areas(self):
|
|
"""Add park areas for variety"""
|
|
self.stdout.write("Creating park areas...")
|
|
|
|
try:
|
|
areas_data = [
|
|
{
|
|
"park": "Magic Kingdom",
|
|
"areas": [
|
|
{
|
|
"name": "Main Street, U.S.A.",
|
|
"description": "Victorian-era themed entrance corridor",
|
|
},
|
|
{
|
|
"name": "Adventureland",
|
|
"description": "Exotic tropical places themed area",
|
|
},
|
|
{
|
|
"name": "Frontierland",
|
|
"description": "American Old West themed area",
|
|
},
|
|
{
|
|
"name": "Liberty Square",
|
|
"description": "Colonial America themed area",
|
|
},
|
|
{
|
|
"name": "Fantasyland",
|
|
"description": "Fairy tale themed area",
|
|
},
|
|
{
|
|
"name": "Tomorrowland",
|
|
"description": "Future themed area",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"park": "Universal Studios Florida",
|
|
"areas": [
|
|
{
|
|
"name": "Production Central",
|
|
"description": "Main entrance area with movie-themed attractions",
|
|
},
|
|
{
|
|
"name": "New York",
|
|
"description": "Themed after New York City streets",
|
|
},
|
|
{
|
|
"name": "San Francisco",
|
|
"description": "Themed after San Francisco's waterfront",
|
|
},
|
|
{
|
|
"name": "The Wizarding World of Harry Potter - Diagon Alley",
|
|
"description": "Themed after the Harry Potter series",
|
|
},
|
|
{
|
|
"name": "Springfield",
|
|
"description": "Themed after The Simpsons hometown",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"park": "Cedar Point",
|
|
"areas": [
|
|
{
|
|
"name": "Frontiertown",
|
|
"description": "Western-themed area with multiple roller coasters",
|
|
},
|
|
{
|
|
"name": "Millennium Island",
|
|
"description": "Home to the Millennium Force roller coaster",
|
|
},
|
|
{
|
|
"name": "Cedar Point Shores",
|
|
"description": "Waterpark area",
|
|
},
|
|
{
|
|
"name": "Top Thrill Dragster",
|
|
"description": "Area surrounding the iconic launched coaster",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"park": "Europa-Park",
|
|
"areas": [
|
|
{
|
|
"name": "Germany",
|
|
"description": "German-themed area",
|
|
},
|
|
{
|
|
"name": "France",
|
|
"description": "French-themed area",
|
|
},
|
|
{
|
|
"name": "England",
|
|
"description": "English-themed area",
|
|
},
|
|
{
|
|
"name": "Italy",
|
|
"description": "Italian-themed area",
|
|
},
|
|
{
|
|
"name": "Spain",
|
|
"description": "Spanish-themed area",
|
|
},
|
|
{
|
|
"name": "Portugal",
|
|
"description": "Portuguese-themed area",
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
for area_group in areas_data:
|
|
try:
|
|
park = self.parks[area_group["park"]]
|
|
for area_data in area_group["areas"]:
|
|
area, created = ParkArea.objects.get_or_create(
|
|
name=area_data["name"],
|
|
park=park,
|
|
defaults={
|
|
"description": area_data["description"],
|
|
"opening_date": park.opening_date,
|
|
},
|
|
)
|
|
self.stdout.write(
|
|
f' {
|
|
"Created" if created else "Found"} area: {
|
|
area.name} in {
|
|
park.name}'
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating areas for park {
|
|
area_group["park"]}: {
|
|
str(e)}'
|
|
)
|
|
raise
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error in create_park_areas: {str(e)}")
|
|
raise
|
|
|
|
def create_reviews(self):
|
|
"""Add sample reviews for testing"""
|
|
self.stdout.write("Creating sample reviews...")
|
|
|
|
try:
|
|
# Create a test user if none exists
|
|
test_user, created = User.objects.get_or_create(
|
|
username="testuser",
|
|
defaults={
|
|
"email": "test@example.com",
|
|
"first_name": "Test",
|
|
"last_name": "User",
|
|
},
|
|
)
|
|
if created:
|
|
test_user.set_password("testpass123")
|
|
test_user.save()
|
|
|
|
# Park reviews
|
|
park_reviews_data = [
|
|
{
|
|
"park": "Cedar Point",
|
|
"rating": 10,
|
|
"title": "Best roller coaster park in the world!",
|
|
"content": "Cedar Point is absolutely incredible. The Millennium Force is a must-ride. The park is clean, well-maintained, and the staff is friendly. Highly recommend!",
|
|
"visit_date": "2023-08-15",
|
|
},
|
|
{
|
|
"park": "Magic Kingdom",
|
|
"rating": 9,
|
|
"title": "Magical experience for all ages",
|
|
"content": "Disney does it again with Magic Kingdom. The attention to detail is amazing and the shows are spectacular. Space Mountain is a classic.",
|
|
"visit_date": "2023-07-20",
|
|
},
|
|
{
|
|
"park": "Europa-Park",
|
|
"rating": 9,
|
|
"title": "Europe's best theme park",
|
|
"content": "Europa-Park is fantastic! The theming is incredible and the rides are world-class. Silver Star is absolutely breathtaking.",
|
|
"visit_date": "2023-06-10",
|
|
},
|
|
{
|
|
"park": "Universal Studios Florida",
|
|
"rating": 8,
|
|
"title": "Great movie-themed attractions",
|
|
"content": "Universal has some amazing rides, especially in the Harry Potter area. The theming is top-notch and the shows are entertaining.",
|
|
"visit_date": "2023-05-05",
|
|
},
|
|
]
|
|
|
|
for review_data in park_reviews_data:
|
|
try:
|
|
park = self.parks[review_data["park"]]
|
|
review, created = ParkReview.objects.get_or_create(
|
|
park=park,
|
|
user=test_user,
|
|
defaults={
|
|
"rating": review_data["rating"],
|
|
"title": review_data["title"],
|
|
"content": review_data["content"],
|
|
"visit_date": review_data["visit_date"],
|
|
"is_published": True,
|
|
},
|
|
)
|
|
self.stdout.write(
|
|
f' {
|
|
"Created" if created else "Found"} park review: {
|
|
review.title}'
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating park review for {
|
|
review_data["park"]}: {
|
|
str(e)}'
|
|
)
|
|
raise
|
|
|
|
# Ride reviews
|
|
ride_reviews_data = [
|
|
{
|
|
"ride": "Millennium Force",
|
|
"rating": 10,
|
|
"title": "The king of roller coasters!",
|
|
"content": "Absolutely incredible ride! The first drop is breathtaking and the speed is unreal. A must-experience for any coaster enthusiast.",
|
|
"visit_date": "2023-08-15",
|
|
},
|
|
{
|
|
"ride": "Top Thrill Dragster",
|
|
"rating": 9,
|
|
"title": "Incredible launch and height",
|
|
"content": "The launch is intense and reaching the top of the 420-foot tower is amazing. The view from the top is spectacular!",
|
|
"visit_date": "2023-08-16",
|
|
},
|
|
{
|
|
"ride": "Silver Star",
|
|
"rating": 10,
|
|
"title": "Best dive coaster in Europe",
|
|
"content": "The dive drop is incredible! The theming around the ride is beautiful and the overall experience is fantastic.",
|
|
"visit_date": "2023-06-10",
|
|
},
|
|
{
|
|
"ride": "Space Mountain",
|
|
"rating": 8,
|
|
"title": "Classic Disney coaster",
|
|
"content": "A classic that never gets old. The indoor setting and space theme make it unique. Great for all ages.",
|
|
"visit_date": "2023-07-20",
|
|
},
|
|
]
|
|
|
|
for review_data in ride_reviews_data:
|
|
try:
|
|
ride = self.rides[review_data["ride"]]
|
|
review, created = RideReview.objects.get_or_create(
|
|
ride=ride,
|
|
user=test_user,
|
|
defaults={
|
|
"rating": review_data["rating"],
|
|
"title": review_data["title"],
|
|
"content": review_data["content"],
|
|
"visit_date": review_data["visit_date"],
|
|
"is_published": True,
|
|
},
|
|
)
|
|
self.stdout.write(
|
|
f' {
|
|
"Created" if created else "Found"} ride review: {
|
|
review.title}'
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(
|
|
f'Error creating ride review for {
|
|
review_data["ride"]}: {
|
|
str(e)}'
|
|
)
|
|
raise
|
|
|
|
self.stdout.write(self.style.SUCCESS("Sample data creation completed!"))
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error in create_reviews: {str(e)}")
|
|
raise
|