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('{0}', 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) if "authors" in self.fields: 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( '{0}', 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('{0}', _("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")