Use decorator for admin display functions

This commit is contained in:
int-y1 2023-08-25 23:06:21 -04:00 committed by Guanzhong Chen
parent 138ce7fc99
commit 79be4af4b5
7 changed files with 37 additions and 58 deletions

View File

@ -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('<a href="{0}">{1}</a>', 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

View File

@ -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('<a class="button rejudge-link" href="{0}">{1}</a>',
reverse('admin:judge_contest_rejudge', args=(obj.contest.id, obj.id)), _('Rejudge'))
rejudge_column.short_description = ''
class ContestForm(ModelForm):
@ -222,6 +222,7 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
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 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
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 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
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 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
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 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
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 @@ class ContestParticipationAdmin(admin.ModelAdmin):
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 @@ class ContestParticipationAdmin(admin.ModelAdmin):
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'

View File

@ -25,9 +25,9 @@ class NavigationBarAdmin(DraggableMPTTAdmin):
super(NavigationBarAdmin, self).__init__(*args, **kwargs)
self.__save_model_calls = 0
@admin.display(description=_('link path'))
def linked_path(self, obj):
return format_html('<a href="{0}" target="_blank">{0}</a>', 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 @@ class LogEntryAdmin(admin.ModelAdmin):
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 @@ class LogEntryAdmin(admin.ModelAdmin):
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')

View File

@ -77,12 +77,11 @@ class OrganizationAdmin(VersionAdmin):
actions_on_bottom = True
form = OrganizationForm
@admin.display(description='')
def show_public(self, obj):
return format_html('<a href="{0}" style="white-space:nowrap;">{1}</a>',
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'

View File

@ -174,28 +174,26 @@ class ProblemAdmin(NoBatchDeleteMixin, VersionAdmin):
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('<a href="{1}">{0}</a>', 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 @@ class ProblemAdmin(NoBatchDeleteMixin, VersionAdmin):
'%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 @@ class ProblemAdmin(NoBatchDeleteMixin, VersionAdmin):
'%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 @@ class ProblemPointsVoteAdmin(admin.ModelAdmin):
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('<a href="{0}">{1}</a>', link, obj.problem.name)
linked_problem.short_description = _('problem')
linked_problem.admin_order_field = 'problem__name'

View File

@ -87,31 +87,28 @@ class ProfileAdmin(NoBatchDeleteMixin, VersionAdmin):
fields += ('is_totp_enabled',)
return fields
@admin.display(description='')
def show_public(self, obj):
return format_html('<a href="{0}" style="white-space:nowrap;">{1}</a>',
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 @@ class ProfileAdmin(NoBatchDeleteMixin, VersionAdmin):
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)

View File

@ -156,6 +156,7 @@ class SubmissionAdmin(VersionAdmin):
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 @@ class SubmissionAdmin(VersionAdmin):
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 @@ class SubmissionAdmin(VersionAdmin):
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 @@ class SubmissionAdmin(VersionAdmin):
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('<input type="button" disabled value="{0}"/>', _('Locked'))
else:
return format_html('<input type="button" value="{0}" onclick="location.href=\'{1}\'"/>', _('Rejudge'),
reverse('admin:judge_submission_rejudge', args=(obj.id,)))
judge_column.short_description = ''
def get_urls(self):
return [