mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-21 13:31:09 -05:00
photos fix
This commit is contained in:
@@ -9,11 +9,9 @@
|
||||
"description": "The most visited theme park in the world, Magic Kingdom is Walt Disney World's first theme park.",
|
||||
"website": "https://disneyworld.disney.go.com/destinations/magic-kingdom/",
|
||||
"owner": "The Walt Disney Company",
|
||||
"size_acres": 142,
|
||||
"size_acres": "142.00",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Walt_Disney_World_Magic_Kingdom_Cinderella_Castle.jpg/1280px-Walt_Disney_World_Magic_Kingdom_Cinderella_Castle.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Magic_Kingdom_Main_Street_USA_Panorama.jpg/1280px-Magic_Kingdom_Main_Street_USA_Panorama.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Magic_Kingdom_-_Cinderella_Castle_at_Night.jpg/1280px-Magic_Kingdom_-_Cinderella_Castle_at_Night.jpg"
|
||||
"https://images.unsplash.com/photo-1524008279394-3aed4643b30b"
|
||||
],
|
||||
"rides": [
|
||||
{
|
||||
@@ -24,13 +22,12 @@
|
||||
"manufacturer": "Walt Disney Imagineering",
|
||||
"description": "A high-speed roller coaster in the dark through space.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Magic_Kingdom_Space_Mountain.jpg/1280px-Magic_Kingdom_Space_Mountain.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Space_Mountain_%28Magic_Kingdom%29_entrance.jpg/1280px-Space_Mountain_%28Magic_Kingdom%29_entrance.jpg"
|
||||
"https://images.unsplash.com/photo-1536768139911-e290a59011e4"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 183,
|
||||
"length_ft": 3196,
|
||||
"speed_mph": 27,
|
||||
"height_ft": "183.00",
|
||||
"length_ft": "3196.00",
|
||||
"speed_mph": "27.00",
|
||||
"inversions": 0,
|
||||
"ride_time_seconds": 180
|
||||
}
|
||||
@@ -43,13 +40,12 @@
|
||||
"manufacturer": "Walt Disney Imagineering",
|
||||
"description": "A mine train roller coaster through the Old West.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Big_Thunder_Mountain_Railroad_at_Magic_Kingdom.jpg/1280px-Big_Thunder_Mountain_Railroad_at_Magic_Kingdom.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Big_Thunder_Mountain_Railroad_%28Magic_Kingdom%29.jpg/1280px-Big_Thunder_Mountain_Railroad_%28Magic_Kingdom%29.jpg"
|
||||
"https://images.unsplash.com/photo-1513889961551-628c1e5e2ee9"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 104,
|
||||
"length_ft": 2671,
|
||||
"speed_mph": 30,
|
||||
"height_ft": "104.00",
|
||||
"length_ft": "2671.00",
|
||||
"speed_mph": "30.00",
|
||||
"inversions": 0,
|
||||
"ride_time_seconds": 197
|
||||
}
|
||||
@@ -62,13 +58,12 @@
|
||||
"manufacturer": "Vekoma",
|
||||
"description": "A family roller coaster featuring unique swinging cars.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Seven_Dwarfs_Mine_Train_at_Magic_Kingdom.jpg/1280px-Seven_Dwarfs_Mine_Train_at_Magic_Kingdom.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Seven_Dwarfs_Mine_Train_drop.jpg/1280px-Seven_Dwarfs_Mine_Train_drop.jpg"
|
||||
"https://images.unsplash.com/photo-1590144662036-33bf0ebd2c7f"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 112,
|
||||
"length_ft": 2000,
|
||||
"speed_mph": 34,
|
||||
"height_ft": "112.00",
|
||||
"length_ft": "2000.00",
|
||||
"speed_mph": "34.00",
|
||||
"inversions": 0,
|
||||
"ride_time_seconds": 180
|
||||
}
|
||||
@@ -81,8 +76,7 @@
|
||||
"manufacturer": "Walt Disney Imagineering",
|
||||
"description": "A dark ride through a haunted estate.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Haunted_Mansion_at_Magic_Kingdom.jpg/1280px-Haunted_Mansion_at_Magic_Kingdom.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/2/2b/Haunted_Mansion_entrance.jpg/1280px-Haunted_Mansion_entrance.jpg"
|
||||
"https://images.unsplash.com/photo-1597466599360-3b9775841aec"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -93,8 +87,7 @@
|
||||
"manufacturer": "Walt Disney Imagineering",
|
||||
"description": "A boat ride through pirate-filled Caribbean waters.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Pirates_of_the_Caribbean_%28Magic_Kingdom%29.jpg/1280px-Pirates_of_the_Caribbean_%28Magic_Kingdom%29.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Pirates_of_the_Caribbean_entrance.jpg/1280px-Pirates_of_the_Caribbean_entrance.jpg"
|
||||
"https://images.unsplash.com/photo-1506126799754-92bc47fc5d78"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -108,11 +101,9 @@
|
||||
"description": "Known as the Roller Coaster Capital of the World.",
|
||||
"website": "https://www.cedarpoint.com",
|
||||
"owner": "Cedar Fair",
|
||||
"size_acres": 364,
|
||||
"size_acres": "364.00",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/7/7c/Cedar_Point_aerial_view.jpg/1280px-Cedar_Point_aerial_view.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Cedar_Point_Beach.jpg/1280px-Cedar_Point_Beach.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cedar_Point_at_dusk.jpg/1280px-Cedar_Point_at_dusk.jpg"
|
||||
"https://images.unsplash.com/photo-1536768139911-e290a59011e4"
|
||||
],
|
||||
"rides": [
|
||||
{
|
||||
@@ -123,13 +114,12 @@
|
||||
"manufacturer": "Rocky Mountain Construction",
|
||||
"description": "A hybrid roller coaster featuring multiple inversions.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/Steel_Vengeance_at_Cedar_Point.jpg/1280px-Steel_Vengeance_at_Cedar_Point.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/Steel_Vengeance_first_drop.jpg/1280px-Steel_Vengeance_first_drop.jpg"
|
||||
"https://images.unsplash.com/photo-1543674892-7d64d45df18b"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 205,
|
||||
"length_ft": 5740,
|
||||
"speed_mph": 74,
|
||||
"height_ft": "205.00",
|
||||
"length_ft": "5740.00",
|
||||
"speed_mph": "74.00",
|
||||
"inversions": 4,
|
||||
"ride_time_seconds": 150
|
||||
}
|
||||
@@ -142,13 +132,12 @@
|
||||
"manufacturer": "Intamin",
|
||||
"description": "A giga coaster with stunning views of Lake Erie.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Millennium_Force_at_Cedar_Point.jpg/1280px-Millennium_Force_at_Cedar_Point.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Millennium_Force_lift_hill.jpg/1280px-Millennium_Force_lift_hill.jpg"
|
||||
"https://images.unsplash.com/photo-1605559911160-a3d95d213904"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 310,
|
||||
"length_ft": 6595,
|
||||
"speed_mph": 93,
|
||||
"height_ft": "310.00",
|
||||
"length_ft": "6595.00",
|
||||
"speed_mph": "93.00",
|
||||
"inversions": 0,
|
||||
"ride_time_seconds": 120
|
||||
}
|
||||
@@ -161,13 +150,12 @@
|
||||
"manufacturer": "Intamin",
|
||||
"description": "A strata coaster featuring a 420-foot top hat element.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Top_Thrill_Dragster.jpg/1280px-Top_Thrill_Dragster.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/Top_Thrill_Dragster_launch.jpg/1280px-Top_Thrill_Dragster_launch.jpg"
|
||||
"https://images.unsplash.com/photo-1578912996078-305d92249aa6"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 420,
|
||||
"length_ft": 2800,
|
||||
"speed_mph": 120,
|
||||
"height_ft": "420.00",
|
||||
"length_ft": "2800.00",
|
||||
"speed_mph": "120.00",
|
||||
"inversions": 0,
|
||||
"ride_time_seconds": 50
|
||||
}
|
||||
@@ -180,13 +168,12 @@
|
||||
"manufacturer": "Intamin",
|
||||
"description": "A launched roller coaster with multiple inversions.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Maverick_at_Cedar_Point.jpg/1280px-Maverick_at_Cedar_Point.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/Maverick_first_drop.jpg/1280px-Maverick_first_drop.jpg"
|
||||
"https://images.unsplash.com/photo-1581309638082-877cb8132535"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 105,
|
||||
"length_ft": 4450,
|
||||
"speed_mph": 70,
|
||||
"height_ft": "105.00",
|
||||
"length_ft": "4450.00",
|
||||
"speed_mph": "70.00",
|
||||
"inversions": 2,
|
||||
"ride_time_seconds": 150
|
||||
}
|
||||
@@ -202,11 +189,9 @@
|
||||
"description": "A theme park featuring cutting-edge technology and thrilling attractions.",
|
||||
"website": "https://www.universalorlando.com/web/en/us/theme-parks/islands-of-adventure",
|
||||
"owner": "NBCUniversal",
|
||||
"size_acres": 110,
|
||||
"size_acres": "110.00",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Islands_of_Adventure_entrance.jpg/1280px-Islands_of_Adventure_entrance.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Hogwarts_Castle_at_Universal%27s_Islands_of_Adventure.jpg/1280px-Hogwarts_Castle_at_Universal%27s_Islands_of_Adventure.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Port_of_Entry_at_Islands_of_Adventure.jpg/1280px-Port_of_Entry_at_Islands_of_Adventure.jpg"
|
||||
"https://images.unsplash.com/photo-1597466599360-3b9775841aec"
|
||||
],
|
||||
"rides": [
|
||||
{
|
||||
@@ -217,13 +202,12 @@
|
||||
"manufacturer": "Intamin",
|
||||
"description": "A high-speed launch coaster featuring velociraptors.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Jurassic_World_VelociCoaster.jpg/1280px-Jurassic_World_VelociCoaster.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/VelociCoaster_top_hat.jpg/1280px-VelociCoaster_top_hat.jpg"
|
||||
"https://images.unsplash.com/photo-1536768139911-e290a59011e4"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 155,
|
||||
"length_ft": 4700,
|
||||
"speed_mph": 70,
|
||||
"height_ft": "155.00",
|
||||
"length_ft": "4700.00",
|
||||
"speed_mph": "70.00",
|
||||
"inversions": 4,
|
||||
"ride_time_seconds": 145
|
||||
}
|
||||
@@ -236,13 +220,12 @@
|
||||
"manufacturer": "Intamin",
|
||||
"description": "A story coaster through the Forbidden Forest.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d7/Hagrid%27s_Magical_Creatures_Motorbike_Adventure.jpg/1280px-Hagrid%27s_Magical_Creatures_Motorbike_Adventure.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Hagrid%27s_entrance.jpg/1280px-Hagrid%27s_entrance.jpg"
|
||||
"https://images.unsplash.com/photo-1513889961551-628c1e5e2ee9"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 65,
|
||||
"length_ft": 5053,
|
||||
"speed_mph": 50,
|
||||
"height_ft": "65.00",
|
||||
"length_ft": "5053.00",
|
||||
"speed_mph": "50.00",
|
||||
"inversions": 0,
|
||||
"ride_time_seconds": 180
|
||||
}
|
||||
@@ -255,26 +238,23 @@
|
||||
"manufacturer": "Oceaneering International",
|
||||
"description": "A 3D dark ride featuring Spider-Man.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/The_Amazing_Adventures_of_Spider-Man.jpg/1280px-The_Amazing_Adventures_of_Spider-Man.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Spider-Man_ride_entrance.jpg/1280px-Spider-Man_ride_entrance.jpg"
|
||||
"https://images.unsplash.com/photo-1590144662036-33bf0ebd2c7f"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Alton Towers",
|
||||
"location": "Staffordshire, England",
|
||||
"location": "Alton, England",
|
||||
"country": "GB",
|
||||
"opening_date": "1980-04-04",
|
||||
"status": "OPERATING",
|
||||
"description": "The UK's largest theme park, built around a historic stately home.",
|
||||
"website": "https://www.altontowers.com",
|
||||
"owner": "Merlin Entertainments",
|
||||
"size_acres": 910,
|
||||
"size_acres": "910.00",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Alton_Towers_aerial_view.jpg/1280px-Alton_Towers_aerial_view.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Alton_Towers_mansion.jpg/1280px-Alton_Towers_mansion.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Alton_Towers_gardens.jpg/1280px-Alton_Towers_gardens.jpg"
|
||||
"https://images.unsplash.com/photo-1506126799754-92bc47fc5d78"
|
||||
],
|
||||
"rides": [
|
||||
{
|
||||
@@ -285,13 +265,12 @@
|
||||
"manufacturer": "Bolliger & Mabillard",
|
||||
"description": "An inverted roller coaster through ravines.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Nemesis_at_Alton_Towers.jpg/1280px-Nemesis_at_Alton_Towers.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Nemesis_loop.jpg/1280px-Nemesis_loop.jpg"
|
||||
"https://images.unsplash.com/photo-1543674892-7d64d45df18b"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 43,
|
||||
"length_ft": 2349,
|
||||
"speed_mph": 50,
|
||||
"height_ft": "43.00",
|
||||
"length_ft": "2349.00",
|
||||
"speed_mph": "50.00",
|
||||
"inversions": 4,
|
||||
"ride_time_seconds": 80
|
||||
}
|
||||
@@ -304,13 +283,12 @@
|
||||
"manufacturer": "Bolliger & Mabillard",
|
||||
"description": "The world's first vertical drop roller coaster.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Oblivion_at_Alton_Towers.jpg/1280px-Oblivion_at_Alton_Towers.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Oblivion_vertical_drop.jpg/1280px-Oblivion_vertical_drop.jpg"
|
||||
"https://images.unsplash.com/photo-1605559911160-a3d95d213904"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 65,
|
||||
"length_ft": 1804,
|
||||
"speed_mph": 68,
|
||||
"height_ft": "65.00",
|
||||
"length_ft": "1804.00",
|
||||
"speed_mph": "68.00",
|
||||
"inversions": 0,
|
||||
"ride_time_seconds": 100
|
||||
}
|
||||
@@ -326,11 +304,9 @@
|
||||
"description": "Germany's largest theme park, featuring European-themed areas.",
|
||||
"website": "https://www.europapark.de",
|
||||
"owner": "Mack Rides",
|
||||
"size_acres": 235,
|
||||
"size_acres": "235.00",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Europa-Park_entrance.jpg/1280px-Europa-Park_entrance.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/Europa-Park_aerial_view.jpg/1280px-Europa-Park_aerial_view.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Europa-Park_at_night.jpg/1280px-Europa-Park_at_night.jpg"
|
||||
"https://images.unsplash.com/photo-1536768139911-e290a59011e4"
|
||||
],
|
||||
"rides": [
|
||||
{
|
||||
@@ -341,13 +317,12 @@
|
||||
"manufacturer": "Bolliger & Mabillard",
|
||||
"description": "A hypercoaster with stunning views.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/2/24/Silver_Star_at_Europa-Park.jpg/1280px-Silver_Star_at_Europa-Park.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Silver_Star_first_drop.jpg/1280px-Silver_Star_first_drop.jpg"
|
||||
"https://images.unsplash.com/photo-1536768139911-e290a59011e4"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 239,
|
||||
"length_ft": 4003,
|
||||
"speed_mph": 79,
|
||||
"height_ft": "239.00",
|
||||
"length_ft": "4003.00",
|
||||
"speed_mph": "79.00",
|
||||
"inversions": 0,
|
||||
"ride_time_seconds": 180
|
||||
}
|
||||
@@ -360,13 +335,12 @@
|
||||
"manufacturer": "Mack Rides",
|
||||
"description": "A launched roller coaster with multiple inversions.",
|
||||
"photos": [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Blue_Fire_at_Europa-Park.jpg/1280px-Blue_Fire_at_Europa-Park.jpg",
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Blue_Fire_launch.jpg/1280px-Blue_Fire_launch.jpg"
|
||||
"https://images.unsplash.com/photo-1513889961551-628c1e5e2ee9"
|
||||
],
|
||||
"stats": {
|
||||
"height_ft": 125,
|
||||
"length_ft": 3465,
|
||||
"speed_mph": 62,
|
||||
"height_ft": "125.00",
|
||||
"length_ft": "3465.00",
|
||||
"speed_mph": "62.00",
|
||||
"inversions": 4,
|
||||
"ride_time_seconds": 150
|
||||
}
|
||||
|
||||
@@ -1,297 +1,216 @@
|
||||
import os
|
||||
import json
|
||||
import random
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
import os
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.core.files import File
|
||||
from django.utils.text import slugify
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import connection
|
||||
from faker import Faker
|
||||
from django.core.files.temp import NamedTemporaryFile
|
||||
from django.core.files import File
|
||||
import requests
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
from cities_light.models import City, Country
|
||||
|
||||
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 accounts.models import User, UserProfile, TopList, TopListItem
|
||||
from companies.models import Company, Manufacturer
|
||||
from cities_light.models import Country, Region, City
|
||||
from django.contrib.auth.models import Permission
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
fake = Faker()
|
||||
User = get_user_model()
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Seeds the database with sample data'
|
||||
help = 'Seeds the database with initial data'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--users', type=int, default=50)
|
||||
parser.add_argument('--reviews-per-item', type=int, default=10)
|
||||
def handle(self, *args, **kwargs):
|
||||
self.stdout.write('Starting database seed...')
|
||||
|
||||
# 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()
|
||||
|
||||
# Create top lists
|
||||
self.stdout.write('Creating top lists...')
|
||||
self.create_top_lists()
|
||||
|
||||
self.stdout.write('Successfully seeded database')
|
||||
|
||||
def download_and_save_image(self, url):
|
||||
try:
|
||||
response = requests.get(url)
|
||||
img = Image.open(BytesIO(response.content))
|
||||
img_io = BytesIO()
|
||||
img.save(img_io, format='JPEG')
|
||||
img_io.seek(0)
|
||||
filename = url.split('/')[-1]
|
||||
return filename, File(img_io)
|
||||
except Exception as e:
|
||||
self.stdout.write(self.style.WARNING(f'Failed to download image {url}: {str(e)}'))
|
||||
return None, None
|
||||
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, count):
|
||||
def create_users(self):
|
||||
self.stdout.write('Creating users...')
|
||||
users = []
|
||||
|
||||
|
||||
# Try to get admin user
|
||||
try:
|
||||
# Get existing admin user
|
||||
admin_user = User.objects.get(username='admin')
|
||||
users.append(admin_user)
|
||||
self.stdout.write('Added existing admin user')
|
||||
admin = User.objects.get(username='admin')
|
||||
self.stdout.write('Admin user exists, updating permissions...')
|
||||
except User.DoesNotExist:
|
||||
self.stdout.write(self.style.WARNING('Admin user not found, skipping...'))
|
||||
|
||||
# Create regular users using raw SQL
|
||||
roles = ['USER'] * 20 + ['MODERATOR'] * 3 + ['ADMIN'] * 2
|
||||
with connection.cursor() as cursor:
|
||||
for _ in range(count):
|
||||
# Create user
|
||||
username = fake.user_name()
|
||||
while User.objects.filter(username=username).exists():
|
||||
username = fake.user_name()
|
||||
|
||||
user_id = str(uuid.uuid4())[:10]
|
||||
cursor.execute("""
|
||||
INSERT INTO accounts_user (
|
||||
username, password, email, is_superuser, is_staff,
|
||||
is_active, date_joined, user_id, first_name,
|
||||
last_name, role, is_banned, ban_reason,
|
||||
theme_preference
|
||||
) VALUES (
|
||||
%s, %s, %s, false, false,
|
||||
true, NOW(), %s, '', '',
|
||||
%s, false, '', 'light'
|
||||
) RETURNING id;
|
||||
""", [username, make_password('password123'), fake.email(), user_id, random.choice(roles)])
|
||||
|
||||
user_db_id = cursor.fetchone()[0]
|
||||
|
||||
# Create profile
|
||||
profile_id = str(uuid.uuid4())[:10]
|
||||
display_name = f"{fake.first_name()}_{fake.last_name()}_{fake.random_number(digits=4)}"
|
||||
cursor.execute("""
|
||||
INSERT INTO accounts_userprofile (
|
||||
profile_id, display_name, pronouns, bio,
|
||||
twitter, instagram, youtube, discord,
|
||||
coaster_credits, dark_ride_credits,
|
||||
flat_ride_credits, water_ride_credits,
|
||||
user_id, avatar
|
||||
) VALUES (
|
||||
%s, %s, %s, %s,
|
||||
%s, %s, %s, %s,
|
||||
%s, %s, %s, %s,
|
||||
%s, ''
|
||||
);
|
||||
""", [
|
||||
profile_id, display_name, random.choice(['he/him', 'she/her', 'they/them', '']),
|
||||
fake.text(max_nb_chars=200),
|
||||
fake.url() if random.choice([True, False]) else '',
|
||||
fake.url() if random.choice([True, False]) else '',
|
||||
fake.url() if random.choice([True, False]) else '',
|
||||
fake.user_name() if random.choice([True, False]) else '',
|
||||
random.randint(0, 500), random.randint(0, 200),
|
||||
random.randint(0, 300), random.randint(0, 100),
|
||||
user_db_id
|
||||
])
|
||||
|
||||
users.append(User.objects.get(id=user_db_id))
|
||||
admin = User.objects.create_superuser('admin', 'admin@example.com', 'admin')
|
||||
self.stdout.write('Created admin user')
|
||||
|
||||
# Create regular users
|
||||
usernames = [
|
||||
'destiny89', 'destiny97', 'thompsonchris', 'chriscohen', 'littlesharon',
|
||||
'wrichardson', 'christophermiles', 'jacksonangela', 'jennifer71', 'smithemily',
|
||||
'brandylong', 'milleranna', 'tlopez', 'fgriffith', 'mariah80',
|
||||
'kendradavis', 'rosarioashley', 'camposkaitlyn', 'lisaherrera', 'riveratiffany',
|
||||
'codytucker', 'cheyenne78', 'christinagreen', 'eric57', 'steinsuzanne',
|
||||
'david95', 'rstewart', 'josephhaynes', 'umedina', 'tylerbryant',
|
||||
'lcampos', 'shellyford', 'ksmith', 'qeverett', 'waguilar',
|
||||
'zbrowning', 'yalexander', 'wallacewilliam', 'bsuarez', 'ismith',
|
||||
'joyceosborne', 'garythomas', 'tlewis', 'robertgonzales', 'medinashannon',
|
||||
'yhanson', 'howellmorgan', 'taylorsusan', 'barnold', 'bryan20'
|
||||
]
|
||||
|
||||
for username in usernames:
|
||||
if not User.objects.filter(username=username).exists():
|
||||
User.objects.create_user(
|
||||
username=username,
|
||||
email=f'{username}@example.com',
|
||||
password='password123'
|
||||
)
|
||||
self.stdout.write(f'Created user: {username}')
|
||||
|
||||
return users
|
||||
|
||||
def create_companies(self):
|
||||
self.stdout.write('Creating companies...')
|
||||
|
||||
# Delete existing companies
|
||||
Company.objects.all().delete()
|
||||
self.stdout.write('Deleted existing companies')
|
||||
|
||||
companies = {
|
||||
'The Walt Disney Company': {
|
||||
'headquarters': 'Burbank, California',
|
||||
'founded_date': '1923-10-16',
|
||||
'website': 'https://www.disney.com',
|
||||
},
|
||||
'Cedar Fair': {
|
||||
'headquarters': 'Sandusky, Ohio',
|
||||
'founded_date': '1983-05-01',
|
||||
'website': 'https://www.cedarfair.com',
|
||||
},
|
||||
'NBCUniversal': {
|
||||
'headquarters': 'New York City, New York',
|
||||
'founded_date': '1912-04-30',
|
||||
'website': 'https://www.nbcuniversal.com',
|
||||
},
|
||||
'Merlin Entertainments': {
|
||||
'headquarters': 'Poole, England',
|
||||
'founded_date': '1999-05-19',
|
||||
'website': 'https://www.merlinentertainments.biz',
|
||||
},
|
||||
'Mack Rides': {
|
||||
'headquarters': 'Waldkirch, Germany',
|
||||
'founded_date': '1780-01-01',
|
||||
'website': 'https://mack-rides.com',
|
||||
},
|
||||
}
|
||||
|
||||
company_instances = {}
|
||||
for name, details in companies.items():
|
||||
company = Company.objects.create(
|
||||
name=name,
|
||||
slug=slugify(name),
|
||||
headquarters=details['headquarters'],
|
||||
founded_date=datetime.strptime(details['founded_date'], '%Y-%m-%d').date(),
|
||||
website=details['website'],
|
||||
)
|
||||
company_instances[name] = company
|
||||
|
||||
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}')
|
||||
|
||||
return company_instances
|
||||
|
||||
def create_manufacturers(self):
|
||||
self.stdout.write('Creating manufacturers...')
|
||||
|
||||
# Delete existing manufacturers
|
||||
Manufacturer.objects.all().delete()
|
||||
self.stdout.write('Deleted existing manufacturers')
|
||||
|
||||
manufacturers = {
|
||||
'Walt Disney Imagineering': {
|
||||
'headquarters': 'Glendale, California',
|
||||
'founded_date': '1952-12-16',
|
||||
'website': 'https://sites.disney.com/waltdisneyimagineering/',
|
||||
},
|
||||
'Bolliger & Mabillard': {
|
||||
'headquarters': 'Monthey, Switzerland',
|
||||
'founded_date': '1988-01-01',
|
||||
'website': 'https://www.bolliger-mabillard.com',
|
||||
},
|
||||
'Intamin': {
|
||||
'headquarters': 'Schaan, Liechtenstein',
|
||||
'founded_date': '1967-01-01',
|
||||
'website': 'https://www.intamin.com',
|
||||
},
|
||||
'Rocky Mountain Construction': {
|
||||
'headquarters': 'Hayden, Idaho',
|
||||
'founded_date': '2001-01-01',
|
||||
'website': 'https://www.rockymountainconstruction.com',
|
||||
},
|
||||
'Vekoma': {
|
||||
'headquarters': 'Vlodrop, Netherlands',
|
||||
'founded_date': '1926-01-01',
|
||||
'website': 'https://www.vekoma.com',
|
||||
},
|
||||
'Mack Rides': {
|
||||
'headquarters': 'Waldkirch, Germany',
|
||||
'founded_date': '1780-01-01',
|
||||
'website': 'https://mack-rides.com',
|
||||
},
|
||||
'Oceaneering International': {
|
||||
'headquarters': 'Houston, Texas',
|
||||
'founded_date': '1964-01-01',
|
||||
'website': 'https://www.oceaneering.com',
|
||||
},
|
||||
}
|
||||
|
||||
manufacturer_instances = {}
|
||||
for name, details in manufacturers.items():
|
||||
manufacturer = Manufacturer.objects.create(
|
||||
name=name,
|
||||
slug=slugify(name),
|
||||
headquarters=details['headquarters'],
|
||||
founded_date=datetime.strptime(details['founded_date'], '%Y-%m-%d').date(),
|
||||
website=details['website'],
|
||||
)
|
||||
manufacturer_instances[name] = manufacturer
|
||||
|
||||
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}')
|
||||
|
||||
return manufacturer_instances
|
||||
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, users):
|
||||
self.stdout.write('Creating parks and rides from seed data...')
|
||||
|
||||
# Create companies and manufacturers first
|
||||
companies = self.create_companies()
|
||||
manufacturers = self.create_manufacturers()
|
||||
|
||||
# Load seed data
|
||||
seed_data_path = os.path.join(os.path.dirname(__file__), 'seed_data.json')
|
||||
with open(seed_data_path, 'r') as f:
|
||||
seed_data = json.load(f)
|
||||
|
||||
# Delete existing parks (this will cascade delete rides)
|
||||
def create_parks_and_rides(self):
|
||||
# Delete existing parks and rides
|
||||
Park.objects.all().delete()
|
||||
self.stdout.write('Deleted existing parks and rides')
|
||||
|
||||
parks = []
|
||||
for park_data in seed_data['parks']:
|
||||
# Load seed data
|
||||
with open(os.path.join(os.path.dirname(__file__), 'seed_data.json')) as f:
|
||||
data = json.load(f)
|
||||
|
||||
country_map = {
|
||||
'US': 'United States',
|
||||
'GB': 'United Kingdom',
|
||||
'DE': 'Germany'
|
||||
}
|
||||
|
||||
for park_data in data['parks']:
|
||||
try:
|
||||
# Get country from cities_light
|
||||
country = Country.objects.get(code2=park_data['country'])
|
||||
|
||||
# Try to find city, but don't require it
|
||||
city = None
|
||||
try:
|
||||
city_name = park_data['location'].split(',')[0].strip()
|
||||
city = City.objects.filter(name__iexact=city_name, country=country).first()
|
||||
except:
|
||||
self.stdout.write(self.style.WARNING(f'City not found for {park_data["name"]}, using location text'))
|
||||
|
||||
# Create park
|
||||
park = Park.objects.create(
|
||||
name=park_data['name'],
|
||||
slug=slugify(park_data['name']),
|
||||
location=park_data['location'],
|
||||
country=country,
|
||||
city=city,
|
||||
opening_date=datetime.strptime(park_data['opening_date'], '%Y-%m-%d').date(),
|
||||
opening_date=park_data['opening_date'],
|
||||
status=park_data['status'],
|
||||
description=park_data['description'],
|
||||
website=park_data['website'],
|
||||
owner=companies[park_data['owner']],
|
||||
owner=Company.objects.get(name=park_data['owner']),
|
||||
size_acres=park_data['size_acres']
|
||||
)
|
||||
|
||||
# Add park photos
|
||||
for photo_url in park_data.get('photos', []):
|
||||
filename, file = self.download_and_save_image(photo_url)
|
||||
if filename and file:
|
||||
for photo_url in park_data['photos']:
|
||||
img_file = self.download_image(photo_url)
|
||||
if img_file:
|
||||
Photo.objects.create(
|
||||
content_object=park,
|
||||
image=file,
|
||||
uploaded_by=random.choice(users),
|
||||
caption=f"Photo of {park.name}",
|
||||
is_approved=True
|
||||
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 this park
|
||||
# Create rides
|
||||
for ride_data in park_data['rides']:
|
||||
ride = Ride.objects.create(
|
||||
name=ride_data['name'],
|
||||
slug=slugify(ride_data['name']),
|
||||
category=ride_data['category'],
|
||||
park=park,
|
||||
category=ride_data['category'],
|
||||
opening_date=ride_data['opening_date'],
|
||||
status=ride_data['status'],
|
||||
opening_date=datetime.strptime(ride_data['opening_date'], '%Y-%m-%d').date(),
|
||||
manufacturer=manufacturers[ride_data['manufacturer']],
|
||||
manufacturer=Manufacturer.objects.get(name=ride_data['manufacturer']),
|
||||
description=ride_data['description']
|
||||
)
|
||||
|
||||
# Add roller coaster stats if applicable
|
||||
if ride_data['category'] == 'RC' and 'stats' in ride_data:
|
||||
# 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'],
|
||||
@@ -300,118 +219,67 @@ class Command(BaseCommand):
|
||||
inversions=ride_data['stats']['inversions'],
|
||||
ride_time_seconds=ride_data['stats']['ride_time_seconds']
|
||||
)
|
||||
|
||||
# Add ride photos
|
||||
for photo_url in ride_data.get('photos', []):
|
||||
filename, file = self.download_and_save_image(photo_url)
|
||||
if filename and file:
|
||||
Photo.objects.create(
|
||||
content_object=ride,
|
||||
image=file,
|
||||
uploaded_by=random.choice(users),
|
||||
caption=f"Photo of {ride.name}",
|
||||
is_approved=True
|
||||
)
|
||||
|
||||
parks.append(park)
|
||||
self.stdout.write(f'Created park and rides: {park.name}')
|
||||
|
||||
except Exception as e:
|
||||
self.stdout.write(self.style.ERROR(f'Failed to create park {park_data["name"]}: {str(e)}'))
|
||||
except Country.DoesNotExist:
|
||||
self.stdout.write(f'Country not found: {park_data["country"]}')
|
||||
continue
|
||||
|
||||
return parks
|
||||
|
||||
def create_reviews(self, users, reviews_per_item):
|
||||
self.stdout.write('Creating reviews...')
|
||||
def create_reviews(self):
|
||||
# Delete existing reviews
|
||||
Review.objects.all().delete()
|
||||
self.stdout.write('Deleted existing reviews')
|
||||
|
||||
# Park reviews
|
||||
total_parks = Park.objects.count()
|
||||
for i, park in enumerate(Park.objects.all(), 1):
|
||||
for _ in range(random.randint(reviews_per_item - 5, reviews_per_item + 5)):
|
||||
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 = random.randint(3, 5)
|
||||
for _ in range(num_reviews):
|
||||
# Generate random visit date
|
||||
days_offset = random.randint(0, 365)
|
||||
visit_date = one_year_ago + timedelta(days=days_offset)
|
||||
|
||||
Review.objects.create(
|
||||
user=random.choice(users),
|
||||
content_object=park,
|
||||
title=fake.sentence(),
|
||||
content=fake.text(max_nb_chars=500),
|
||||
rating=random.randint(1, 10),
|
||||
visit_date=fake.date_between(start_date=park.opening_date, end_date='today'),
|
||||
is_published=True
|
||||
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=random.randint(7, 10),
|
||||
visit_date=visit_date
|
||||
)
|
||||
if i % 5 == 0:
|
||||
self.stdout.write(f'Created reviews for {i}/{total_parks} parks')
|
||||
self.stdout.write(f'Created reviews for {park.name}')
|
||||
|
||||
# Ride reviews
|
||||
total_rides = Ride.objects.count()
|
||||
for i, ride in enumerate(Ride.objects.all(), 1):
|
||||
for _ in range(random.randint(reviews_per_item - 5, reviews_per_item + 5)):
|
||||
Review.objects.create(
|
||||
user=random.choice(users),
|
||||
content_object=ride,
|
||||
title=fake.sentence(),
|
||||
content=fake.text(max_nb_chars=500),
|
||||
rating=random.randint(1, 10),
|
||||
visit_date=fake.date_between(start_date=ride.opening_date, end_date='today'),
|
||||
is_published=True
|
||||
)
|
||||
if i % 20 == 0:
|
||||
self.stdout.write(f'Created reviews for {i}/{total_rides} rides')
|
||||
|
||||
def create_top_lists(self, users):
|
||||
self.stdout.write('Creating top lists...')
|
||||
def create_top_lists(self):
|
||||
# Delete existing top lists
|
||||
TopList.objects.all().delete()
|
||||
# TopList.objects.all().delete()
|
||||
self.stdout.write('Deleted existing top lists')
|
||||
|
||||
categories = ['RC', 'DR', 'FR', 'WR', 'PK']
|
||||
total_users = len(users)
|
||||
|
||||
# Get content types
|
||||
park_ct = ContentType.objects.get_for_model(Park)
|
||||
ride_ct = ContentType.objects.get_for_model(Ride)
|
||||
users = list(User.objects.exclude(username='admin'))
|
||||
parks = list(Park.objects.all())
|
||||
|
||||
for i, user in enumerate(users, 1):
|
||||
for category in categories:
|
||||
if random.choice([True, False]): # 50% chance to create a list
|
||||
top_list = TopList.objects.create(
|
||||
user=user,
|
||||
title=f"My Top {random.randint(5, 20)} {dict(TopList.Categories.choices)[category]}s",
|
||||
category=category,
|
||||
description=fake.text(max_nb_chars=200)
|
||||
)
|
||||
|
||||
# Add items to the list
|
||||
items = []
|
||||
if category == 'PK':
|
||||
items = list(Park.objects.all())
|
||||
content_type = park_ct
|
||||
else:
|
||||
items = list(Ride.objects.filter(category=category))
|
||||
content_type = ride_ct
|
||||
|
||||
if items:
|
||||
selected_items = random.sample(items, min(len(items), random.randint(5, 20)))
|
||||
for rank, item in enumerate(selected_items, 1):
|
||||
TopListItem.objects.create(
|
||||
top_list=top_list,
|
||||
content_type=content_type,
|
||||
object_id=item.id,
|
||||
rank=rank,
|
||||
notes=fake.sentence() if random.choice([True, False]) else ''
|
||||
)
|
||||
|
||||
# Create top list for every 10th user
|
||||
if i % 10 == 0:
|
||||
self.stdout.write(f'Created top lists for {i}/{total_users} users')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
self.stdout.write('Starting database seed...')
|
||||
|
||||
users = self.create_users(options['users'])
|
||||
parks = self.create_parks_and_rides(users)
|
||||
self.create_reviews(users, options['reviews_per_item'])
|
||||
self.create_top_lists(users)
|
||||
|
||||
self.stdout.write(self.style.SUCCESS('Successfully seeded database'))
|
||||
# top_list = TopList.objects.create(
|
||||
# user=user,
|
||||
# name=f"{user.username}'s Top Parks",
|
||||
# description='My favorite theme parks'
|
||||
# )
|
||||
|
||||
# Add 3-5 random parks
|
||||
# selected_parks = random.sample(parks, random.randint(3, 5))
|
||||
# for j, park in enumerate(selected_parks, 1):
|
||||
# TopListItem.objects.create(
|
||||
# top_list=top_list,
|
||||
# content_type=ContentType.objects.get_for_model(park),
|
||||
# object_id=park.id,
|
||||
# rank=j
|
||||
# )
|
||||
self.stdout.write(f'Created top lists for {i}/50 users')
|
||||
|
||||
Reference in New Issue
Block a user