mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 05:31:10 -05:00
add category views for each type of ride, add ride designers
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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'
|
||||
}),
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -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",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -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,
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user