NDOJ/judge/admin/interface.py
2023-05-20 08:52:37 +09:00

235 lines
7.3 KiB
Python
Executable file

from django.contrib import admin
from django.contrib.auth.models import User
from django.forms import ModelForm
from django.urls import NoReverseMatch, reverse, reverse_lazy
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from mptt.admin import DraggableMPTTAdmin
from reversion.admin import VersionAdmin
from reversion_compare.admin import CompareVersionAdmin
from judge.dblock import LockModel
from judge.models import NavigationBar
from judge.widgets import (
AdminHeavySelect2MultipleWidget,
AdminHeavySelect2Widget,
HeavyPreviewAdminPageDownWidget,
)
class NavigationBarAdmin(DraggableMPTTAdmin):
list_display = DraggableMPTTAdmin.list_display + ("key", "linked_path")
fields = ("key", "label", "path", "order", "regex", "parent")
list_editable = () # Bug in SortableModelAdmin: 500 without list_editable being set
mptt_level_indent = 20
sortable = "order"
def __init__(self, *args, **kwargs):
super(NavigationBarAdmin, self).__init__(*args, **kwargs)
self.__save_model_calls = 0
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
return super(NavigationBarAdmin, self).save_model(request, obj, form, change)
def changelist_view(self, request, extra_context=None):
self.__save_model_calls = 0
with NavigationBar.objects.disable_mptt_updates():
result = super(NavigationBarAdmin, self).changelist_view(
request, extra_context
)
if self.__save_model_calls:
with LockModel(write=(NavigationBar,)):
NavigationBar.objects.rebuild()
return result
class BlogPostForm(ModelForm):
def __init__(self, *args, **kwargs):
super(BlogPostForm, self).__init__(*args, **kwargs)
self.fields["authors"].widget.can_add_related = False
class Meta:
widgets = {
"authors": AdminHeavySelect2MultipleWidget(
data_view="profile_select2", attrs={"style": "width: 100%"}
),
"organizations": AdminHeavySelect2MultipleWidget(
data_view="organization_select2", attrs={"style": "width: 100%"}
),
}
if HeavyPreviewAdminPageDownWidget is not None:
widgets["content"] = HeavyPreviewAdminPageDownWidget(
preview=reverse_lazy("blog_preview")
)
widgets["summary"] = HeavyPreviewAdminPageDownWidget(
preview=reverse_lazy("blog_preview")
)
class BlogPostAdmin(CompareVersionAdmin):
fieldsets = (
(
None,
{
"fields": (
"title",
"slug",
"authors",
"visible",
"sticky",
"publish_on",
"is_organization_private",
"organizations",
)
},
),
(_("Content"), {"fields": ("content", "og_image")}),
(_("Summary"), {"classes": ("collapse",), "fields": ("summary",)}),
)
prepopulated_fields = {"slug": ("title",)}
list_display = ("id", "title", "visible", "sticky", "publish_on")
list_display_links = ("id", "title")
ordering = ("-publish_on",)
form = BlogPostForm
date_hierarchy = "publish_on"
def has_change_permission(self, request, obj=None):
return (
request.user.has_perm("judge.edit_all_post")
or request.user.has_perm("judge.change_blogpost")
and (obj is None or obj.authors.filter(id=request.profile.id).exists())
)
class SolutionForm(ModelForm):
def __init__(self, *args, **kwargs):
super(SolutionForm, self).__init__(*args, **kwargs)
self.fields["authors"].widget.can_add_related = False
class Meta:
widgets = {
"authors": AdminHeavySelect2MultipleWidget(
data_view="profile_select2", attrs={"style": "width: 100%"}
),
"problem": AdminHeavySelect2Widget(
data_view="problem_select2", attrs={"style": "width: 250px"}
),
}
if HeavyPreviewAdminPageDownWidget is not None:
widgets["content"] = HeavyPreviewAdminPageDownWidget(
preview=reverse_lazy("solution_preview")
)
class LicenseForm(ModelForm):
class Meta:
if HeavyPreviewAdminPageDownWidget is not None:
widgets = {
"text": HeavyPreviewAdminPageDownWidget(
preview=reverse_lazy("license_preview")
)
}
class LicenseAdmin(admin.ModelAdmin):
fields = ("key", "link", "name", "display", "icon", "text")
list_display = ("name", "key")
form = LicenseForm
class UserListFilter(admin.SimpleListFilter):
title = _("user")
parameter_name = "user"
def lookups(self, request, model_admin):
return User.objects.filter(is_staff=True).values_list("id", "username")
def queryset(self, request, queryset):
if self.value():
return queryset.filter(user_id=self.value(), user__is_staff=True)
return queryset
class LogEntryAdmin(admin.ModelAdmin):
readonly_fields = (
"user",
"content_type",
"object_id",
"object_repr",
"action_flag",
"change_message",
)
list_display = (
"__str__",
"action_time",
"user",
"content_type",
"object_link",
"diff_link",
)
search_fields = (
"object_repr",
"change_message",
"user__username",
"content_type__model",
)
list_filter = (UserListFilter, "content_type")
list_display_links = None
actions = None
def has_add_permission(self, request):
return False
def has_change_permission(self, request, obj=None):
return obj is None and request.user.is_superuser
def has_delete_permission(self, request, obj=None):
return False
def object_link(self, obj):
if obj.is_deletion():
link = obj.object_repr
else:
ct = obj.content_type
try:
link = format_html(
'<a href="{1}">{0}</a>',
obj.object_repr,
reverse(
"admin:%s_%s_change" % (ct.app_label, ct.model),
args=(obj.object_id,),
),
)
except NoReverseMatch:
link = obj.object_repr
return link
object_link.admin_order_field = "object_repr"
object_link.short_description = _("object")
def diff_link(self, obj):
if obj.is_deletion():
return None
ct = obj.content_type
try:
url = reverse(
"admin:%s_%s_history" % (ct.app_label, ct.model), args=(obj.object_id,)
)
link = format_html('<a href="{1}">{0}</a>', _("Diff"), url)
except NoReverseMatch:
link = None
return link
diff_link.short_description = _("diff")
def queryset(self, request):
return super().queryset(request).prefetch_related("content_type")