mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 14:31:08 -05:00
major changes, including tailwind v4
This commit is contained in:
201
rides/admin.py
201
rides/admin.py
@@ -1,168 +1,73 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.html import format_html
|
||||
from django.db.models import Avg
|
||||
from .models import Ride, RollerCoasterStats
|
||||
from django.contrib.gis.admin import GISModelAdmin
|
||||
from .models.company import Company
|
||||
from .models.rides import Ride
|
||||
from .models.location import RideLocation
|
||||
|
||||
class RollerCoasterStatsInline(admin.StackedInline):
|
||||
model = RollerCoasterStats
|
||||
can_delete = False
|
||||
class ManufacturerAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'headquarters', 'website', 'rides_count')
|
||||
search_fields = ('name',)
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).filter(roles__contains=['MANUFACTURER'])
|
||||
|
||||
class DesignerAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'headquarters', 'website')
|
||||
search_fields = ('name',)
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).filter(roles__contains=['DESIGNER'])
|
||||
|
||||
|
||||
class RideLocationInline(admin.StackedInline):
|
||||
"""Inline admin for RideLocation"""
|
||||
model = RideLocation
|
||||
extra = 0
|
||||
fieldsets = (
|
||||
('Basic Stats', {
|
||||
'fields': (
|
||||
('height_ft', 'length_ft'),
|
||||
('speed_mph', 'inversions'),
|
||||
'ride_time_seconds'
|
||||
)
|
||||
}),
|
||||
('Track Details', {
|
||||
'fields': (
|
||||
'track_type',
|
||||
'launch_type'
|
||||
)
|
||||
}),
|
||||
('Train Configuration', {
|
||||
'fields': (
|
||||
'train_style',
|
||||
('trains_count', 'cars_per_train', 'seats_per_car')
|
||||
)
|
||||
}),
|
||||
fields = (
|
||||
'park_area',
|
||||
'point',
|
||||
'entrance_notes',
|
||||
'accessibility_notes',
|
||||
)
|
||||
|
||||
@admin.register(Ride)
|
||||
class RideAdmin(admin.ModelAdmin):
|
||||
list_display = ('id', 'name', 'park', 'category', 'get_status', 'manufacturer', 'opening_date', 'get_avg_rating')
|
||||
list_filter = ('status', 'category', 'manufacturer', 'park')
|
||||
search_fields = ('name', 'park__name', 'manufacturer__name', 'description')
|
||||
prepopulated_fields = {'slug': ('name',)}
|
||||
inlines = [RollerCoasterStatsInline]
|
||||
readonly_fields = ('id', 'created_at', 'updated_at')
|
||||
actions = ['mark_as_operating', 'mark_as_closed', 'mark_as_under_maintenance', 'mark_as_removed']
|
||||
|
||||
class RideLocationAdmin(GISModelAdmin):
|
||||
"""Admin for standalone RideLocation management"""
|
||||
list_display = ('ride', 'park_area', 'has_coordinates', 'created_at')
|
||||
list_filter = ('park_area', 'created_at')
|
||||
search_fields = ('ride__name', 'park_area', 'entrance_notes')
|
||||
readonly_fields = ('latitude', 'longitude', 'coordinates', 'created_at', 'updated_at')
|
||||
fieldsets = (
|
||||
('Basic Information', {
|
||||
'fields': (
|
||||
'name',
|
||||
'slug',
|
||||
'description',
|
||||
'park',
|
||||
'park_area'
|
||||
)
|
||||
('Ride', {
|
||||
'fields': ('ride',)
|
||||
}),
|
||||
('Ride Details', {
|
||||
'fields': (
|
||||
'category',
|
||||
'manufacturer',
|
||||
'model_name',
|
||||
'status'
|
||||
)
|
||||
('Location Information', {
|
||||
'fields': ('park_area', 'point', 'latitude', 'longitude', 'coordinates'),
|
||||
'description': 'Optional coordinates - not all rides need precise location tracking'
|
||||
}),
|
||||
('Dates', {
|
||||
'fields': (
|
||||
'opening_date',
|
||||
'closing_date',
|
||||
'status_since'
|
||||
)
|
||||
}),
|
||||
('Requirements', {
|
||||
'fields': (
|
||||
'min_height_in',
|
||||
'max_height_in',
|
||||
'accessibility_options'
|
||||
)
|
||||
}),
|
||||
('Capacity', {
|
||||
'fields': (
|
||||
'capacity_per_hour',
|
||||
'ride_duration_seconds'
|
||||
)
|
||||
('Navigation Notes', {
|
||||
'fields': ('entrance_notes', 'accessibility_notes'),
|
||||
}),
|
||||
('Metadata', {
|
||||
'fields': ('id', 'created_at', 'updated_at'),
|
||||
'fields': ('created_at', 'updated_at'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
def get_status(self, obj):
|
||||
status_colors = {
|
||||
'OPERATING': 'green',
|
||||
'CLOSED_TEMP': 'orange',
|
||||
'CLOSED_PERM': 'red',
|
||||
'UNDER_CONSTRUCTION': 'blue',
|
||||
'DEMOLISHED': 'grey',
|
||||
'RELOCATED': 'purple'
|
||||
}
|
||||
return format_html(
|
||||
'<span style="color: {};">{}</span>',
|
||||
status_colors.get(obj.status, 'black'),
|
||||
obj.get_status_display()
|
||||
)
|
||||
get_status.short_description = 'Status'
|
||||
def latitude(self, obj):
|
||||
return obj.latitude
|
||||
latitude.short_description = 'Latitude'
|
||||
|
||||
def get_avg_rating(self, obj):
|
||||
avg = obj.reviews.filter(is_published=True).aggregate(avg_rating=Avg('rating'))['avg_rating']
|
||||
if avg:
|
||||
rating_str = '{:.1f}'.format(float(avg))
|
||||
return format_html(
|
||||
'<span style="color: gold;">★ {}</span>',
|
||||
rating_str
|
||||
)
|
||||
return '-'
|
||||
get_avg_rating.short_description = 'Rating'
|
||||
def longitude(self, obj):
|
||||
return obj.longitude
|
||||
longitude.short_description = 'Longitude'
|
||||
|
||||
def mark_as_operating(self, request, queryset):
|
||||
queryset.update(status='OPERATING')
|
||||
mark_as_operating.short_description = "Mark selected rides as operating"
|
||||
|
||||
def mark_as_closed(self, request, queryset):
|
||||
queryset.update(status='CLOSED_TEMP')
|
||||
mark_as_closed.short_description = "Mark selected rides as temporarily closed"
|
||||
class RideAdmin(admin.ModelAdmin):
|
||||
"""Enhanced Ride admin with location inline"""
|
||||
inlines = [RideLocationInline]
|
||||
|
||||
def mark_as_under_maintenance(self, request, queryset):
|
||||
queryset.update(status='CLOSED_TEMP')
|
||||
mark_as_under_maintenance.short_description = "Mark selected rides as under maintenance"
|
||||
|
||||
def mark_as_removed(self, request, queryset):
|
||||
queryset.update(status='DEMOLISHED')
|
||||
mark_as_removed.short_description = "Mark selected rides as demolished"
|
||||
|
||||
@admin.register(RollerCoasterStats)
|
||||
class RollerCoasterStatsAdmin(admin.ModelAdmin):
|
||||
list_display = ('ride', 'height_ft', 'length_ft', 'speed_mph', 'inversions', 'get_capacity')
|
||||
list_filter = ('launch_type', 'track_type', 'train_style')
|
||||
search_fields = ('ride__name', 'track_type')
|
||||
readonly_fields = ('id', 'ride')
|
||||
|
||||
fieldsets = (
|
||||
('Basic Stats', {
|
||||
'fields': (
|
||||
'id',
|
||||
'ride',
|
||||
('height_ft', 'length_ft'),
|
||||
('speed_mph', 'inversions'),
|
||||
'ride_time_seconds'
|
||||
)
|
||||
}),
|
||||
('Track Details', {
|
||||
'fields': (
|
||||
'track_type',
|
||||
'launch_type'
|
||||
)
|
||||
}),
|
||||
('Train Configuration', {
|
||||
'fields': (
|
||||
'train_style',
|
||||
('trains_count', 'cars_per_train', 'seats_per_car')
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
def get_capacity(self, obj):
|
||||
if obj.trains_count and obj.cars_per_train and obj.seats_per_car:
|
||||
capacity = obj.trains_count * obj.cars_per_train * obj.seats_per_car
|
||||
return format_html(
|
||||
'{} seats total',
|
||||
str(capacity)
|
||||
)
|
||||
return '-'
|
||||
get_capacity.short_description = 'Total Capacity'
|
||||
admin.site.register(Company)
|
||||
admin.site.register(Ride, RideAdmin)
|
||||
admin.site.register(RideLocation, RideLocationAdmin)
|
||||
|
||||
Reference in New Issue
Block a user