diff --git a/judge/admin/comments.py b/judge/admin/comments.py index 32d316ef5f..d69c1c6df5 100644 --- a/judge/admin/comments.py +++ b/judge/admin/comments.py @@ -1,3 +1,4 @@ +from django.contrib import admin from django.db.models import F from django.forms import ModelForm from django.urls import reverse_lazy @@ -36,28 +37,27 @@ class CommentAdmin(VersionAdmin): def get_queryset(self, request): return Comment.objects.order_by('-time') + @admin.display(description=_('Hide comments')) def hide_comment(self, request, queryset): count = queryset.update(hidden=True) self.message_user(request, ngettext('%d comment successfully hidden.', '%d comments successfully hidden.', count) % count) - hide_comment.short_description = _('Hide comments') + @admin.display(description=_('Unhide comments')) def unhide_comment(self, request, queryset): count = queryset.update(hidden=False) self.message_user(request, ngettext('%d comment successfully unhidden.', '%d comments successfully unhidden.', count) % count) - unhide_comment.short_description = _('Unhide comments') + @admin.display(description=_('Associated page'), ordering='page') def linked_page(self, obj): link = obj.link if link is not None: return format_html('{1}', link, obj.page) else: return format_html('{0}', obj.page) - linked_page.short_description = _('Associated page') - linked_page.admin_order_field = 'page' def save_model(self, request, obj, form, change): obj.revisions = F('revisions') + 1 diff --git a/judge/admin/contest.py b/judge/admin/contest.py index 3f8d6f8f1a..59c25d103a 100644 --- a/judge/admin/contest.py +++ b/judge/admin/contest.py @@ -69,12 +69,12 @@ class ContestProblemInline(SortableInlineAdminMixin, admin.TabularInline): readonly_fields = ('rejudge_column',) form = ContestProblemInlineForm + @admin.display(description='') def rejudge_column(self, obj): if obj.id is None: return '' return format_html('{1}', reverse('admin:judge_contest_rejudge', args=(obj.contest.id, obj.id)), _('Rejudge')) - rejudge_column.short_description = '' class ContestForm(ModelForm): @@ -222,6 +222,7 @@ def _rescore(self, contest_key): from judge.tasks import rescore_contest transaction.on_commit(rescore_contest.s(contest_key).delay) + @admin.display(description=_('Mark contests as visible')) def make_visible(self, request, queryset): if not request.user.has_perm('judge.change_contest_visibility'): queryset = queryset.filter(Q(is_private=True) | Q(is_organization_private=True)) @@ -229,8 +230,8 @@ def make_visible(self, request, queryset): self.message_user(request, ngettext('%d contest successfully marked as visible.', '%d contests successfully marked as visible.', count) % count) - make_visible.short_description = _('Mark contests as visible') + @admin.display(description=_('Mark contests as hidden')) def make_hidden(self, request, queryset): if not request.user.has_perm('judge.change_contest_visibility'): queryset = queryset.filter(Q(is_private=True) | Q(is_organization_private=True)) @@ -238,8 +239,8 @@ def make_hidden(self, request, queryset): self.message_user(request, ngettext('%d contest successfully marked as hidden.', '%d contests successfully marked as hidden.', count) % count) - make_hidden.short_description = _('Mark contests as hidden') + @admin.display(description=_('Lock contest submissions')) def set_locked(self, request, queryset): for row in queryset: self.set_locked_after(row, timezone.now()) @@ -247,8 +248,8 @@ def set_locked(self, request, queryset): self.message_user(request, ngettext('%d contest successfully locked.', '%d contests successfully locked.', count) % count) - set_locked.short_description = _('Lock contest submissions') + @admin.display(description=_('Unlock contest submissions')) def set_unlocked(self, request, queryset): for row in queryset: self.set_locked_after(row, None) @@ -256,7 +257,6 @@ def set_unlocked(self, request, queryset): self.message_user(request, ngettext('%d contest successfully unlocked.', '%d contests successfully unlocked.', count) % count) - set_unlocked.short_description = _('Unlock contest submissions') def set_locked_after(self, contest, locked_after): with transaction.atomic(): @@ -350,6 +350,7 @@ def save_model(self, request, obj, form, change): if form.changed_data and 'is_disqualified' in form.changed_data: obj.set_disqualified(obj.is_disqualified) + @admin.display(description=_('Recalculate results')) def recalculate_results(self, request, queryset): count = 0 for participation in queryset: @@ -358,14 +359,11 @@ def recalculate_results(self, request, queryset): self.message_user(request, ngettext('%d participation recalculated.', '%d participations recalculated.', count) % count) - recalculate_results.short_description = _('Recalculate results') + @admin.display(description=_('username'), ordering='user__user__username') def username(self, obj): return obj.user.username - username.short_description = _('username') - username.admin_order_field = 'user__user__username' + @admin.display(description=_('virtual'), ordering='virtual') def show_virtual(self, obj): return obj.virtual or '-' - show_virtual.short_description = _('virtual') - show_virtual.admin_order_field = 'virtual' diff --git a/judge/admin/interface.py b/judge/admin/interface.py index eac8f7176a..f49c3a654c 100644 --- a/judge/admin/interface.py +++ b/judge/admin/interface.py @@ -25,9 +25,9 @@ def __init__(self, *args, **kwargs): super(NavigationBarAdmin, self).__init__(*args, **kwargs) self.__save_model_calls = 0 + @admin.display(description=_('link path')) def linked_path(self, obj): return format_html('{0}', obj.path) - linked_path.short_description = _('link path') def save_model(self, request, obj, form, change): self.__save_model_calls += 1 @@ -151,6 +151,7 @@ def has_change_permission(self, request, obj=None): def has_delete_permission(self, request, obj=None): return False + @admin.display(description=_('object'), ordering='object_repr') def object_link(self, obj): if obj.is_deletion(): link = obj.object_repr @@ -162,8 +163,6 @@ def object_link(self, obj): except NoReverseMatch: link = obj.object_repr return link - object_link.admin_order_field = 'object_repr' - object_link.short_description = _('object') def queryset(self, request): return super().queryset(request).prefetch_related('content_type') diff --git a/judge/admin/organization.py b/judge/admin/organization.py index d0f978cc63..ff5fab5f0b 100644 --- a/judge/admin/organization.py +++ b/judge/admin/organization.py @@ -77,12 +77,11 @@ class OrganizationAdmin(VersionAdmin): actions_on_bottom = True form = OrganizationForm + @admin.display(description='') def show_public(self, obj): return format_html('{1}', obj.get_absolute_url(), gettext('View on site')) - show_public.short_description = '' - def get_readonly_fields(self, request, obj=None): fields = self.readonly_fields if not request.user.has_perm('judge.organization_admin'): @@ -108,7 +107,6 @@ class OrganizationRequestAdmin(admin.ModelAdmin): list_display = ('username', 'organization', 'state', 'time') readonly_fields = ('user', 'organization', 'request_class') + @admin.display(description=_('username'), ordering='user__user__username') def username(self, obj): return obj.user.user.username - username.short_description = _('username') - username.admin_order_field = 'user__user__username' diff --git a/judge/admin/problem.py b/judge/admin/problem.py index 8664960e51..9a2150a194 100644 --- a/judge/admin/problem.py +++ b/judge/admin/problem.py @@ -174,28 +174,26 @@ def get_readonly_fields(self, request, obj=None): fields += ('description',) return fields + @admin.display(description=_('Authors')) def show_authors(self, obj): return ', '.join(map(attrgetter('user.username'), obj.authors.all())) - show_authors.short_description = _('Authors') - + @admin.display(description='') def show_public(self, obj): return format_html('{0}', gettext('View on site'), obj.get_absolute_url()) - show_public.short_description = '' - def _rescore(self, request, problem_id): from judge.tasks import rescore_problem transaction.on_commit(rescore_problem.s(problem_id).delay) + @admin.display(description=_('Set publish date to now')) def update_publish_date(self, request, queryset): count = queryset.update(date=timezone.now()) self.message_user(request, ngettext("%d problem's publish date successfully updated.", "%d problems' publish date successfully updated.", count) % count) - update_publish_date.short_description = _('Set publish date to now') - + @admin.display(description=_('Mark problems as public')) def make_public(self, request, queryset): count = queryset.update(is_public=True) for problem_id in queryset.values_list('id', flat=True): @@ -204,8 +202,7 @@ def make_public(self, request, queryset): '%d problems successfully marked as public.', count) % count) - make_public.short_description = _('Mark problems as public') - + @admin.display(description=_('Mark problems as private')) def make_private(self, request, queryset): count = queryset.update(is_public=False) for problem_id in queryset.values_list('id', flat=True): @@ -214,8 +211,6 @@ def make_private(self, request, queryset): '%d problems successfully marked as private.', count) % count) - make_private.short_description = _('Mark problems as private') - def get_queryset(self, request): return Problem.get_editable_problems(request.user).prefetch_related('authors__user').distinct() @@ -270,8 +265,7 @@ def has_change_permission(self, request, obj=None): def lookup_allowed(self, key, value): return super().lookup_allowed(key, value) or key in ('problem__code',) + @admin.display(description=_('problem'), ordering='problem__name') def linked_problem(self, obj): link = reverse('problem_detail', args=[obj.problem.code]) return format_html('{1}', link, obj.problem.name) - linked_problem.short_description = _('problem') - linked_problem.admin_order_field = 'problem__name' diff --git a/judge/admin/profile.py b/judge/admin/profile.py index d839b0b470..67466e5c1c 100644 --- a/judge/admin/profile.py +++ b/judge/admin/profile.py @@ -87,31 +87,28 @@ def get_readonly_fields(self, request, obj=None): fields += ('is_totp_enabled',) return fields + @admin.display(description='') def show_public(self, obj): return format_html('{1}', obj.get_absolute_url(), gettext('View on site')) - show_public.short_description = '' + @admin.display(description=_('User'), ordering='user__username') def admin_user_admin(self, obj): return obj.username - admin_user_admin.admin_order_field = 'user__username' - admin_user_admin.short_description = _('User') + @admin.display(description=_('Email'), ordering='user__email') def email(self, obj): return obj.user.email - email.admin_order_field = 'user__email' - email.short_description = _('Email') + @admin.display(description=_('Timezone'), ordering='timezone') def timezone_full(self, obj): return obj.timezone - timezone_full.admin_order_field = 'timezone' - timezone_full.short_description = _('Timezone') + @admin.display(description=_('date joined'), ordering='user__date_joined') def date_joined(self, obj): return obj.user.date_joined - date_joined.admin_order_field = 'user__date_joined' - date_joined.short_description = _('date joined') + @admin.display(description=_('Recalculate scores')) def recalculate_points(self, request, queryset): count = 0 for profile in queryset: @@ -120,7 +117,6 @@ def recalculate_points(self, request, queryset): self.message_user(request, ngettext('%d user had scores recalculated.', '%d users had scores recalculated.', count) % count) - recalculate_points.short_description = _('Recalculate scores') def get_form(self, request, obj=None, **kwargs): form = super(ProfileAdmin, self).get_form(request, obj, **kwargs) diff --git a/judge/admin/submission.py b/judge/admin/submission.py index 64b675e493..fb05d31123 100644 --- a/judge/admin/submission.py +++ b/judge/admin/submission.py @@ -156,6 +156,7 @@ def has_change_permission(self, request, obj=None): def lookup_allowed(self, key, value): return super(SubmissionAdmin, self).lookup_allowed(key, value) or key in ('problem__code',) + @admin.display(description=_('Rejudge the selected submissions')) def judge(self, request, queryset): if not request.user.has_perm('judge.rejudge_submission') or not request.user.has_perm('judge.edit_own_problem'): self.message_user(request, gettext('You do not have the permission to rejudge submissions.'), @@ -176,8 +177,8 @@ def judge(self, request, queryset): self.message_user(request, ngettext('%d submission was successfully scheduled for rejudging.', '%d submissions were successfully scheduled for rejudging.', judged) % judged) - judge.short_description = _('Rejudge the selected submissions') + @admin.display(description=_('Rescore the selected submissions')) def recalculate_score(self, request, queryset): if not request.user.has_perm('judge.rejudge_submission'): self.message_user(request, gettext('You do not have the permission to rejudge submissions.'), @@ -205,28 +206,24 @@ def recalculate_score(self, request, queryset): self.message_user(request, ngettext('%d submission was successfully rescored.', '%d submissions were successfully rescored.', len(submissions)) % len(submissions)) - recalculate_score.short_description = _('Rescore the selected submissions') + @admin.display(description=_('Problem code'), ordering='problem__code') def problem_code(self, obj): return obj.problem.code - problem_code.short_description = _('Problem code') - problem_code.admin_order_field = 'problem__code' + @admin.display(description=_('Problem name'), ordering='problem__name') def problem_name(self, obj): return obj.problem.name - problem_name.short_description = _('Problem name') - problem_name.admin_order_field = 'problem__name' + @admin.display(description=_('User'), ordering='user__user__username') def user_column(self, obj): return obj.user.user.username - user_column.admin_order_field = 'user__user__username' - user_column.short_description = _('User') + @admin.display(description=_('Time'), ordering='time') def execution_time(self, obj): return round(obj.time, 2) if obj.time is not None else 'None' - execution_time.short_description = _('Time') - execution_time.admin_order_field = 'time' + @admin.display(description=_('Memory'), ordering='memory') def pretty_memory(self, obj): memory = obj.memory if memory is None: @@ -235,21 +232,18 @@ def pretty_memory(self, obj): return gettext('%d KB') % memory else: return gettext('%.2f MB') % (memory / 1024) - pretty_memory.admin_order_field = 'memory' - pretty_memory.short_description = _('Memory') + @admin.display(description=_('Language'), ordering='language__name') def language_column(self, obj): return obj.language.name - language_column.admin_order_field = 'language__name' - language_column.short_description = _('Language') + @admin.display(description='') def judge_column(self, obj): if obj.is_locked: return format_html('', _('Locked')) else: return format_html('', _('Rejudge'), reverse('admin:judge_submission_rejudge', args=(obj.id,))) - judge_column.short_description = '' def get_urls(self): return [