mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 02:31:08 -05:00
- Cleaned up and standardized assertions in ApiTestMixin for API response validation. - Updated ASGI settings to use os.environ for setting the DJANGO_SETTINGS_MODULE. - Removed unused imports and improved formatting in settings.py. - Refactored URL patterns in urls.py for better readability and organization. - Enhanced view functions in views.py for consistency and clarity. - Added .flake8 configuration for linting and style enforcement. - Introduced type stubs for django-environ to improve type checking with Pylance.
179 lines
6.0 KiB
Python
179 lines
6.0 KiB
Python
from django.views.generic import TemplateView
|
|
from django.http import JsonResponse
|
|
from django.contrib.gis.geos import Point
|
|
from parks.models import Park
|
|
from parks.filters import ParkFilter
|
|
from core.services.location_search import (
|
|
location_search_service,
|
|
LocationSearchFilters,
|
|
)
|
|
from core.forms.search import LocationSearchForm
|
|
|
|
|
|
class AdaptiveSearchView(TemplateView):
|
|
template_name = "core/search/results.html"
|
|
|
|
def get_queryset(self):
|
|
"""
|
|
Get the base queryset, optimized with select_related and prefetch_related
|
|
"""
|
|
return (
|
|
Park.objects.select_related("operator", "property_owner")
|
|
.prefetch_related("location", "photos")
|
|
.all()
|
|
)
|
|
|
|
def get_filterset(self):
|
|
"""
|
|
Get the filterset instance
|
|
"""
|
|
return ParkFilter(self.request.GET, queryset=self.get_queryset())
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""
|
|
Add filtered results and filter form to context
|
|
"""
|
|
context = super().get_context_data(**kwargs)
|
|
filterset = self.get_filterset()
|
|
|
|
# Check if location-based search is being used
|
|
location_search = self.request.GET.get("location_search", "").strip()
|
|
near_location = self.request.GET.get("near_location", "").strip()
|
|
|
|
# Add location search context
|
|
context.update(
|
|
{
|
|
"results": filterset.qs,
|
|
"filters": filterset,
|
|
"applied_filters": bool(
|
|
self.request.GET
|
|
), # Check if any filters are applied
|
|
"is_location_search": bool(location_search or near_location),
|
|
"location_search_query": location_search or near_location,
|
|
}
|
|
)
|
|
|
|
return context
|
|
|
|
|
|
class FilterFormView(TemplateView):
|
|
"""
|
|
View for rendering just the filter form for HTMX updates
|
|
"""
|
|
|
|
template_name = "core/search/filters.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
filterset = ParkFilter(self.request.GET, queryset=Park.objects.all())
|
|
context["filters"] = filterset
|
|
return context
|
|
|
|
|
|
class LocationSearchView(TemplateView):
|
|
"""
|
|
Enhanced search view with comprehensive location search capabilities.
|
|
"""
|
|
|
|
template_name = "core/search/location_results.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
# Build search filters from request parameters
|
|
filters = self._build_search_filters()
|
|
|
|
# Perform search
|
|
results = location_search_service.search(filters)
|
|
|
|
# Group results by type for better presentation
|
|
grouped_results = {
|
|
"parks": [r for r in results if r.content_type == "park"],
|
|
"rides": [r for r in results if r.content_type == "ride"],
|
|
"companies": [r for r in results if r.content_type == "company"],
|
|
}
|
|
|
|
context.update(
|
|
{
|
|
"results": results,
|
|
"grouped_results": grouped_results,
|
|
"total_results": len(results),
|
|
"search_filters": filters,
|
|
"has_location_filter": bool(filters.location_point),
|
|
"search_form": LocationSearchForm(self.request.GET),
|
|
}
|
|
)
|
|
|
|
return context
|
|
|
|
def _build_search_filters(self) -> LocationSearchFilters:
|
|
"""Build LocationSearchFilters from request parameters."""
|
|
form = LocationSearchForm(self.request.GET)
|
|
form.is_valid() # Populate cleaned_data
|
|
|
|
# Parse location coordinates if provided
|
|
location_point = None
|
|
lat = form.cleaned_data.get("lat")
|
|
lng = form.cleaned_data.get("lng")
|
|
if lat and lng:
|
|
try:
|
|
location_point = Point(float(lng), float(lat), srid=4326)
|
|
except (ValueError, TypeError):
|
|
location_point = None
|
|
|
|
# Parse location types
|
|
location_types = set()
|
|
if form.cleaned_data.get("search_parks"):
|
|
location_types.add("park")
|
|
if form.cleaned_data.get("search_rides"):
|
|
location_types.add("ride")
|
|
if form.cleaned_data.get("search_companies"):
|
|
location_types.add("company")
|
|
|
|
# If no specific types selected, search all
|
|
if not location_types:
|
|
location_types = {"park", "ride", "company"}
|
|
|
|
# Parse radius
|
|
radius_km = None
|
|
radius_str = form.cleaned_data.get("radius_km", "").strip()
|
|
if radius_str:
|
|
try:
|
|
radius_km = float(radius_str)
|
|
# Clamp between 1-500km
|
|
radius_km = max(1, min(500, radius_km))
|
|
except (ValueError, TypeError):
|
|
radius_km = None
|
|
|
|
return LocationSearchFilters(
|
|
search_query=form.cleaned_data.get("q", "").strip() or None,
|
|
location_point=location_point,
|
|
radius_km=radius_km,
|
|
location_types=location_types if location_types else None,
|
|
country=form.cleaned_data.get("country", "").strip() or None,
|
|
state=form.cleaned_data.get("state", "").strip() or None,
|
|
city=form.cleaned_data.get("city", "").strip() or None,
|
|
park_status=self.request.GET.getlist("park_status") or None,
|
|
include_distance=True,
|
|
max_results=int(self.request.GET.get("limit", 100)),
|
|
)
|
|
|
|
|
|
class LocationSuggestionsView(TemplateView):
|
|
"""
|
|
AJAX endpoint for location search suggestions.
|
|
"""
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
query = request.GET.get("q", "").strip()
|
|
limit = int(request.GET.get("limit", 10))
|
|
|
|
if len(query) < 2:
|
|
return JsonResponse({"suggestions": []})
|
|
|
|
try:
|
|
suggestions = location_search_service.suggest_locations(query, limit)
|
|
return JsonResponse({"suggestions": suggestions})
|
|
except Exception as e:
|
|
return JsonResponse({"error": str(e)}, status=500)
|