Enhance park search with autocomplete and improved filtering options

Introduce autocomplete for park searches, optimize park data fetching with select_related and prefetch_related, add new API endpoints for autocomplete and quick filters, and refactor the park list view to use new Django Cotton components for a more dynamic and user-friendly 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 21:44:12 +00:00
parent 7feb7c462d
commit 4c954fff6f
13 changed files with 1588 additions and 245 deletions

View File

@@ -245,15 +245,56 @@ class ParkListView(HTMXFilterableMixin, ListView):
return get_view_mode(self.request)
def get_queryset(self) -> QuerySet[Park]:
"""Get optimized queryset with filter service"""
"""Get optimized queryset with enhanced filtering and proper relations"""
try:
# Use filter service for optimized filtering
filter_params = dict(self.request.GET.items())
queryset = self.filter_service.get_filtered_queryset(filter_params)
# 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'
)
)
# Also create filterset for form rendering
self.filterset = self.filter_class(self.request.GET, queryset=queryset)
# 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
except Exception as e:
messages.error(self.request, f"Error loading parks: {str(e)}")
queryset = self.model.objects.none()
@@ -275,6 +316,12 @@ class ParkListView(HTMXFilterableMixin, ListView):
filter_counts = self.filter_service.get_filter_counts()
popular_filters = self.filter_service.get_popular_filters()
# Calculate active filters for chips component
active_filters = {}
for key, value in self.request.GET.items():
if key not in ['page', 'view_mode'] and value:
active_filters[key] = value
context.update(
{
"view_mode": self.get_view_mode(),
@@ -282,6 +329,9 @@ class ParkListView(HTMXFilterableMixin, ListView):
"search_query": self.request.GET.get("search", ""),
"filter_counts": filter_counts,
"popular_filters": popular_filters,
"active_filters": active_filters,
"filter_count": len(active_filters),
"current_ordering": self.request.GET.get("ordering", "name"),
"total_results": (
context.get("paginator").count
if context.get("paginator")