From df91eb97b88f67be7e21a87988fa87326d141340 Mon Sep 17 00:00:00 2001 From: pacnpal <183241239+pacnpal@users.noreply.github.com> Date: Mon, 10 Feb 2025 14:48:29 -0500 Subject: [PATCH] Add ParkContextRequired mixin to enforce park context in ride views; update URLs and templates for global ride listing --- rides/views.py | 65 +++++++++++++++------------------- templates/base/base.html | 2 +- templates/home.html | 10 +++--- templates/rides/ride_list.html | 9 ++--- 4 files changed, 36 insertions(+), 50 deletions(-) diff --git a/rides/views.py b/rides/views.py index 7461da93..1eeb7126 100644 --- a/rides/views.py +++ b/rides/views.py @@ -7,7 +7,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.decorators import login_required from django.contrib.contenttypes.models import ContentType from django.contrib import messages -from django.http import HttpRequest, HttpResponse +from django.http import HttpRequest, HttpResponse, Http404 from django.db.models import Count from .models import ( Ride, RollerCoasterStats, RideModel, RideEvent, @@ -21,6 +21,13 @@ from moderation.models import EditSubmission from companies.models import Manufacturer from designers.models import Designer +class ParkContextRequired: + """Mixin to require park context for views""" + def dispatch(self, request, *args, **kwargs): + if 'park_slug' not in self.kwargs: + raise Http404("Park context is required") + return super().dispatch(request, *args, **kwargs) + def show_coaster_fields(request: HttpRequest) -> HttpResponse: """Show roller coaster specific fields based on category selection""" category = request.GET.get('category') @@ -61,7 +68,7 @@ class RideDetailView(HistoryMixin, DetailView): return context -class RideCreateView(LoginRequiredMixin, CreateView): +class RideCreateView(LoginRequiredMixin, ParkContextRequired, CreateView): """View for creating a new ride""" model = Ride form_class = RideForm @@ -69,27 +76,23 @@ class RideCreateView(LoginRequiredMixin, CreateView): def get_success_url(self): """Get URL to redirect to after successful creation""" - if hasattr(self, 'park'): - return reverse('parks:rides:ride_detail', kwargs={ - 'park_slug': self.park.slug, - 'ride_slug': self.object.slug - }) - return reverse('rides:ride_detail', kwargs={'ride_slug': self.object.slug}) + return reverse('parks:rides:ride_detail', kwargs={ + 'park_slug': self.park.slug, + 'ride_slug': self.object.slug + }) def get_form_kwargs(self): """Pass park to the form""" kwargs = super().get_form_kwargs() - if 'park_slug' in self.kwargs: - self.park = get_object_or_404(Park, slug=self.kwargs['park_slug']) - kwargs['park'] = self.park + self.park = get_object_or_404(Park, slug=self.kwargs['park_slug']) + kwargs['park'] = self.park return kwargs def get_context_data(self, **kwargs): """Add park and park_slug to context""" context = super().get_context_data(**kwargs) - if hasattr(self, 'park'): - context['park'] = self.park - context['park_slug'] = self.park.slug + context['park'] = self.park + context['park_slug'] = self.park.slug context['is_edit'] = False return context @@ -131,7 +134,7 @@ class RideCreateView(LoginRequiredMixin, CreateView): return super().form_valid(form) -class RideUpdateView(LoginRequiredMixin, EditSubmissionMixin, UpdateView): +class RideUpdateView(LoginRequiredMixin, ParkContextRequired, EditSubmissionMixin, UpdateView): """View for updating an existing ride""" model = Ride form_class = RideForm @@ -140,39 +143,27 @@ class RideUpdateView(LoginRequiredMixin, EditSubmissionMixin, UpdateView): def get_success_url(self): """Get URL to redirect to after successful update""" - if hasattr(self, 'park'): - return reverse('parks:rides:ride_detail', kwargs={ - 'park_slug': self.park.slug, - 'ride_slug': self.object.slug - }) - return reverse('rides:ride_detail', kwargs={'ride_slug': self.object.slug}) + return reverse('parks:rides:ride_detail', kwargs={ + 'park_slug': self.park.slug, + 'ride_slug': self.object.slug + }) def get_queryset(self): - """Get ride for the specific park if park_slug is provided""" - queryset = Ride.objects.all() - if 'park_slug' in self.kwargs: - queryset = queryset.filter(park__slug=self.kwargs['park_slug']) - return queryset + """Get ride for the specific park""" + return Ride.objects.filter(park__slug=self.kwargs['park_slug']) def get_form_kwargs(self): """Pass park to the form""" kwargs = super().get_form_kwargs() - # For park-specific URLs, use the park from the URL - if 'park_slug' in self.kwargs: - self.park = get_object_or_404(Park, slug=self.kwargs['park_slug']) - kwargs['park'] = self.park - # For global URLs, use the ride's park - else: - self.park = self.get_object().park - kwargs['park'] = self.park + self.park = get_object_or_404(Park, slug=self.kwargs['park_slug']) + kwargs['park'] = self.park return kwargs def get_context_data(self, **kwargs): """Add park and park_slug to context""" context = super().get_context_data(**kwargs) - if hasattr(self, 'park'): - context['park'] = self.park - context['park_slug'] = self.park.slug + context['park'] = self.park + context['park_slug'] = self.park.slug context['is_edit'] = True return context diff --git a/templates/base/base.html b/templates/base/base.html index 90173632..7343ddfc 100644 --- a/templates/base/base.html +++ b/templates/base/base.html @@ -99,7 +99,7 @@ Parks - + Rides diff --git a/templates/home.html b/templates/home.html index de15bfa7..fb4a3a69 100644 --- a/templates/home.html +++ b/templates/home.html @@ -18,7 +18,7 @@ class="px-8 py-3 text-lg btn-primary"> Explore Parks - View Rides @@ -40,7 +40,7 @@ -
{{ stats.ride_count }} @@ -51,7 +51,7 @@ -
{{ stats.coaster_count }} @@ -108,7 +108,7 @@ @@ -45,7 +40,7 @@