from auditlog.mixins import AuditlogHistoryAdminMixin from django.contrib import admin, messages from django.db import transaction from django.db.models.deletion import ProtectedError from import_export.admin import ImportExportModelAdmin from unfold.admin import ModelAdmin as UnfoldModelAdmin from core.admins.utils import SoftDeleteListFilter class BaseAdmin(AuditlogHistoryAdminMixin, ImportExportModelAdmin, UnfoldModelAdmin): show_auditlog_history_link = True actions = ["hard_delete_selected", "restore_selected"] list_filter = (SoftDeleteListFilter,) def get_queryset(self, request): return self.model.all_objects.all() @admin.action(description="Hard delete selected (permanent)") def hard_delete_selected(self, request, queryset): count = queryset.count() try: with transaction.atomic(): queryset.hard_delete() self.message_user( request, f"{count} record(s) permanently deleted.", level=messages.SUCCESS, ) except ProtectedError: self.message_user( request, "Cannot hard delete because related protected objects exist.", level=messages.ERROR, ) except Exception as e: self.message_user(request, str(e), level=messages.ERROR) @admin.action(description="Restore selected (undo soft delete)") def restore_selected(self, request, queryset): restored = 0 for obj in queryset: if getattr(obj, "is_deleted", False): obj.restore() restored += 1 self.message_user( request, f"{restored} record(s) restored.", level=messages.SUCCESS, ) def get_actions(self, request): actions = super().get_actions(request) if not request.user.is_superuser: actions.pop("hard_delete_selected", None) is_deleted_filter = request.GET.get("is_deleted") should_show_restore_actions = is_deleted_filter == "1" if not should_show_restore_actions: actions.pop("restore_selected", None) actions.pop("hard_delete_selected", None) return actions