From 9e31e3db5ee3538e615425bb45e4c40c99c69254 Mon Sep 17 00:00:00 2001
From: plhw57tbe <2723863608@qq.com>
Date: Sun, 19 Oct 2025 23:21:41 +0800
Subject: [PATCH] Update logentryadmin.py
---
.../djangoblog/logentryadmin.py | 45 +++++++++++++++----
1 file changed, 37 insertions(+), 8 deletions(-)
diff --git a/src/DjangoBlog-master/djangoblog/logentryadmin.py b/src/DjangoBlog-master/djangoblog/logentryadmin.py
index 2f6a535..ac3f7cb 100644
--- a/src/DjangoBlog-master/djangoblog/logentryadmin.py
+++ b/src/DjangoBlog-master/djangoblog/logentryadmin.py
@@ -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 = '{}'.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 = '{}'.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
\ No newline at end of file