|
|
#gq:
|
|
|
from django.contrib import admin
|
|
|
from django.contrib.admin.models import DELETION
|
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
from django.urls import reverse, NoReverseMatch
|
|
|
from django.utils.encoding import force_str
|
|
|
from django.utils.html import escape
|
|
|
from django.utils.safestring import mark_safe
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
class LogEntryAdmin(admin.ModelAdmin):
|
|
|
"""Admin操作日志自定义管理类:优化展示与权限控制"""
|
|
|
list_filter = ['content_type'] # 按内容类型筛选
|
|
|
search_fields = ['object_repr', 'change_message'] # 搜索对象描述、操作信息
|
|
|
list_display_links = ['action_time', 'get_change_message'] # 可点击跳转字段
|
|
|
list_display = ['action_time', 'user_link', 'content_type', 'object_link', 'get_change_message'] # 列表展示字段
|
|
|
|
|
|
def has_add_permission(self, request):
|
|
|
"""禁用添加:日志自动生成,不允许手动添加"""
|
|
|
return False
|
|
|
|
|
|
def has_change_permission(self, request, obj=None):
|
|
|
"""仅超级用户/有权限用户可查看,禁止POST修改"""
|
|
|
return (request.user.is_superuser or request.user.has_perm('admin.change_logentry')) and request.method != 'POST'
|
|
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
|
"""禁用删除:日志需保留"""
|
|
|
return False
|
|
|
|
|
|
def object_link(self, obj):
|
|
|
"""操作对象字段:非删除操作显示Admin编辑链接"""
|
|
|
object_link = escape(obj.object_repr)
|
|
|
if obj.action_flag != DELETION and obj.content_type:
|
|
|
try:
|
|
|
url = reverse(f'admin:{obj.content_type.app_label}_{obj.content_type.model}_change', args=[obj.object_id])
|
|
|
object_link = f'<a href="{url}">{object_link}</a>'
|
|
|
except NoReverseMatch:
|
|
|
pass
|
|
|
return mark_safe(object_link)
|
|
|
|
|
|
object_link.admin_order_field = 'object_repr'
|
|
|
object_link.short_description = _('object')
|
|
|
|
|
|
def user_link(self, obj):
|
|
|
"""操作用户字段:显示用户Admin编辑链接"""
|
|
|
content_type = ContentType.objects.get_for_model(type(obj.user))
|
|
|
user_link = escape(force_str(obj.user))
|
|
|
try:
|
|
|
url = reverse(f'admin:{content_type.app_label}_{content_type.model}_change', args=[obj.user.pk])
|
|
|
user_link = f'<a href="{url}">{user_link}</a>'
|
|
|
except NoReverseMatch:
|
|
|
pass
|
|
|
return mark_safe(user_link)
|
|
|
|
|
|
user_link.admin_order_field = 'user'
|
|
|
user_link.short_description = _('user')
|
|
|
|
|
|
def get_queryset(self, request):
|
|
|
"""预加载content_type,优化查询性能"""
|
|
|
return super().get_queryset(request).prefetch_related('content_type')
|
|
|
|
|
|
def get_actions(self, request):
|
|
|
"""移除批量删除操作"""
|
|
|
actions = super().get_actions(request)
|
|
|
del actions['delete_selected']
|
|
|
return actions |