add category views for each type of ride, add ride designers

This commit is contained in:
pacnpal
2024-11-04 00:33:19 +00:00
parent 07526dcba8
commit ae913e757a
35 changed files with 1607 additions and 275 deletions

View File

@@ -4,7 +4,7 @@ from .models import Ride
class RideForm(forms.ModelForm):
class Meta:
model = Ride
fields = ['name', 'park_area', 'category', 'manufacturer', 'model_name', 'status',
fields = ['name', 'park_area', 'category', 'manufacturer', 'designer', 'model_name', 'status',
'opening_date', 'closing_date', 'status_since', 'min_height_in', 'max_height_in',
'accessibility_options', 'capacity_per_hour', 'ride_duration_seconds', 'description']
widgets = {
@@ -20,6 +20,9 @@ class RideForm(forms.ModelForm):
'manufacturer': forms.Select(attrs={
'class': 'w-full border-gray-300 rounded-lg form-select dark:border-gray-600 dark:bg-gray-700 dark:text-white'
}),
'designer': forms.Select(attrs={
'class': 'w-full border-gray-300 rounded-lg form-select dark:border-gray-600 dark:bg-gray-700 dark:text-white'
}),
'model_name': forms.TextInput(attrs={
'class': 'w-full border-gray-300 rounded-lg form-input dark:border-gray-600 dark:bg-gray-700 dark:text-white'
}),

View File

@@ -0,0 +1,65 @@
# Generated by Django 5.1.2 on 2024-11-04 00:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("rides", "0002_alter_ride_manufacturer"),
]
operations = [
migrations.AddField(
model_name="historicalrollercoasterstats",
name="max_drop_height_ft",
field=models.DecimalField(
blank=True,
decimal_places=2,
help_text="Maximum vertical drop height in feet",
max_digits=6,
null=True,
),
),
migrations.AddField(
model_name="historicalrollercoasterstats",
name="track_material",
field=models.CharField(
blank=True,
choices=[
("STEEL", "Steel"),
("WOOD", "Wood"),
("HYBRID", "Hybrid"),
("OTHER", "Other"),
],
default="STEEL",
max_length=20,
),
),
migrations.AddField(
model_name="rollercoasterstats",
name="max_drop_height_ft",
field=models.DecimalField(
blank=True,
decimal_places=2,
help_text="Maximum vertical drop height in feet",
max_digits=6,
null=True,
),
),
migrations.AddField(
model_name="rollercoasterstats",
name="track_material",
field=models.CharField(
blank=True,
choices=[
("STEEL", "Steel"),
("WOOD", "Wood"),
("HYBRID", "Hybrid"),
("OTHER", "Other"),
],
default="STEEL",
max_length=20,
),
),
]

View File

@@ -0,0 +1,69 @@
# Generated by Django 5.1.2 on 2024-11-04 00:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("rides", "0003_historicalrollercoasterstats_max_drop_height_ft_and_more"),
]
operations = [
migrations.AddField(
model_name="historicalrollercoasterstats",
name="roller_coaster_type",
field=models.CharField(
blank=True,
choices=[
("SITDOWN", "Sit-Down"),
("INVERTED", "Inverted"),
("FLYING", "Flying"),
("STANDUP", "Stand-Up"),
("WING", "Wing"),
("SUSPENDED", "Suspended"),
("BOBSLED", "Bobsled"),
("PIPELINE", "Pipeline"),
("MOTORBIKE", "Motorbike"),
("FLOORLESS", "Floorless"),
("DIVE", "Dive"),
("FAMILY", "Family"),
("WILD_MOUSE", "Wild Mouse"),
("SPINNING", "Spinning"),
("FOURTH_DIMENSION", "4th Dimension"),
("OTHER", "Other"),
],
default="SITDOWN",
help_text="The type/style of roller coaster (e.g. Sit-Down, Inverted, Flying)",
max_length=20,
),
),
migrations.AddField(
model_name="rollercoasterstats",
name="roller_coaster_type",
field=models.CharField(
blank=True,
choices=[
("SITDOWN", "Sit-Down"),
("INVERTED", "Inverted"),
("FLYING", "Flying"),
("STANDUP", "Stand-Up"),
("WING", "Wing"),
("SUSPENDED", "Suspended"),
("BOBSLED", "Bobsled"),
("PIPELINE", "Pipeline"),
("MOTORBIKE", "Motorbike"),
("FLOORLESS", "Floorless"),
("DIVE", "Dive"),
("FAMILY", "Family"),
("WILD_MOUSE", "Wild Mouse"),
("SPINNING", "Spinning"),
("FOURTH_DIMENSION", "4th Dimension"),
("OTHER", "Other"),
],
default="SITDOWN",
help_text="The type/style of roller coaster (e.g. Sit-Down, Inverted, Flying)",
max_length=20,
),
),
]

View File

@@ -0,0 +1,40 @@
# Generated by Django 5.1.2 on 2024-11-04 00:28
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("designers", "0001_initial"),
("rides", "0004_historicalrollercoasterstats_roller_coaster_type_and_more"),
]
operations = [
migrations.AddField(
model_name="historicalride",
name="designer",
field=models.ForeignKey(
blank=True,
db_constraint=False,
help_text="The designer/engineering firm responsible for the ride",
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="designers.designer",
),
),
migrations.AddField(
model_name="ride",
name="designer",
field=models.ForeignKey(
blank=True,
help_text="The designer/engineering firm responsible for the ride",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="rides",
to="designers.designer",
),
),
]

View File

