Files
thrillwiki_django_no_react/backend/thrillwiki/views.py
pacnpal edcd8f2076 Add secret management guide, client-side performance monitoring, and search accessibility enhancements
- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols.
- Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage.
- Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
2025-12-23 16:41:42 -05:00

192 lines
6.6 KiB
Python

from django.shortcuts import render
from django.views.generic import TemplateView
from django.db.models import Q
from django.core.cache import cache
from apps.parks.models import Park, Company
from apps.rides.models import Ride
from apps.core.analytics import PageView
from django.conf import settings
import logging
import os
import secrets
from apps.core.logging import log_exception
logger = logging.getLogger(__name__)
def handler404(request, exception):
return render(request, "404.html", status=404)
def handler500(request):
return render(request, "500.html", status=500)
class HomeView(TemplateView):
template_name = "home.html"
def get_context_data(self, **kwargs):
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(),
}
# Try to get trending items from cache first
trending_parks = cache.get("trending_parks")
trending_rides = cache.get("trending_rides")
# If not in cache, get them directly and cache them
if trending_parks is None:
try:
trending_parks = list(
PageView.get_trending_items(Park, hours=24, limit=10)
)
if trending_parks:
cache.set(
"trending_parks", trending_parks, 3600
) # Cache for 1 hour
else:
# Fallback to highest rated parks if no trending data
trending_parks = Park.objects.exclude(
average_rating__isnull=True
).order_by("-average_rating")[:10]
except Exception as e:
log_exception(
logger,
e,
context={"operation": "get_trending_parks", "fallback": True},
request=self.request,
)
# Fallback to highest rated parks if trending calculation fails
trending_parks = Park.objects.exclude(
average_rating__isnull=True
).order_by("-average_rating")[:10]
if trending_rides is None:
try:
trending_rides = list(
PageView.get_trending_items(Ride, hours=24, limit=10)
)
if trending_rides:
cache.set(
"trending_rides", trending_rides, 3600
) # Cache for 1 hour
else:
# Fallback to highest rated rides if no trending data
trending_rides = Ride.objects.exclude(
average_rating__isnull=True
).order_by("-average_rating")[:10]
except Exception as e:
log_exception(
logger,
e,
context={"operation": "get_trending_rides", "fallback": True},
request=self.request,
)
# Fallback to highest rated rides if trending calculation fails
trending_rides = Ride.objects.exclude(
average_rating__isnull=True
).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).order_by(
"-average_rating"
)[:20]
) # Get more items to randomly select from
highest_rated_rides = list(
Ride.objects.exclude(average_rating__isnull=True).order_by(
"-average_rating"
)[:20]
) # Get more items to randomly select from
# Combine and shuffle highest rated items
all_highest_rated = highest_rated_parks + highest_rated_rides
secrets.SystemRandom().shuffle(all_highest_rated)
# Keep the same context variable names for template compatibility
context["popular_parks"] = trending_parks
context["popular_rides"] = trending_rides
context["highest_rated"] = all_highest_rated[
:10
] # Take first 10 after shuffling
return context
class SearchView(TemplateView):
template_name = "search_results.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if query := self.request.GET.get("q", "").strip():
# Search parks
context["parks"] = (
Park.objects.filter(
Q(name__icontains=query)
| Q(location__icontains=query)
| Q(description__icontains=query)
)
.select_related("operating_company")
.prefetch_related("photos")[:10]
)
# Search rides
context["rides"] = (
Ride.objects.filter(
Q(name__icontains=query)
| Q(description__icontains=query)
| Q(manufacturer__name__icontains=query)
)
.select_related("park", "coaster_stats")
.prefetch_related("photos")[:10]
)
# Search companies
context["companies"] = Company.objects.filter(
Q(name__icontains=query) | Q(description__icontains=query)
).prefetch_related("operated_parks", "owned_parks")[:10]
logger.info(
f"Search query: '{query}' returned {len(context['parks'])} parks, "
f"{len(context['rides'])} rides, {len(context['companies'])} companies",
extra={
"query": query,
"parks_count": len(context["parks"]),
"rides_count": len(context["rides"]),
"companies_count": len(context["companies"]),
"user_id": (
self.request.user.id
if self.request.user.is_authenticated
else None
),
},
)
return context
def environment_and_settings_view(request):
# Get all environment variables
env_vars = dict(os.environ)
# Get all Django settings as a dictionary
settings_vars = {
setting: getattr(settings, setting)
for setting in dir(settings)
if setting.isupper()
}
return render(
request,
"environment_and_settings.html",
{"env_vars": env_vars, "settings_vars": settings_vars},
)