添加 logentryadmin.py 注释

jyf_branch
姜雨菲 4 months ago
parent 10ca267b57
commit f7675c6ff7

@ -1,91 +1,136 @@
#姜雨菲: 导入Django管理后台核心模块
from django.contrib import admin
from django.contrib.admin.models import DELETION
from django.contrib.contenttypes.models import ContentType
#姜雨菲: 导入日志相关常量和模型
from django.contrib.admin.models import DELETION # 表示"删除"操作的常量
from django.contrib.contenttypes.models import ContentType # 内容类型模型,用于关联不同模型
#姜雨菲: 导入URL反向解析和异常处理
from django.urls import reverse, NoReverseMatch
# 导入字符串处理工具
from django.utils.encoding import force_str
# 导入HTML转义工具
from django.utils.html import escape
# 导入安全字符串标记工具用于渲染HTML
from django.utils.safestring import mark_safe
# 导入国际化翻译工具
from django.utils.translation import gettext_lazy as _
class LogEntryAdmin(admin.ModelAdmin):
"""
自定义管理员日志(LogEntry)的管理类
用于在Django admin后台展示和管理系统操作日志
"""
# 列表页的筛选器:按内容类型筛选
list_filter = [
'content_type'
]
# 搜索字段:支持按对象表示和变更消息搜索
search_fields = [
'object_repr',
'change_message'
'object_repr', # 对象的字符串表示
'change_message' # 操作变更的描述信息
]
# 列表页中可点击的链接字段
list_display_links = [
'action_time',
'get_change_message',
'action_time', # 操作时间
'get_change_message', # 变更消息
]
# 列表页展示的字段
list_display = [
'action_time',
'user_link',
'content_type',
'object_link',
'get_change_message',
'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):
"""
限制修改权限
- 仅超级用户或拥有change_logentry权限的用户可查看
- 禁止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):
"""
生成操作对象的链接若对象存在
对于已删除的对象仅显示文本对于存在的对象显示可点击的链接
"""
# 先对对象的字符串表示进行HTML转义防止XSS攻击
object_link = escape(obj.object_repr)
# 获取操作对象的内容类型
content_type = obj.content_type
# 如果不是删除操作且内容类型存在,尝试生成编辑链接
if obj.action_flag != DELETION and content_type is not None:
# try returning an actual link instead of object repr string
try:
# 反向解析对象的编辑页面URL
url = reverse(
# 生成admin的URL名称格式app_label_model_change
'admin:{}_{}_change'.format(content_type.app_label,
content_type.model),
args=[obj.object_id]
args=[obj.object_id] # 传递对象ID作为参数
)
# 生成带链接的HTML
object_link = '<a href="{}">{}</a>'.format(url, object_link)
except NoReverseMatch:
# 若无法解析URL如模型未注册到admin则只显示文本
pass
# 标记为安全字符串允许Django渲染HTML
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))
# 对用户名进行HTML转义
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]
args=[obj.user.pk] # 传递用户ID作为参数
)
# 生成带链接的HTML
user_link = '<a href="{}">{}</a>'.format(url, user_link)
except NoReverseMatch:
# 若无法解析URL只显示用户名
pass
# 标记为安全字符串允许渲染HTML
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):
"""优化查询集预加载content_type减少数据库查询次数"""
queryset = super(LogEntryAdmin, self).get_queryset(request)
return queryset.prefetch_related('content_type')
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
return actions
Loading…
Cancel
Save