@@ -43,10 +43,19 @@ class Ride(models.Model):
default='OT'
)
manufacturer = models.ForeignKey(
'companies.manufacturer', on_delete=models.CASCADE, null=False, blank=False
)
# other fields...
'companies.manufacturer',
on_delete=models.CASCADE,
null=False,
blank=False
)
designer = models.ForeignKey(
'designers.Designer',
on_delete=models.SET_NULL,
related_name='rides',
null=True,
blank=True,
help_text='The designer/engineering firm responsible for the ride'
)
model_name = models.CharField(max_length=255, blank=True)
status = models.CharField(
max_length=20,
@@ -108,6 +117,32 @@ class RollerCoasterStats(models.Model):
('OTHER', 'Other'),
]
TRACK_MATERIAL_CHOICES = [
('STEEL', 'Steel'),
('WOOD', 'Wood'),
('HYBRID', 'Hybrid'),
('OTHER', 'Other'),
]
COASTER_TYPE_CHOICES = [
('SITDOWN', 'Sit-Down'),
('INVERTED', 'Inverted'),
('FLYING', 'Flying'),
('STANDUP', 'Stand-Up'),
('WING', 'Wing'),
('SUSPENDED', 'Suspended'),
('BOBSLED', 'Bobsled'),
('PIPELINE', 'Pipeline'),
('MOTORBIKE', 'Motorbike'),
('FLOORLESS', 'Floorless'),
('DIVE', 'Dive'),
('FAMILY', 'Family'),
('WILD_MOUSE', 'Wild Mouse'),
('SPINNING', 'Spinning'),
('FOURTH_DIMENSION', '4th Dimension'),
('OTHER', 'Other'),
]
ride = models.OneToOneField(
Ride,
on_delete=models.CASCADE,
@@ -134,6 +169,26 @@ class RollerCoasterStats(models.Model):
inversions = models.PositiveIntegerField(default=0)
ride_time_seconds = models.PositiveIntegerField(null=True, blank=True)
track_type = models.CharField(max_length=255, blank=True)
track_material = models.CharField(
max_length=20,
choices=TRACK_MATERIAL_CHOICES,
default='STEEL',
blank=True
)
roller_coaster_type = models.CharField(
max_length=20,
choices=COASTER_TYPE_CHOICES,
default='SITDOWN',
blank=True,
help_text='The type/style of roller coaster (e.g. Sit-Down, Inverted, Flying)'
)
max_drop_height_ft = models.DecimalField(
max_digits=6,
decimal_places=2,
null=True,
blank=True,
help_text='Maximum vertical drop height in feet'
)
launch_type = models.CharField(
max_length=20,
choices=LAUNCH_CHOICES,

View File

@@ -4,8 +4,17 @@ from . import views
app_name = 'rides' # Add namespace
urlpatterns = [
path('all/', views.RideListView.as_view(), name='all_rides'), # New pattern for all rides
# Global category URLs
path('', views.RideListView.as_view(), name='ride_list'),
path('all/', views.RideListView.as_view(), name='all_rides'),
path('roller_coasters/', views.SingleCategoryListView.as_view(), {'category': 'RC'}, name='roller_coasters'),
path('dark_rides/', views.SingleCategoryListView.as_view(), {'category': 'DR'}, name='dark_rides'),
path('flat_rides/', views.SingleCategoryListView.as_view(), {'category': 'FR'}, name='flat_rides'),
path('water_rides/', views.SingleCategoryListView.as_view(), {'category': 'WR'}, name='water_rides'),
path('transports/', views.SingleCategoryListView.as_view(), {'category': 'TR'}, name='transports'),
path('others/', views.SingleCategoryListView.as_view(), {'category': 'OT'}, name='others'),
# Basic ride URLs
path('create/', views.RideCreateView.as_view(), name='ride_create'),
path('<slug:ride_slug>/edit/', views.RideUpdateView.as_view(), name='ride_edit'),
path('<slug:ride_slug>/', views.RideDetailView.as_view(), name='ride_detail'),

View File

@@ -6,15 +6,79 @@ 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 django.http import JsonResponse, HttpResponseRedirect, Http404
from django.db.models import Count
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
from media.models import Photo
class SingleCategoryListView(ListView):
model = Ride
template_name = 'rides/ride_category_list.html'
context_object_name = 'categories'
def get_category_code(self):
category = self.kwargs.get('category')
if not category:
raise Http404("Category not found")
return category
def get_queryset(self):
category_code = self.get_category_code()
category_name = dict(Ride.CATEGORY_CHOICES)[category_code]
rides = Ride.objects.filter(category=category_code).select_related(
'park', 'manufacturer'
).order_by('name')
return {category_name: rides} if rides.exists() else {}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
category_code = self.get_category_code()
category_name = dict(Ride.CATEGORY_CHOICES)[category_code]
context['title'] = f'All {category_name}s'
context['category_code'] = category_code
return context
class ParkSingleCategoryListView(ListView):
model = Ride
template_name = 'rides/ride_category_list.html'
context_object_name = 'categories'
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_category_code(self):
category = self.kwargs.get('category')
if not category:
raise Http404("Category not found")
return category
def get_queryset(self):
category_code = self.get_category_code()
category_name = dict(Ride.CATEGORY_CHOICES)[category_code]
rides = Ride.objects.filter(
park=self.park,
category=category_code
).select_related('manufacturer').order_by('name')
return {category_name: rides} if rides.exists() else {}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['park'] = self.park
category_code = self.get_category_code()
category_name = dict(Ride.CATEGORY_CHOICES)[category_code]
context['title'] = f'{category_name}s at {self.park.name}'
context['category_code'] = category_code
return context
class RideCreateView(LoginRequiredMixin, CreateView):
model = Ride
form_class = RideForm