Files
thrillwiki_django_no_react/rides/views.py
2024-10-31 22:32:01 +00:00

241 lines
9.2 KiB
Python

from django.views.generic import DetailView, ListView, CreateView, UpdateView
from django.shortcuts import get_object_or_404
from django.core.serializers.json import DjangoJSONEncoder
from django.urls import reverse
from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.contrib import messages
from django.http import JsonResponse, HttpResponseRedirect
from .models import Ride, RollerCoasterStats
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
class RideCreateView(LoginRequiredMixin, CreateView):
model = Ride
form_class = RideForm
template_name = 'rides/ride_form.html'
def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
self.park = get_object_or_404(Park, slug=self.kwargs['park_slug'])
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['park'] = self.park
return kwargs
def form_valid(self, form):
form.instance.park = self.park
cleaned_data = form.cleaned_data.copy()
cleaned_data['park'] = self.park.id
# Convert model instances to IDs for JSON serialization
if cleaned_data.get('park_area'):
cleaned_data['park_area'] = cleaned_data['park_area'].id
if cleaned_data.get('manufacturer'):
cleaned_data['manufacturer'] = cleaned_data['manufacturer'].id
# Create submission record
submission = EditSubmission.objects.create(
user=self.request.user,
content_type=ContentType.objects.get_for_model(Ride),
submission_type='CREATE',
changes=cleaned_data,
reason=self.request.POST.get('reason', ''),
source=self.request.POST.get('source', '')
)
# If user is moderator or above, auto-approve
if self.request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
self.object = form.save()
submission.object_id = self.object.id
submission.status = 'APPROVED'
submission.handled_by = self.request.user
submission.save()
messages.success(self.request, f'Successfully created {self.object.name}')
return HttpResponseRedirect(self.get_success_url())
messages.success(self.request, 'Your ride submission has been sent for review')
return HttpResponseRedirect(reverse('parks:rides:ride_list', kwargs={'park_slug': self.park.slug}))
def get_success_url(self):
return reverse('parks:rides:ride_detail', kwargs={
'park_slug': self.park.slug,
'ride_slug': self.object.slug
})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['park'] = self.park
return context
class RideUpdateView(LoginRequiredMixin, UpdateView):
model = Ride
form_class = RideForm
template_name = 'rides/ride_form.html'
slug_url_kwarg = 'ride_slug'
def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
self.park = get_object_or_404(Park, slug=self.kwargs['park_slug'])
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['park'] = self.park
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['park'] = self.park
context['is_edit'] = True
return context
def form_valid(self, form):
cleaned_data = form.cleaned_data.copy()
cleaned_data['park'] = self.park.id
# Convert model instances to IDs for JSON serialization
if cleaned_data.get('park_area'):
cleaned_data['park_area'] = cleaned_data['park_area'].id
if cleaned_data.get('manufacturer'):
cleaned_data['manufacturer'] = cleaned_data['manufacturer'].id
# Create submission record
submission = EditSubmission.objects.create(
user=self.request.user,
content_type=ContentType.objects.get_for_model(Ride),
object_id=self.object.id,
submission_type='EDIT',
changes=cleaned_data,
reason=self.request.POST.get('reason', ''),
source=self.request.POST.get('source', '')
)
# If user is moderator or above, auto-approve
if self.request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
self.object = form.save()
submission.status = 'APPROVED'
submission.handled_by = self.request.user
submission.save()
messages.success(self.request, f'Successfully updated {self.object.name}')
return HttpResponseRedirect(self.get_success_url())
messages.success(self.request, f'Your changes to {self.object.name} have been sent for review')
return HttpResponseRedirect(reverse('parks:rides:ride_detail', kwargs={
'park_slug': self.park.slug,
'ride_slug': self.object.slug
}))
def get_success_url(self):
return reverse('parks:rides:ride_detail', kwargs={
'park_slug': self.park.slug,
'ride_slug': self.object.slug
})
class RideDetailView(SlugRedirectMixin, EditSubmissionMixin, PhotoSubmissionMixin, HistoryMixin, DetailView):
model = Ride
template_name = 'rides/ride_detail.html'
context_object_name = 'ride'
slug_url_kwarg = 'ride_slug'
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
park_slug = self.kwargs.get('park_slug')
ride_slug = self.kwargs.get('ride_slug')
# Try to get by current or historical slug
obj, is_old_slug = self.model.get_by_slug(ride_slug)
if obj.park.slug != park_slug:
raise self.model.DoesNotExist("Park slug doesn't match")
return obj
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.object.category == 'RC':
context['coaster_stats'] = RollerCoasterStats.objects.filter(ride=self.object).first()
return context
def get_redirect_url_pattern(self):
return 'parks:rides:ride_detail'
def get_redirect_url_kwargs(self):
return {
'park_slug': self.object.park.slug,
'ride_slug': self.object.slug
}
class RideListView(ListView):
model = Ride
template_name = 'rides/ride_list.html'
context_object_name = 'rides'
def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
self.park = None
if 'park_slug' in self.kwargs:
self.park = get_object_or_404(Park, slug=self.kwargs['park_slug'])
def get_queryset(self):
queryset = Ride.objects.select_related('park', 'coaster_stats', 'manufacturer').prefetch_related('photos')
# Filter by park if viewing park-specific rides
if self.park:
queryset = queryset.filter(park=self.park)
search = self.request.GET.get('search', '').strip() or None
category = self.request.GET.get('category', '').strip() or None
status = self.request.GET.get('status', '').strip() or None
manufacturer = self.request.GET.get('manufacturer', '').strip() or None
if search:
if self.park:
queryset = queryset.filter(name__icontains=search)
else:
queryset = queryset.filter(
Q(name__icontains=search) |
Q(park__name__icontains=search)
)
if category:
queryset = queryset.filter(category=category)
if status:
queryset = queryset.filter(status=status)
if manufacturer:
queryset = queryset.exclude(manufacturer__isnull=True)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['park'] = self.park
# Get manufacturers for the filter dropdown
manufacturer_query = Ride.objects
if self.park:
manufacturer_query = manufacturer_query.filter(park=self.park)
context['manufacturers'] = list(
manufacturer_query.exclude(manufacturer__isnull=True)
.values_list('manufacturer__name', flat=True)
.distinct().order_by('manufacturer__name')
)
# Add current filter values to context
context['current_filters'] = {
'search': self.request.GET.get('search', ''),
'category': self.request.GET.get('category', ''),
'status': self.request.GET.get('status', ''),
'manufacturer': self.request.GET.get('manufacturer', '')
}
return context
def get(self, request, *args, **kwargs):
# Check if this is an HTMX request
if request.htmx:
# If it is, return just the rides list partial
self.template_name = 'rides/partials/ride_list.html'
return super().get(request, *args, **kwargs)