from django.contrib import admin from django.utils.html import format_html from django.db.models import Avg from .models import Ride, RollerCoasterStats class RollerCoasterStatsInline(admin.StackedInline): model = RollerCoasterStats can_delete = False 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') ) }), ) @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'] fieldsets = ( ('Basic Information', { 'fields': ( 'name', 'slug', 'description', 'park', 'park_area' ) }), ('Ride Details', { 'fields': ( 'category', 'manufacturer', 'model_name', 'status' ) }), ('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' ) }), ('Metadata', { 'fields': ('id', '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( '{}', status_colors.get(obj.status, 'black'), obj.get_status_display() ) get_status.short_description = 'Status' 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( '★ {}', rating_str ) return '-' get_avg_rating.short_description = 'Rating' 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" 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'