from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.html import format_html
from django.urls import reverse
from django.contrib.auth.models import Group
from .models import User, UserProfile, EmailVerification, TopList, TopListItem
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'Profile'
fieldsets = (
('Personal Info', {
'fields': ('display_name', 'avatar', 'pronouns', 'bio')
}),
('Social Media', {
'fields': ('twitter', 'instagram', 'youtube', 'discord')
}),
('Ride Credits', {
'fields': (
'coaster_credits',
'dark_ride_credits',
'flat_ride_credits',
'water_ride_credits'
)
}),
)
class TopListItemInline(admin.TabularInline):
model = TopListItem
extra = 1
fields = ('content_type', 'object_id', 'rank', 'notes')
ordering = ('rank',)
@admin.register(User)
class CustomUserAdmin(UserAdmin):
list_display = ('username', 'email', 'get_avatar', 'get_status', 'role', 'date_joined', 'last_login', 'get_credits')
list_filter = ('is_active', 'is_staff', 'role', 'is_banned', 'groups', 'date_joined')
search_fields = ('username', 'email')
ordering = ('-date_joined',)
actions = ['activate_users', 'deactivate_users', 'ban_users', 'unban_users']
inlines = [UserProfileInline]
fieldsets = (
(None, {'fields': ('username', 'password')}),
('Personal info', {'fields': ('email', 'pending_email')}),
('Roles and Permissions', {
'fields': ('role', 'groups', 'user_permissions'),
'description': 'Role determines group membership. Groups determine permissions.',
}),
('Status', {
'fields': ('is_active', 'is_staff', 'is_superuser'),
'description': 'These are automatically managed based on role.',
}),
('Ban Status', {
'fields': ('is_banned', 'ban_reason', 'ban_date'),
}),
('Preferences', {
'fields': ('theme_preference',),
}),
('Important dates', {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'email', 'password1', 'password2', 'role'),
}),
)
def get_avatar(self, obj):
if obj.profile.avatar:
return format_html('
', obj.profile.avatar.url)
return format_html('
{}
', obj.username[0].upper())
get_avatar.short_description = 'Avatar'
def get_status(self, obj):
if obj.is_banned:
return format_html('Banned')
if not obj.is_active:
return format_html('Inactive')
if obj.is_superuser:
return format_html('Superuser')
if obj.is_staff:
return format_html('Staff')
return format_html('Active')
get_status.short_description = 'Status'
def get_credits(self, obj):
try:
profile = obj.profile
return format_html(
'RC: {}
DR: {}
FR: {}
WR: {}',
profile.coaster_credits,
profile.dark_ride_credits,
profile.flat_ride_credits,
profile.water_ride_credits
)
except UserProfile.DoesNotExist:
return '-'
get_credits.short_description = 'Ride Credits'
def activate_users(self, request, queryset):
queryset.update(is_active=True)
activate_users.short_description = "Activate selected users"
def deactivate_users(self, request, queryset):
queryset.update(is_active=False)
deactivate_users.short_description = "Deactivate selected users"
def ban_users(self, request, queryset):
from django.utils import timezone
queryset.update(is_banned=True, ban_date=timezone.now())
ban_users.short_description = "Ban selected users"
def unban_users(self, request, queryset):
queryset.update(is_banned=False, ban_date=None, ban_reason='')
unban_users.short_description = "Unban selected users"
def save_model(self, request, obj, form, change):
creating = not obj.pk
super().save_model(request, obj, form, change)
if creating and obj.role != User.Roles.USER:
# Ensure new user with role gets added to appropriate group
group = Group.objects.filter(name=obj.role).first()
if group:
obj.groups.add(group)
@admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('user', 'display_name', 'coaster_credits', 'dark_ride_credits', 'flat_ride_credits', 'water_ride_credits')
list_filter = ('coaster_credits', 'dark_ride_credits', 'flat_ride_credits', 'water_ride_credits')
search_fields = ('user__username', 'user__email', 'display_name', 'bio')
fieldsets = (
('User Information', {
'fields': ('user', 'display_name', 'avatar', 'pronouns', 'bio')
}),
('Social Media', {
'fields': ('twitter', 'instagram', 'youtube', 'discord')
}),
('Ride Credits', {
'fields': (
'coaster_credits',
'dark_ride_credits',
'flat_ride_credits',
'water_ride_credits'
)
}),
)
@admin.register(EmailVerification)
class EmailVerificationAdmin(admin.ModelAdmin):
list_display = ('user', 'created_at', 'last_sent', 'is_expired')
list_filter = ('created_at', 'last_sent')
search_fields = ('user__username', 'user__email', 'token')
readonly_fields = ('created_at', 'last_sent')
fieldsets = (
('Verification Details', {
'fields': ('user', 'token')
}),
('Timing', {
'fields': ('created_at', 'last_sent')
}),
)
def is_expired(self, obj):
from django.utils import timezone
from datetime import timedelta
if timezone.now() - obj.last_sent > timedelta(days=1):
return format_html('Expired')
return format_html('Valid')
is_expired.short_description = 'Status'
@admin.register(TopList)
class TopListAdmin(admin.ModelAdmin):
list_display = ('title', 'user', 'category', 'created_at', 'updated_at')
list_filter = ('category', 'created_at', 'updated_at')
search_fields = ('title', 'user__username', 'description')
inlines = [TopListItemInline]
fieldsets = (
('Basic Information', {
'fields': ('user', 'title', 'category', 'description')
}),
('Timestamps', {
'fields': ('created_at', 'updated_at'),
'classes': ('collapse',)
}),
)
readonly_fields = ('created_at', 'updated_at')
@admin.register(TopListItem)
class TopListItemAdmin(admin.ModelAdmin):
list_display = ('top_list', 'content_type', 'object_id', 'rank')
list_filter = ('top_list__category', 'rank')
search_fields = ('top_list__title', 'notes')
ordering = ('top_list', 'rank')
fieldsets = (
('List Information', {
'fields': ('top_list', 'rank')
}),
('Item Details', {
'fields': ('content_type', 'object_id', 'notes')
}),
)