photos fix

This commit is contained in:
pacnpal
2024-11-01 01:27:11 +00:00
parent 3cbda93094
commit 6265f82193
89 changed files with 2241 additions and 614 deletions

View File

@@ -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')