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 [