Update logentryadmin.py

pull/10/head
plhw57tbe 4 months ago
parent 0d0fb564d6
commit 9e31e3db5e

@ -1,27 +1,37 @@
# 导入 Django Admin 核心模块:用于自定义后台管理界面
from django.contrib import admin
# 导入 Admin 日志相关常量和模型:处理日志操作类型(如删除)
from django.contrib.admin.models import DELETION
from django.contrib.contenttypes.models import ContentType
# 导入 Django URL 和字符串处理工具:生成反向链接、处理编码和转义
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 _
# 自定义 LogEntry Admin 类:用于在 Django 后台管理 Admin 操作日志(记录用户对模型的增删改操作)
class LogEntryAdmin(admin.ModelAdmin):
# 列表页筛选器:按“内容类型”(即操作的模型,如 Article、Comment筛选日志
list_filter = [
'content_type'
]
# 列表页搜索框:支持按“对象名称”(如文章标题)和“操作描述”(如“修改了标题”)搜索
search_fields = [
'object_repr',
'change_message'
]
# 列表页可点击的链接:点击“操作时间”或“操作描述”可进入日志详情页
list_display_links = [
'action_time',
'get_change_message',
]
# 列表页展示的字段:操作时间、操作用户(带链接)、操作模型、操作对象(带链接)、操作描述
list_display = [
'action_time',
'user_link',
@ -30,62 +40,81 @@ class LogEntryAdmin(admin.ModelAdmin):
'get_change_message',
]
# 权限控制:禁止添加日志(日志由系统自动生成,不允许手动添加)
def has_add_permission(self, request):
return False
# 权限控制:仅允许超级用户或拥有“修改日志”权限的用户查看/修改日志,且禁止 POST 请求(避免提交修改)
def has_change_permission(self, request, obj=None):
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):
# 转义对象名称(避免 XSS 攻击)
object_link = escape(obj.object_repr)
# 获取操作对象的内容类型(即所属模型)
content_type = obj.content_type
# 若操作不是“删除”DELETION且内容类型存在排除异常情况
if obj.action_flag != DELETION and content_type is not None:
# try returning an actual link instead of object repr string
try:
# 生成对象编辑页的 URL格式admin/应用名/模型名/change/对象ID/
url = reverse(
'admin:{}_{}_change'.format(content_type.app_label,
content_type.model),
args=[obj.object_id]
)
# 将对象名称转为链接(点击跳转到编辑页)
object_link = '<a href="{}">{}</a>'.format(url, object_link)
except NoReverseMatch:
# 若无法生成链接(如模型未注册到 Admin则保留纯文本名称
pass
# 标记为安全 HTML告诉 Django 无需转义,避免链接被当作文本显示)
return mark_safe(object_link)
object_link.admin_order_field = 'object_repr'
object_link.short_description = _('object')
# 配置自定义字段的排序和显示名称
object_link.admin_order_field = 'object_repr' # 支持按“对象名称”排序
object_link.short_description = _('object') # 列表页字段显示名称(支持翻译)
# 自定义列表字段:操作用户(生成带链接的用户名,点击可跳转到用户的编辑页)
def user_link(self, obj):
# 获取用户模型的内容类型
content_type = ContentType.objects.get_for_model(type(obj.user))
# 转义用户名(避免 XSS 攻击)
user_link = escape(force_str(obj.user))
try:
# try returning an actual link instead of object repr string
# 生成用户编辑页的 URL
url = reverse(
'admin:{}_{}_change'.format(content_type.app_label,
content_type.model),
args=[obj.user.pk]
)
# 将用户名转为链接(点击跳转到用户编辑页)
user_link = '<a href="{}">{}</a>'.format(url, user_link)
except NoReverseMatch:
# 若无法生成链接(如用户模型未注册到 Admin则保留纯文本用户名
pass
return mark_safe(user_link)
user_link.admin_order_field = 'user'
user_link.short_description = _('user')
# 配置自定义字段的排序和显示名称
user_link.admin_order_field = 'user' # 支持按“用户”排序
user_link.short_description = _('user') # 列表页字段显示名称(支持翻译)
# 优化查询性能:预加载“内容类型”关联数据(避免列表页加载时产生大量数据库查询)
def get_queryset(self, request):
queryset = super(LogEntryAdmin, self).get_queryset(request)
return queryset.prefetch_related('content_type')
# 自定义批量操作:移除“批量删除”按钮(防止误删日志)
def get_actions(self, request):
actions = super(LogEntryAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
del actions['delete_selected'] # 删除“批量删除”操作
return actions
Loading…
Cancel
Save