From 3d4115a1083584a10f03a6094688961550928167 Mon Sep 17 00:00:00 2001 From: pacnpal <183241239+pacnpal@users.noreply.github.com> Date: Sun, 14 Sep 2025 21:19:04 -0400 Subject: [PATCH] feat: Improve park and ride data seeding logic to avoid duplicates and enhance uniqueness --- .../apps/api/management/commands/seed_data.py | 161 ++++++++++-------- 1 file changed, 88 insertions(+), 73 deletions(-) diff --git a/backend/apps/api/management/commands/seed_data.py b/backend/apps/api/management/commands/seed_data.py index 7d01f2b9..9e3e52d2 100644 --- a/backend/apps/api/management/commands/seed_data.py +++ b/backend/apps/api/management/commands/seed_data.py @@ -696,26 +696,38 @@ class Command(BaseCommand): if not created: self.stdout.write(f' â„šī¸ Using existing park: {park_name}') - # Create park location - ParkLocation.objects.create( - park=park, - point=Point(lng, lat), - street_address=f"{random.randint(100, 9999)} {park_name} Dr", - city=city, - state=state, - country=country, - postal_code=f"{random.randint(10000, 99999)}" if country == 'USA' else '', - ) + # Create park location only if it doesn't exist + location_exists = False + try: + location_exists = hasattr(park, 'location') and park.location is not None + except Exception: + location_exists = False - # Create park areas - area_names = ['Main Street', 'Fantasyland', 'Tomorrowland', 'Adventureland', 'Frontierland'] - for area_name in random.sample(area_names, random.randint(2, 4)): - ParkArea.objects.create( + if created or not location_exists: + ParkLocation.objects.get_or_create( park=park, - name=area_name, - description=f"Themed area within {park_name}", + defaults={ + 'point': Point(lng, lat), + 'street_address': f"{random.randint(100, 9999)} {park_name} Dr", + 'city': city, + 'state': state, + 'country': country, + 'postal_code': f"{random.randint(10000, 99999)}" if country == 'USA' else '', + } ) + # Create park areas only if park was created + if created: + area_names = ['Main Street', 'Fantasyland', 'Tomorrowland', 'Adventureland', 'Frontierland'] + for area_name in random.sample(area_names, random.randint(2, 4)): + ParkArea.objects.get_or_create( + park=park, + name=area_name, + defaults={ + 'description': f"Themed area within {park_name}", + } + ) + parks.append(park) # Create additional random parks @@ -733,7 +745,8 @@ class Command(BaseCommand): for i in range(len(famous_parks), count): park_type = random.choice(park_types) - park_name = f"{random.choice(['Adventure', 'Magic', 'Wonder', 'Fantasy', 'Thrill', 'Family'])} {random.choice(['World', 'Land', 'Park', 'Kingdom', 'Gardens'])}" + # Make park names more unique by adding a number + park_name = f"{random.choice(['Adventure', 'Magic', 'Wonder', 'Fantasy', 'Thrill', 'Family'])} {random.choice(['World', 'Land', 'Park', 'Kingdom', 'Gardens'])} {i + 1}" operator = random.choice(operators) property_owner = random.choice(property_owners) if property_owners and random.random() < 0.5 else None @@ -963,49 +976,71 @@ class Command(BaseCommand): # Create park reviews park_review_count = count // 2 - for _ in range(park_review_count): + created_park_reviews = 0 + attempts = 0 + max_attempts = park_review_count * 3 # Allow multiple attempts to avoid infinite loops + + while created_park_reviews < park_review_count and attempts < max_attempts: if not parks: break user = random.choice(users) park = random.choice(parks) + attempts += 1 - ParkReview.objects.create( + # Use get_or_create to avoid duplicates + review, created = ParkReview.objects.get_or_create( user=user, park=park, - rating=random.randint(6, 10), - title=f"Great visit to {park.name}", - content=random.choice(review_texts), - is_published=random.choice([True] * 9 + [False]), - visit_date=date( - random.randint(2020, 2024), - random.randint(1, 12), - random.randint(1, 28) - ), + defaults={ + 'rating': random.randint(6, 10), + 'title': f"Great visit to {park.name}", + 'content': random.choice(review_texts), + 'is_published': random.choice([True] * 9 + [False]), + 'visit_date': date( + random.randint(2020, 2024), + random.randint(1, 12), + random.randint(1, 28) + ), + } ) + + if created: + created_park_reviews += 1 # Create ride reviews - ride_review_count = count - park_review_count - for _ in range(ride_review_count): + ride_review_count = count - created_park_reviews + created_ride_reviews = 0 + attempts = 0 + max_attempts = ride_review_count * 3 # Allow multiple attempts to avoid infinite loops + + while created_ride_reviews < ride_review_count and attempts < max_attempts: if not rides: break user = random.choice(users) ride = random.choice(rides) + attempts += 1 - RideReview.objects.create( + # Use get_or_create to avoid duplicates + review, created = RideReview.objects.get_or_create( user=user, ride=ride, - rating=random.randint(6, 10), - title=f"Awesome ride - {ride.name}", - content=random.choice(review_texts), - is_published=random.choice([True] * 9 + [False]), - visit_date=date( - random.randint(2020, 2024), - random.randint(1, 12), - random.randint(1, 28) - ), + defaults={ + 'rating': random.randint(6, 10), + 'title': f"Awesome ride - {ride.name}", + 'content': random.choice(review_texts), + 'is_published': random.choice([True] * 9 + [False]), + 'visit_date': date( + random.randint(2020, 2024), + random.randint(1, 12), + random.randint(1, 28) + ), + } ) + + if created: + created_ride_reviews += 1 self.stdout.write(f' ✅ Created {count} reviews') @@ -1034,9 +1069,11 @@ class Command(BaseCommand): # Add items to the list for rank, coaster in enumerate(random.sample(coasters, min(len(coasters), 10)), 1): + from django.contrib.contenttypes.models import ContentType + content_type = ContentType.objects.get_for_model(coaster) TopListItem.objects.create( top_list=top_list, - content_type_id=coaster._meta.pk.related_model._meta.pk, + content_type=content_type, object_id=coaster.pk, rank=rank, notes=f"Incredible {coaster.category} experience at {coaster.park.name}", @@ -1054,9 +1091,11 @@ class Command(BaseCommand): # Add items to the list for rank, park in enumerate(random.sample(parks, min(len(parks), 5)), 1): + from django.contrib.contenttypes.models import ContentType + content_type = ContentType.objects.get_for_model(park) TopListItem.objects.create( top_list=top_list, - content_type_id=park._meta.pk.related_model._meta.pk, + content_type=content_type, object_id=park.pk, rank=rank, notes=f"Amazing park with great {park.park_type.lower().replace('_', ' ')} atmosphere", @@ -1121,38 +1160,14 @@ class Command(BaseCommand): """Create sample photo records""" self.stdout.write('📸 Creating photo records...') - # Since we don't have actual Cloudflare images, we'll create placeholder records - photo_count = 0 + if not CloudflareImage: + self.stdout.write(' âš ī¸ CloudflareImage model not available, skipping photo creation') + return - # Create park photos - for park in random.sample(parks, min(len(parks), 5)): - for i in range(random.randint(1, 3)): - ParkPhoto.objects.create( - park=park, - caption=f"Beautiful view of {park.name}", - alt_text=f"Photo of {park.name} theme park", - photo_type=random.choice(['ENTRANCE', 'OVERVIEW', 'ATTRACTION', 'DINING']), - is_primary=i == 0, - photographer="ThrillWiki Staff", - source="Official Park Photography", - ) - photo_count += 1 - - # Create ride photos - for ride in random.sample(rides, min(len(rides), 10)): - for i in range(random.randint(1, 2)): - RidePhoto.objects.create( - ride=ride, - caption=f"Exciting view of {ride.name}", - alt_text=f"Photo of {ride.name} ride", - photo_type=random.choice(['ACTION', 'OVERVIEW', 'QUEUE', 'DETAIL']), - is_primary=i == 0, - photographer="ThrillWiki Staff", - source="Official Park Photography", - ) - photo_count += 1 - - self.stdout.write(f' ✅ Created {photo_count} photo records') + # Since we don't have actual Cloudflare images, we'll skip photo creation + # In a real scenario, you would need actual CloudflareImage instances + self.stdout.write(' âš ī¸ Photo creation skipped (requires actual CloudflareImage instances)') + self.stdout.write(' â„šī¸ To create photos, you need to upload actual images to Cloudflare first') def create_rankings(self, rides: List[Ride]) -> None: """Create ride rankings if model exists"""