From 95f94cc7993db71de50f9a651ca5ca4edf4b5114 Mon Sep 17 00:00:00 2001
From: pac7 <47831526-pac7@users.noreply.replit.com>
Date: Mon, 22 Sep 2025 15:45:51 +0000
Subject: [PATCH] Improve site performance and adhere to best practices
Optimize database queries for parks and rides using select_related and prefetch_related, implement caching for homepage stats and trending items, and update the ride detail template to remove unnecessary link wrapping.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 48ecdb60-d0f0-4b75-95c9-34e409ef35fb
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
---
.replit | 4 ++
templates/rides/ride_detail.html | 5 +--
thrillwiki/views.py | 76 +++++++++++++++++++++++++++-----
3 files changed, 69 insertions(+), 16 deletions(-)
diff --git a/.replit b/.replit
index 3520ba63..8f36374f 100644
--- a/.replit
+++ b/.replit
@@ -62,6 +62,10 @@ externalPort = 3000
localPort = 45245
externalPort = 3001
+[[ports]]
+localPort = 46739
+externalPort = 3002
+
[deployment]
deploymentTarget = "autoscale"
run = [
diff --git a/templates/rides/ride_detail.html b/templates/rides/ride_detail.html
index 257f3f8a..bf14548f 100644
--- a/templates/rides/ride_detail.html
+++ b/templates/rides/ride_detail.html
@@ -373,10 +373,7 @@
{% endif %}
diff --git a/thrillwiki/views.py b/thrillwiki/views.py
index 7618ac6f..98f1fdab 100644
--- a/thrillwiki/views.py
+++ b/thrillwiki/views.py
@@ -6,8 +6,28 @@ from apps.parks.models import Park, Company
from apps.rides.models import Ride
from apps.core.analytics import PageView
from django.conf import settings
+from django.db import connection
import os
import secrets
+import logging
+
+# Set up logger for query debugging
+logger = logging.getLogger(__name__)
+
+
+def optimize_park_queryset(queryset):
+ """Add proper select_related and prefetch_related to park querysets"""
+ return queryset.select_related(
+ 'operator', 'property_owner', 'card_image', 'banner_image'
+ ).prefetch_related('photos')
+
+
+def optimize_ride_queryset(queryset):
+ """Add proper select_related and prefetch_related to ride querysets"""
+ return queryset.select_related(
+ 'park', 'park__operator', 'manufacturer', 'designer', 'card_image',
+ 'ride_model', 'park_area'
+ ).prefetch_related('photos')
def handler404(request, exception):
@@ -22,14 +42,22 @@ class HomeView(TemplateView):
template_name = "home.html"
def get_context_data(self, **kwargs):
+ # Track query count for performance monitoring
+ queries_start = len(connection.queries)
+
context = super().get_context_data(**kwargs)
- # Get stats
- context["stats"] = {
- "total_parks": Park.objects.count(),
- "ride_count": Ride.objects.count(),
- "coaster_count": Ride.objects.filter(category="RC").count(),
- }
+ # Get stats - try cache first
+ stats = cache.get("homepage_stats")
+ if stats is None:
+ stats = {
+ "total_parks": Park.objects.count(),
+ "ride_count": Ride.objects.count(),
+ "coaster_count": Ride.objects.filter(category="RC").count(),
+ }
+ # Cache stats for 30 minutes
+ cache.set("homepage_stats", stats, 1800)
+ context["stats"] = stats
# Try to get trending items from cache first
trending_parks = cache.get("trending_parks")
@@ -38,9 +66,11 @@ class HomeView(TemplateView):
# If not in cache, get them directly and cache them
if trending_parks is None:
try:
- trending_parks = list(
+ # Get trending parks with optimized queries
+ trending_parks_qs = optimize_park_queryset(
PageView.get_trending_items(Park, hours=24, limit=10)
)
+ trending_parks = list(trending_parks_qs)
# Filter out any parks with invalid slugs
trending_parks = [p for p in trending_parks if getattr(p, 'slug', None)]
if trending_parks:
@@ -51,18 +81,24 @@ class HomeView(TemplateView):
# Fallback to highest rated parks if no trending data
trending_parks = Park.objects.exclude(
average_rating__isnull=True
- ).exclude(slug__isnull=True).exclude(slug__exact='').order_by("-average_rating")[:10]
+ ).exclude(slug__isnull=True).exclude(slug__exact='').select_related(
+ 'operator', 'property_owner', 'card_image', 'banner_image'
+ ).prefetch_related('photos').order_by("-average_rating")[:10]
except Exception:
# Fallback to highest rated parks if trending calculation fails
trending_parks = Park.objects.exclude(
average_rating__isnull=True
- ).exclude(slug__isnull=True).exclude(slug__exact='').order_by("-average_rating")[:10]
+ ).exclude(slug__isnull=True).exclude(slug__exact='').select_related(
+ 'operator', 'property_owner', 'card_image', 'banner_image'
+ ).prefetch_related('photos').order_by("-average_rating")[:10]
if trending_rides is None:
try:
- trending_rides = list(
+ # Get trending rides with optimized queries
+ trending_rides_qs = optimize_ride_queryset(
PageView.get_trending_items(Ride, hours=24, limit=10)
)
+ trending_rides = list(trending_rides_qs)
# Filter out any rides with invalid slugs
trending_rides = [r for r in trending_rides if getattr(r, 'slug', None)]
if trending_rides:
@@ -73,23 +109,34 @@ class HomeView(TemplateView):
# Fallback to highest rated rides if no trending data
trending_rides = Ride.objects.exclude(
average_rating__isnull=True
- ).exclude(slug__isnull=True).exclude(slug__exact='').order_by("-average_rating")[:10]
+ ).exclude(slug__isnull=True).exclude(slug__exact='').select_related(
+ 'park', 'park__operator', 'manufacturer', 'designer', 'card_image',
+ 'ride_model', 'park_area'
+ ).prefetch_related('photos').order_by("-average_rating")[:10]
except Exception:
# Fallback to highest rated rides if trending calculation fails
trending_rides = Ride.objects.exclude(
average_rating__isnull=True
- ).exclude(slug__isnull=True).exclude(slug__exact='').order_by("-average_rating")[:10]
+ ).exclude(slug__isnull=True).exclude(slug__exact='').select_related(
+ 'park', 'park__operator', 'manufacturer', 'designer', 'card_image',
+ 'ride_model', 'park_area'
+ ).prefetch_related('photos').order_by("-average_rating")[:10]
# Get highest rated items (mix of parks and rides)
highest_rated_parks = list(
Park.objects.exclude(average_rating__isnull=True)
.exclude(slug__isnull=True).exclude(slug__exact='')
+ .select_related('operator', 'property_owner', 'card_image', 'banner_image')
+ .prefetch_related('photos')
.order_by("-average_rating")[:20]
) # Get more items to randomly select from
highest_rated_rides = list(
Ride.objects.exclude(average_rating__isnull=True)
.exclude(slug__isnull=True).exclude(slug__exact='')
+ .select_related('park', 'park__operator', 'manufacturer', 'designer', 'card_image',
+ 'ride_model', 'park_area')
+ .prefetch_related('photos')
.order_by("-average_rating")[:20]
) # Get more items to randomly select from
@@ -104,6 +151,11 @@ class HomeView(TemplateView):
:10
] # Take first 10 after shuffling
+ # Log query count for debugging
+ queries_end = len(connection.queries)
+ query_count = queries_end - queries_start
+ logger.info(f"HomeView executed {query_count} queries")
+
return context