from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.utils import timezone from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION from django.utils.html import escape from django.urls import reverse from django.utils.safestring import mark_safe from .models import Club, TeamScore, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamRegistration, PlayerRegistration, Purchase, Court, DateInterval, FailedApiCall, Log, DeviceToken, DrawLog, UnregisteredTeam, UnregisteredPlayer, Image from .forms import CustomUserCreationForm, CustomUserChangeForm from .filters import TeamScoreTournamentListFilter, MatchTournamentListFilter, SimpleTournamentListFilter, MatchTypeListFilter, SimpleIndexListFilter, StartDateRangeFilter from sync.admin import SyncedObjectAdmin class CustomUserAdmin(UserAdmin): form = CustomUserChangeForm add_form = CustomUserCreationForm model = CustomUser search_fields = ['username', 'email', 'phone', 'first_name', 'last_name', 'licence_id'] list_display = ['email', 'first_name', 'last_name', 'username', 'date_joined', 'latest_event_club_name', 'is_active', 'event_count', 'origin', 'registration_payment_mode', 'licence_id'] list_filter = ['is_active', 'origin'] ordering = ['-date_joined'] raw_id_fields = ['agents'] fieldsets = [ (None, {'fields': ['id', 'username', 'email', 'password', 'first_name', 'last_name', 'is_active', 'registration_payment_mode', 'clubs', 'country', 'phone', 'licence_id', 'umpire_code', 'summons_message_body', 'summons_message_signature', 'summons_available_payment_methods', 'summons_display_format', 'summons_display_entry_fee', 'summons_use_full_custom_message', 'match_formats_default_duration', 'bracket_match_format_preference', 'group_stage_match_format_preference', 'loser_bracket_match_format_preference', 'device_id', 'loser_bracket_mode', 'groups', 'origin', 'agents', 'should_synchronize' ]}), ] add_fieldsets = [ ( None, { "classes": ["wide"], "fields": ['username', 'email', 'password1', 'password2', 'first_name', 'last_name', 'clubs', 'country', 'phone', 'licence_id', 'umpire_code', 'groups'], }, ), ] def save_model(self, request, obj, form, change): obj.last_update = timezone.now() super().save_model(request, obj, form, change) class EventAdmin(SyncedObjectAdmin): list_display = ['creation_date', 'name', 'club', 'creator', 'creator_full_name', 'tenup_id', 'display_images'] list_filter = ['creator', 'tenup_id'] raw_id_fields = ['creator'] ordering = ['-creation_date'] readonly_fields = ['display_images_preview'] fieldsets = [ (None, {'fields': ['name', 'club', 'creator', 'creation_date', 'tenup_id']}), ('Images', {'fields': ['display_images_preview'], 'classes': ['collapse']}), ] def display_images(self, obj): count = obj.images.count() return count if count > 0 else '-' display_images.short_description = 'Images' def display_images_preview(self, obj): html = '
{image.title or "Untitled"}
Type: {image.get_image_type_display()}
No images uploaded for this event.
' return mark_safe(html) display_images_preview.short_description = 'Images Preview' class TournamentAdmin(SyncedObjectAdmin): list_display = ['display_name', 'event', 'is_private', 'start_date', 'payment', 'creator', 'is_canceled'] list_filter = [StartDateRangeFilter, 'is_deleted', 'event__creator'] ordering = ['-start_date'] search_fields = ['id'] class TeamRegistrationAdmin(SyncedObjectAdmin): list_display = ['player_names', 'group_stage', 'name', 'tournament', 'registration_date'] list_filter = [SimpleTournamentListFilter] search_fields = ['id'] class TeamScoreAdmin(SyncedObjectAdmin): list_display = ['team_registration', 'score', 'walk_out', 'match'] list_filter = [TeamScoreTournamentListFilter] search_fields = ['id'] raw_id_fields = ['team_registration', 'match'] # Add this line list_per_page = 50 # Controls pagination on the list view def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('team_registration', 'match') class RoundAdmin(SyncedObjectAdmin): list_display = ['tournament', 'name', 'parent', 'index'] list_filter = [SimpleTournamentListFilter, SimpleIndexListFilter] search_fields = ['id'] ordering = ['parent', 'index'] raw_id_fields = ['parent'] # Add this line list_per_page = 50 # Controls pagination on the list view def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('parent') class PlayerRegistrationAdmin(SyncedObjectAdmin): list_display = ['first_name', 'last_name', 'licence_id', 'rank'] search_fields = ['id', 'first_name', 'last_name', 'licence_id__icontains'] list_filter = ['registered_online', TeamScoreTournamentListFilter] ordering = ['last_name', 'first_name'] raw_id_fields = ['team_registration'] # Add this line list_per_page = 50 # Controls pagination on the list view def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('team_registration') class MatchAdmin(SyncedObjectAdmin): list_display = ['__str__', 'round', 'group_stage', 'start_date', 'end_date', 'index'] list_filter = [MatchTypeListFilter, MatchTournamentListFilter, SimpleIndexListFilter] ordering = ['-group_stage', 'round', 'index'] raw_id_fields = ['round', 'group_stage'] # Add this line list_per_page = 50 # Controls pagination on the list view def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('round', 'group_stage') class GroupStageAdmin(SyncedObjectAdmin): list_display = ['tournament', 'start_date', 'index'] list_filter = [SimpleTournamentListFilter] ordering = ['-start_date', 'index'] class ClubAdmin(SyncedObjectAdmin): list_display = ['name', 'acronym', 'city', 'creator', 'events_count', 'broadcast_code'] search_fields = ['name', 'acronym', 'city'] ordering = ['creator'] raw_id_fields = ['creator', 'related_user'] class PurchaseAdmin(SyncedObjectAdmin): list_display = ['id', 'user', 'product_id', 'quantity', 'purchase_date', 'revocation_date', 'expiration_date'] list_filter = ['user'] ordering = ['-purchase_date'] class CourtAdmin(SyncedObjectAdmin): list_display = ['index', 'name', 'club'] ordering = ['club'] class DateIntervalAdmin(SyncedObjectAdmin): list_display = ['court_index', 'event'] class FailedApiCallAdmin(admin.ModelAdmin): list_display = ['date', 'user', 'type', 'error'] list_filter = ['user'] class LogAdmin(admin.ModelAdmin): list_display = ['date', 'user', 'message'] list_filter = ['user'] class DeviceTokenAdmin(admin.ModelAdmin): list_display = ['user', 'value'] list_filter = ['user'] class DrawLogAdmin(SyncedObjectAdmin): list_display = ['tournament', 'draw_date', 'draw_seed', 'draw_match_index', 'draw_team_position'] list_filter = [SimpleTournamentListFilter] ordering = ['draw_date'] class UnregisteredTeamAdmin(admin.ModelAdmin): list_display = ['player_names', 'tournament'] list_filter = [SimpleTournamentListFilter] class UnregisteredPlayerAdmin(admin.ModelAdmin): list_display = ['first_name', 'last_name', 'licence_id'] search_fields = ['first_name', 'last_name'] list_filter = [] ordering = ['last_name', 'first_name'] class ImageAdmin(admin.ModelAdmin): list_display = ['title', 'event', 'image_type', 'order', 'uploaded_at', 'file_size', 'image_preview_small'] list_filter = ['event', 'image_type', 'uploaded_at'] search_fields = ['title', 'description', 'event__name'] ordering = ['order'] readonly_fields = ['id', 'uploaded_at', 'image_preview', 'file_size'] raw_id_fields = ['event'] def image_preview(self, obj): if obj.image: return mark_safe(f'