Improve park listing performance with optimized queries and caching

Implement performance enhancements for park listing by optimizing database queries, introducing efficient caching mechanisms, and refining pagination for a significantly faster and smoother user experience.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: c446bc9e-66df-438c-a86c-f53e6da13649
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
pac7
2025-09-23 22:50:09 +00:00
parent 6391b3d81c
commit fff180c476
11 changed files with 2864 additions and 70 deletions

View File

@@ -229,10 +229,16 @@ class ParkListView(HTMXFilterableMixin, ListView):
context_object_name = "parks"
filter_class = ParkFilter
paginate_by = 20
# Use optimized pagination
paginator_class = None # Will be set dynamically
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.filter_service = ParkFilterService()
# Import here to avoid circular imports
from .services.pagination_service import OptimizedPaginator
self.paginator_class = OptimizedPaginator
def get_template_names(self) -> list[str]:
"""Return park_list.html for HTMX requests"""
@@ -246,54 +252,35 @@ class ParkListView(HTMXFilterableMixin, ListView):
def get_queryset(self) -> QuerySet[Park]:
"""Get optimized queryset with enhanced filtering and proper relations"""
from apps.core.utils.query_optimization import monitor_db_performance
try:
# Start with optimized base queryset
queryset = (
get_base_park_queryset()
.select_related(
'operator',
'property_owner',
'location',
'banner_image',
'card_image'
)
.prefetch_related(
'photos',
'rides__manufacturer',
'areas'
)
)
# Use filter service for enhanced filtering
filter_params = self._get_clean_filter_params()
# Apply ordering
ordering = self.request.GET.get('ordering', 'name')
if ordering:
# Validate ordering to prevent SQL injection
valid_orderings = [
'name', '-name',
'average_rating', '-average_rating',
'coaster_count', '-coaster_count',
'ride_count', '-ride_count',
'opening_date', '-opening_date'
]
if ordering in valid_orderings:
queryset = queryset.order_by(ordering)
else:
queryset = queryset.order_by('name') # Default fallback
# Apply other filters through service
filtered_queryset = self.filter_service.get_filtered_queryset(filter_params)
# Combine with optimized queryset maintaining the optimizations
final_queryset = queryset.filter(
pk__in=filtered_queryset.values_list('pk', flat=True)
)
# Create filterset for form rendering
self.filterset = self.filter_class(self.request.GET, queryset=final_queryset)
return self.filterset.qs
with monitor_db_performance("park_list_queryset"):
# Get clean filter parameters
filter_params = self._get_clean_filter_params()
# Use filter service to build optimized queryset directly
# This eliminates the expensive pk__in subquery anti-pattern
queryset = self.filter_service.get_optimized_filtered_queryset(filter_params)
# Apply ordering with validation
ordering = self.request.GET.get('ordering', 'name')
if ordering:
valid_orderings = [
'name', '-name',
'average_rating', '-average_rating',
'coaster_count', '-coaster_count',
'ride_count', '-ride_count',
'opening_date', '-opening_date'
]
if ordering in valid_orderings:
queryset = queryset.order_by(ordering)
else:
queryset = queryset.order_by('name') # Default fallback
# Create filterset for form rendering
self.filterset = self.filter_class(self.request.GET, queryset=queryset)
return self.filterset.qs
except Exception as e:
messages.error(self.request, f"Error loading parks: {str(e)}")