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

292 lines
11 KiB
Python

from django.views.generic import DetailView, ListView, CreateView, UpdateView
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
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, HttpResponse
from .models import Park, ParkArea
from .forms import ParkForm
from rides.models import Ride
from core.views import SlugRedirectMixin
from moderation.mixins import EditSubmissionMixin, PhotoSubmissionMixin, HistoryMixin
from moderation.models import EditSubmission
from cities_light.models import Country, Region, City
def get_countries(request):
query = request.GET.get('q', '')
filter_parks = request.GET.get('filter_parks', 'false') == 'true'
# Base query
countries = Country.objects.filter(name__icontains=query)
# Only filter by parks if explicitly requested
if filter_parks:
countries = countries.filter(park__isnull=False)
countries = countries.distinct().values('id', 'name')[:10]
return JsonResponse(list(countries), safe=False)
def get_regions(request):
query = request.GET.get('q', '')
country = request.GET.get('country', '')
filter_parks = request.GET.get('filter_parks', 'false') == 'true'
if not country:
return JsonResponse([], safe=False)
# Base query
regions = Region.objects.filter(
Q(name__icontains=query) | Q(alternate_names__icontains=query),
country__name__iexact=country
)
# Only filter by parks if explicitly requested
if filter_parks:
regions = regions.filter(park__isnull=False)
regions = regions.distinct().values('id', 'name')[:10]
return JsonResponse(list(regions), safe=False)
def get_cities(request):
query = request.GET.get('q', '')
region = request.GET.get('region', '')
country = request.GET.get('country', '')
filter_parks = request.GET.get('filter_parks', 'false') == 'true'
if not region or not country:
return JsonResponse([], safe=False)
# Base query
cities = City.objects.filter(
Q(name__icontains=query) | Q(alternate_names__icontains=query),
region__name__iexact=region,
region__country__name__iexact=country
)
# Only filter by parks if explicitly requested
if filter_parks:
cities = cities.filter(park__isnull=False)
cities = cities.distinct().values('id', 'name')[:10]
return JsonResponse(list(cities), safe=False)
class ParkCreateView(LoginRequiredMixin, CreateView):
model = Park
form_class = ParkForm
template_name = 'parks/park_form.html'
def prepare_changes_data(self, cleaned_data):
data = cleaned_data.copy()
# Convert model instances to IDs for JSON serialization
if data.get('owner'):
data['owner'] = data['owner'].id
if data.get('country'):
data['country'] = data['country'].id
if data.get('region'):
data['region'] = data['region'].id
if data.get('city'):
data['city'] = data['city'].id
# Convert dates to ISO format strings
if data.get('opening_date'):
data['opening_date'] = data['opening_date'].isoformat()
if data.get('closing_date'):
data['closing_date'] = data['closing_date'].isoformat()
return data
def form_valid(self, form):
changes = self.prepare_changes_data(form.cleaned_data)
# Create submission record
submission = EditSubmission.objects.create(
user=self.request.user,
content_type=ContentType.objects.get_for_model(Park),
submission_type='CREATE',
changes=changes,
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 park submission has been sent for review')
return HttpResponseRedirect(reverse('parks:park_list'))
def get_success_url(self):
return reverse('parks:park_detail', kwargs={'slug': self.object.slug})
class ParkUpdateView(LoginRequiredMixin, UpdateView):
model = Park
form_class = ParkForm
template_name = 'parks/park_form.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['is_edit'] = True
return context
def prepare_changes_data(self, cleaned_data):
data = cleaned_data.copy()
# Convert model instances to IDs for JSON serialization
if data.get('owner'):
data['owner'] = data['owner'].id
if data.get('country'):
data['country'] = data['country'].id
if data.get('region'):
data['region'] = data['region'].id
if data.get('city'):
data['city'] = data['city'].id
# Convert dates to ISO format strings
if data.get('opening_date'):
data['opening_date'] = data['opening_date'].isoformat()
if data.get('closing_date'):
data['closing_date'] = data['closing_date'].isoformat()
return data
def form_valid(self, form):
changes = self.prepare_changes_data(form.cleaned_data)
# Create submission record
submission = EditSubmission.objects.create(
user=self.request.user,
content_type=ContentType.objects.get_for_model(Park),
object_id=self.object.id,
submission_type='EDIT',
changes=changes,
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:park_detail', kwargs={'slug': self.object.slug}))
def get_success_url(self):
return reverse('parks:park_detail', kwargs={'slug': self.object.slug})
class ParkDetailView(SlugRedirectMixin, EditSubmissionMixin, PhotoSubmissionMixin, HistoryMixin, DetailView):
model = Park
template_name = 'parks/park_detail.html'
context_object_name = 'park'
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
slug = self.kwargs.get(self.slug_url_kwarg)
# Try to get by current or historical slug
return self.model.get_by_slug(slug)[0]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['rides'] = Ride.objects.filter(
park=self.object
).select_related('coaster_stats')
context['areas'] = ParkArea.objects.filter(park=self.object)
return context
def get_redirect_url_pattern(self):
return 'parks:park_detail'
class ParkAreaDetailView(SlugRedirectMixin, EditSubmissionMixin, PhotoSubmissionMixin, HistoryMixin, DetailView):
model = ParkArea
template_name = 'parks/area_detail.html'
context_object_name = 'area'
slug_url_kwarg = 'area_slug'
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
park_slug = self.kwargs.get('park_slug')
area_slug = self.kwargs.get('area_slug')
# Try to get by current or historical slug
obj, is_old_slug = self.model.get_by_slug(area_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)
context['rides'] = Ride.objects.filter(
area=self.object
).select_related('coaster_stats')
return context
def get_redirect_url_pattern(self):
return 'parks:park_detail'
def get_redirect_url_kwargs(self):
return {
'park_slug': self.object.park.slug,
'area_slug': self.object.slug
}
class ParkListView(ListView):
model = Park
template_name = 'parks/park_list.html'
context_object_name = 'parks'
def get_queryset(self):
queryset = Park.objects.select_related('owner', 'country', 'region', 'city').prefetch_related('photos', 'rides')
search = self.request.GET.get('search', '').strip()
country = self.request.GET.get('country', '').strip()
region = self.request.GET.get('region', '').strip()
city = self.request.GET.get('city', '').strip()
statuses = self.request.GET.getlist('status')
if search:
queryset = queryset.filter(
Q(name__icontains=search) |
Q(location__icontains=search)
)
if country:
queryset = queryset.filter(country__name__icontains=country)
if region:
queryset = queryset.filter(region__name__icontains=region)
if city:
queryset = queryset.filter(city__name__icontains=city)
if statuses:
queryset = queryset.filter(status__in=statuses)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['current_filters'] = {
'search': self.request.GET.get('search', ''),
'country': self.request.GET.get('country', ''),
'region': self.request.GET.get('region', ''),
'city': self.request.GET.get('city', ''),
'statuses': self.request.GET.getlist('status')
}
return context
def get(self, request, *args, **kwargs):
# Check if this is an HTMX request
if request.htmx:
# If it is, return just the parks list partial
self.template_name = 'parks/partials/park_list.html'
return super().get(request, *args, **kwargs)