mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 05:51:08 -05:00
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
This commit is contained in:
4
.replit
4
.replit
@@ -62,6 +62,10 @@ externalPort = 3000
|
|||||||
localPort = 45245
|
localPort = 45245
|
||||||
externalPort = 3001
|
externalPort = 3001
|
||||||
|
|
||||||
|
[[ports]]
|
||||||
|
localPort = 46739
|
||||||
|
externalPort = 3002
|
||||||
|
|
||||||
[deployment]
|
[deployment]
|
||||||
deploymentTarget = "autoscale"
|
deploymentTarget = "autoscale"
|
||||||
run = [
|
run = [
|
||||||
|
|||||||
@@ -373,10 +373,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<dt class="text-gray-500 dark:text-gray-400">Designer</dt>
|
<dt class="text-gray-500 dark:text-gray-400">Designer</dt>
|
||||||
<dd class="font-medium text-gray-900 dark:text-white">
|
<dd class="font-medium text-gray-900 dark:text-white">
|
||||||
<a href="{% url 'designers:designer_detail' ride.designer.slug %}"
|
{{ ride.designer.name }}
|
||||||
class="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300">
|
|
||||||
{{ ride.designer.name }}
|
|
||||||
</a>
|
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -6,8 +6,28 @@ from apps.parks.models import Park, Company
|
|||||||
from apps.rides.models import Ride
|
from apps.rides.models import Ride
|
||||||
from apps.core.analytics import PageView
|
from apps.core.analytics import PageView
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db import connection
|
||||||
import os
|
import os
|
||||||
import secrets
|
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):
|
def handler404(request, exception):
|
||||||
@@ -22,14 +42,22 @@ class HomeView(TemplateView):
|
|||||||
template_name = "home.html"
|
template_name = "home.html"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
# Track query count for performance monitoring
|
||||||
|
queries_start = len(connection.queries)
|
||||||
|
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
# Get stats
|
# Get stats - try cache first
|
||||||
context["stats"] = {
|
stats = cache.get("homepage_stats")
|
||||||
"total_parks": Park.objects.count(),
|
if stats is None:
|
||||||
"ride_count": Ride.objects.count(),
|
stats = {
|
||||||
"coaster_count": Ride.objects.filter(category="RC").count(),
|
"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
|
# Try to get trending items from cache first
|
||||||
trending_parks = cache.get("trending_parks")
|
trending_parks = cache.get("trending_parks")
|
||||||
@@ -38,9 +66,11 @@ class HomeView(TemplateView):
|
|||||||
# If not in cache, get them directly and cache them
|
# If not in cache, get them directly and cache them
|
||||||
if trending_parks is None:
|
if trending_parks is None:
|
||||||
try:
|
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)
|
PageView.get_trending_items(Park, hours=24, limit=10)
|
||||||
)
|
)
|
||||||
|
trending_parks = list(trending_parks_qs)
|
||||||
# Filter out any parks with invalid slugs
|
# Filter out any parks with invalid slugs
|
||||||
trending_parks = [p for p in trending_parks if getattr(p, 'slug', None)]
|
trending_parks = [p for p in trending_parks if getattr(p, 'slug', None)]
|
||||||
if trending_parks:
|
if trending_parks:
|
||||||
@@ -51,18 +81,24 @@ class HomeView(TemplateView):
|
|||||||
# Fallback to highest rated parks if no trending data
|
# Fallback to highest rated parks if no trending data
|
||||||
trending_parks = Park.objects.exclude(
|
trending_parks = Park.objects.exclude(
|
||||||
average_rating__isnull=True
|
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:
|
except Exception:
|
||||||
# Fallback to highest rated parks if trending calculation fails
|
# Fallback to highest rated parks if trending calculation fails
|
||||||
trending_parks = Park.objects.exclude(
|
trending_parks = Park.objects.exclude(
|
||||||
average_rating__isnull=True
|
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:
|
if trending_rides is None:
|
||||||
try:
|
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)
|
PageView.get_trending_items(Ride, hours=24, limit=10)
|
||||||
)
|
)
|
||||||
|
trending_rides = list(trending_rides_qs)
|
||||||
# Filter out any rides with invalid slugs
|
# Filter out any rides with invalid slugs
|
||||||
trending_rides = [r for r in trending_rides if getattr(r, 'slug', None)]
|
trending_rides = [r for r in trending_rides if getattr(r, 'slug', None)]
|
||||||
if trending_rides:
|
if trending_rides:
|
||||||
@@ -73,23 +109,34 @@ class HomeView(TemplateView):
|
|||||||
# Fallback to highest rated rides if no trending data
|
# Fallback to highest rated rides if no trending data
|
||||||
trending_rides = Ride.objects.exclude(
|
trending_rides = Ride.objects.exclude(
|
||||||
average_rating__isnull=True
|
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:
|
except Exception:
|
||||||
# Fallback to highest rated rides if trending calculation fails
|
# Fallback to highest rated rides if trending calculation fails
|
||||||
trending_rides = Ride.objects.exclude(
|
trending_rides = Ride.objects.exclude(
|
||||||
average_rating__isnull=True
|
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)
|
# Get highest rated items (mix of parks and rides)
|
||||||
highest_rated_parks = list(
|
highest_rated_parks = list(
|
||||||
Park.objects.exclude(average_rating__isnull=True)
|
Park.objects.exclude(average_rating__isnull=True)
|
||||||
.exclude(slug__isnull=True).exclude(slug__exact='')
|
.exclude(slug__isnull=True).exclude(slug__exact='')
|
||||||
|
.select_related('operator', 'property_owner', 'card_image', 'banner_image')
|
||||||
|
.prefetch_related('photos')
|
||||||
.order_by("-average_rating")[:20]
|
.order_by("-average_rating")[:20]
|
||||||
) # Get more items to randomly select from
|
) # Get more items to randomly select from
|
||||||
|
|
||||||
highest_rated_rides = list(
|
highest_rated_rides = list(
|
||||||
Ride.objects.exclude(average_rating__isnull=True)
|
Ride.objects.exclude(average_rating__isnull=True)
|
||||||
.exclude(slug__isnull=True).exclude(slug__exact='')
|
.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]
|
.order_by("-average_rating")[:20]
|
||||||
) # Get more items to randomly select from
|
) # Get more items to randomly select from
|
||||||
|
|
||||||
@@ -104,6 +151,11 @@ class HomeView(TemplateView):
|
|||||||
:10
|
:10
|
||||||
] # Take first 10 after shuffling
|
] # 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
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user