mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 09:31:09 -05:00
359 lines
13 KiB
Python
359 lines
13 KiB
Python
from typing import Any, Dict, Optional, Tuple, Union, cast, Type
|
|
from django.views.generic import DetailView, ListView, CreateView, UpdateView, RedirectView
|
|
from django.shortcuts import get_object_or_404, render
|
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
from django.urls import reverse
|
|
from django.db.models import Q, Model
|
|
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 (
|
|
JsonResponse,
|
|
HttpResponseRedirect,
|
|
Http404,
|
|
HttpRequest,
|
|
HttpResponse,
|
|
)
|
|
from django.db.models import Count
|
|
from django.core.files.uploadedfile import UploadedFile
|
|
from django.forms import ModelForm
|
|
from django.db.models.query import QuerySet
|
|
from simple_history.models import HistoricalRecords
|
|
from django.contrib.auth import get_user_model
|
|
from django.contrib.auth.models import AnonymousUser
|
|
from .models import Ride, RollerCoasterStats, RideModel, CATEGORY_CHOICES
|
|
from .forms import RideForm
|
|
from parks.models import Park
|
|
from core.views import SlugRedirectMixin
|
|
from moderation.mixins import EditSubmissionMixin, PhotoSubmissionMixin, HistoryMixin
|
|
from moderation.models import EditSubmission
|
|
from media.models import Photo
|
|
from accounts.models import User
|
|
from companies.models import Manufacturer
|
|
from designers.models import Designer
|
|
|
|
|
|
def show_coaster_fields(request: HttpRequest) -> HttpResponse:
|
|
"""Show roller coaster specific fields based on category selection"""
|
|
category = request.GET.get('category')
|
|
if category != 'RC': # Only show for roller coasters
|
|
return HttpResponse('')
|
|
return render(request, "rides/partials/coaster_fields.html")
|
|
|
|
|
|
class RideCreateView(LoginRequiredMixin, CreateView):
|
|
"""View for creating a new ride"""
|
|
model = Ride
|
|
form_class = RideForm
|
|
template_name = 'rides/ride_form.html'
|
|
|
|
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})
|
|
|
|
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
|
|
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['is_edit'] = False
|
|
return context
|
|
|
|
def form_valid(self, form):
|
|
"""Handle form submission including new items"""
|
|
# Check for new manufacturer
|
|
manufacturer_name = form.cleaned_data.get('manufacturer_search')
|
|
if manufacturer_name and not form.cleaned_data.get('manufacturer'):
|
|
# Create submission for new manufacturer
|
|
EditSubmission.objects.create(
|
|
user=self.request.user,
|
|
content_type=ContentType.objects.get_for_model(Manufacturer),
|
|
submission_type="CREATE",
|
|
changes={"name": manufacturer_name},
|
|
)
|
|
|
|
# Check for new designer
|
|
designer_name = form.cleaned_data.get('designer_search')
|
|
if designer_name and not form.cleaned_data.get('designer'):
|
|
# Create submission for new designer
|
|
EditSubmission.objects.create(
|
|
user=self.request.user,
|
|
content_type=ContentType.objects.get_for_model(Designer),
|
|
submission_type="CREATE",
|
|
changes={"name": designer_name},
|
|
)
|
|
|
|
# Check for new ride model
|
|
ride_model_name = form.cleaned_data.get('ride_model_search')
|
|
manufacturer = form.cleaned_data.get('manufacturer')
|
|
if ride_model_name and not form.cleaned_data.get('ride_model') and manufacturer:
|
|
# Create submission for new ride model
|
|
EditSubmission.objects.create(
|
|
user=self.request.user,
|
|
content_type=ContentType.objects.get_for_model(RideModel),
|
|
submission_type="CREATE",
|
|
changes={
|
|
"name": ride_model_name,
|
|
"manufacturer": manufacturer.id
|
|
},
|
|
)
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
class RideDetailView(DetailView):
|
|
"""View for displaying ride details"""
|
|
model = Ride
|
|
template_name = 'rides/ride_detail.html'
|
|
slug_url_kwarg = 'ride_slug'
|
|
|
|
def get_queryset(self):
|
|
"""Get ride for the specific park if park_slug is provided"""
|
|
queryset = Ride.objects.all().select_related(
|
|
'park',
|
|
'ride_model',
|
|
'ride_model__manufacturer'
|
|
).prefetch_related('photos')
|
|
|
|
if 'park_slug' in self.kwargs:
|
|
queryset = queryset.filter(park__slug=self.kwargs['park_slug'])
|
|
|
|
return queryset
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""Add park_slug to context if it exists"""
|
|
context = super().get_context_data(**kwargs)
|
|
if 'park_slug' in self.kwargs:
|
|
context['park_slug'] = self.kwargs['park_slug']
|
|
return context
|
|
|
|
|
|
class RideUpdateView(LoginRequiredMixin, EditSubmissionMixin, UpdateView):
|
|
"""View for updating an existing ride"""
|
|
model = Ride
|
|
form_class = RideForm
|
|
template_name = 'rides/ride_form.html'
|
|
slug_url_kwarg = 'ride_slug'
|
|
|
|
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})
|
|
|
|
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
|
|
|
|
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
|
|
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['is_edit'] = True
|
|
return context
|
|
|
|
def form_valid(self, form):
|
|
"""Handle form submission including new items"""
|
|
# Check for new manufacturer
|
|
manufacturer_name = form.cleaned_data.get('manufacturer_search')
|
|
if manufacturer_name and not form.cleaned_data.get('manufacturer'):
|
|
# Create submission for new manufacturer
|
|
EditSubmission.objects.create(
|
|
user=self.request.user,
|
|
content_type=ContentType.objects.get_for_model(Manufacturer),
|
|
submission_type="CREATE",
|
|
changes={"name": manufacturer_name},
|
|
)
|
|
|
|
# Check for new designer
|
|
designer_name = form.cleaned_data.get('designer_search')
|
|
if designer_name and not form.cleaned_data.get('designer'):
|
|
# Create submission for new designer
|
|
EditSubmission.objects.create(
|
|
user=self.request.user,
|
|
content_type=ContentType.objects.get_for_model(Designer),
|
|
submission_type="CREATE",
|
|
changes={"name": designer_name},
|
|
)
|
|
|
|
# Check for new ride model
|
|
ride_model_name = form.cleaned_data.get('ride_model_search')
|
|
manufacturer = form.cleaned_data.get('manufacturer')
|
|
if ride_model_name and not form.cleaned_data.get('ride_model') and manufacturer:
|
|
# Create submission for new ride model
|
|
EditSubmission.objects.create(
|
|
user=self.request.user,
|
|
content_type=ContentType.objects.get_for_model(RideModel),
|
|
submission_type="CREATE",
|
|
changes={
|
|
"name": ride_model_name,
|
|
"manufacturer": manufacturer.id
|
|
},
|
|
)
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
class RideListView(ListView):
|
|
"""View for displaying a list of rides"""
|
|
model = Ride
|
|
template_name = 'rides/ride_list.html'
|
|
context_object_name = 'rides'
|
|
|
|
def get_queryset(self):
|
|
"""Get all rides or filter by park if park_slug is provided"""
|
|
queryset = Ride.objects.all().select_related(
|
|
'park',
|
|
'ride_model',
|
|
'ride_model__manufacturer'
|
|
).prefetch_related('photos')
|
|
|
|
if 'park_slug' in self.kwargs:
|
|
self.park = get_object_or_404(Park, slug=self.kwargs['park_slug'])
|
|
queryset = queryset.filter(park=self.park)
|
|
|
|
return queryset
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""Add park to context if park_slug is provided"""
|
|
context = super().get_context_data(**kwargs)
|
|
if hasattr(self, 'park'):
|
|
context['park'] = self.park
|
|
context['park_slug'] = self.kwargs['park_slug']
|
|
return context
|
|
|
|
|
|
class SingleCategoryListView(ListView):
|
|
"""View for displaying rides of a specific category"""
|
|
model = Ride
|
|
template_name = 'rides/park_category_list.html'
|
|
context_object_name = 'rides'
|
|
|
|
def get_queryset(self):
|
|
"""Get rides filtered by category and optionally by park"""
|
|
category = self.kwargs.get('category')
|
|
queryset = Ride.objects.filter(
|
|
category=category
|
|
).select_related(
|
|
'park',
|
|
'ride_model',
|
|
'ride_model__manufacturer'
|
|
)
|
|
|
|
if 'park_slug' in self.kwargs:
|
|
self.park = get_object_or_404(Park, slug=self.kwargs['park_slug'])
|
|
queryset = queryset.filter(park=self.park)
|
|
|
|
return queryset
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""Add park and category information to context"""
|
|
context = super().get_context_data(**kwargs)
|
|
if hasattr(self, 'park'):
|
|
context['park'] = self.park
|
|
context['park_slug'] = self.kwargs['park_slug']
|
|
context['category'] = dict(CATEGORY_CHOICES).get(self.kwargs['category'])
|
|
return context
|
|
|
|
|
|
# Alias for parks app to maintain backward compatibility
|
|
ParkSingleCategoryListView = SingleCategoryListView
|
|
|
|
|
|
def is_privileged_user(user: Any) -> bool:
|
|
"""Check if user has privileged access"""
|
|
return bool(user and hasattr(user, 'is_staff') and (user.is_staff or user.is_superuser))
|
|
|
|
|
|
@login_required
|
|
def search_manufacturers(request: HttpRequest) -> HttpResponse:
|
|
"""Search manufacturers and return results for HTMX"""
|
|
query = request.GET.get("q", "").strip()
|
|
|
|
# Show all manufacturers on click, filter on input
|
|
manufacturers = Manufacturer.objects.all().order_by("name")
|
|
if query:
|
|
manufacturers = manufacturers.filter(name__icontains=query)
|
|
manufacturers = manufacturers[:10]
|
|
|
|
return render(
|
|
request,
|
|
"rides/partials/manufacturer_search_results.html",
|
|
{"manufacturers": manufacturers, "search_term": query},
|
|
)
|
|
|
|
|
|
@login_required
|
|
def search_designers(request: HttpRequest) -> HttpResponse:
|
|
"""Search designers and return results for HTMX"""
|
|
query = request.GET.get("q", "").strip()
|
|
|
|
# Show all designers on click, filter on input
|
|
designers = Designer.objects.all().order_by("name")
|
|
if query:
|
|
designers = designers.filter(name__icontains=query)
|
|
designers = designers[:10]
|
|
|
|
return render(
|
|
request,
|
|
"rides/partials/designer_search_results.html",
|
|
{"designers": designers, "search_term": query},
|
|
)
|
|
|
|
|
|
@login_required
|
|
def search_ride_models(request: HttpRequest) -> HttpResponse:
|
|
"""Search ride models and return results for HTMX"""
|
|
query = request.GET.get("q", "").strip()
|
|
manufacturer_id = request.GET.get("manufacturer")
|
|
|
|
# Show all ride models on click, filter on input
|
|
ride_models = RideModel.objects.select_related("manufacturer").order_by("name")
|
|
if query:
|
|
ride_models = ride_models.filter(name__icontains=query)
|
|
if manufacturer_id:
|
|
ride_models = ride_models.filter(manufacturer_id=manufacturer_id)
|
|
ride_models = ride_models[:10]
|
|
|
|
return render(
|
|
request,
|
|
"rides/partials/ride_model_search_results.html",
|
|
{"ride_models": ride_models, "search_term": query, "manufacturer_id": manufacturer_id},
|
|
)
|