可以通过Django的admin监控django_admin_log吗?

发布于 2024-08-21 05:13:09 字数 128 浏览 5 评论 0原文

django_admin_log对于监控管理员中用户的操作非常有用。现在,我可以通过直接查询数据库来实现这一点。是否有内置功能可以让我通过 Django 管理员查看所有用户的 django_admin_log 表?

The table django_admin_log is useful to monitor the actions of users in the admin. Right now, I can achieve that by querying the database directly. Is there a built-in functionality where I can view the table django_admin_log through Django's admin for all users?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

雪化雨蝶 2024-08-28 05:13:09

你不能只是:

from django.contrib.admin.models import LogEntry
admin.site.register(LogEntry)

在你的 admin.py 文件之一中吗?我刚刚测试了它,它是准系统,但它可以工作。

您可能想要更具体,并为 LogEntry 创建一个 ModelAdmin 类,以提供更好的列表视图以及一些过滤功能。但这应该有效。

Can't you just:

from django.contrib.admin.models import LogEntry
admin.site.register(LogEntry)

In one of your admin.py files? I just tested it and it is barebones but it works.

You might want to be more specific and create a ModelAdmin class for LogEntry to provide for a better list view and maybe some filtering abilities. But that should work.

源来凯始玺欢你 2024-08-28 05:13:09

这是我的版本。 可用字段的参考。

class LogAdmin(admin.ModelAdmin):
    """Create an admin view of the history/log table"""
    list_display = ('action_time','user','content_type','change_message','is_addition','is_change','is_deletion')
    list_filter = ['action_time','user','content_type']
    ordering = ('-action_time',)
    #We don't want people changing this historical record:
    def has_add_permission(self, request):
        return False
    def has_change_permission(self, request, obj=None):
        #returning false causes table to not show up in admin page :-(
        #I guess we have to allow changing for now
        return True
    def has_delete_permission(self, request, obj=None):
        return False

Here's my version. Reference for fields available.

class LogAdmin(admin.ModelAdmin):
    """Create an admin view of the history/log table"""
    list_display = ('action_time','user','content_type','change_message','is_addition','is_change','is_deletion')
    list_filter = ['action_time','user','content_type']
    ordering = ('-action_time',)
    #We don't want people changing this historical record:
    def has_add_permission(self, request):
        return False
    def has_change_permission(self, request, obj=None):
        #returning false causes table to not show up in admin page :-(
        #I guess we have to allow changing for now
        return True
    def has_delete_permission(self, request, obj=None):
        return False
歌枕肩 2024-08-28 05:13:09

这是一个更广泛的管理配置,用于查看依赖于 Django 2.1 仅查看权限的所有日志条目:

from django.contrib import admin
from django.contrib.admin.models import LogEntry, DELETION
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.urls import reverse

@admin.register(LogEntry)
class LogEntryAdmin(admin.ModelAdmin):
    date_hierarchy = 'action_time'
    readonly_fields = ('action_time',)
    list_filter = ['user', 'content_type']
    search_fields = ['object_repr', 'change_message']
    list_display = ['__str__', 'content_type', 'action_time', 'user', 'object_link']

    # keep only view permission
    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

    def object_link(self, obj):
        if obj.action_flag == DELETION:
            link = obj.object_repr
        else:
            ct = obj.content_type
            try:
                link = mark_safe('<a href="%s">%s</a>' % (
                                 reverse('admin:%s_%s_change' % (ct.app_label, ct.model),
                                         args=[obj.object_id]),
                                 escape(obj.object_repr),
                ))
            except NoReverseMatch:
                link = obj.object_repr
        return link
    object_link.admin_order_field = 'object_repr'
    object_link.short_description = 'object'

    def queryset(self, request):
        return super(LogEntryAdmin, self).queryset(request) \
            .prefetch_related('content_type')

它基于 this Django 片段 和结果如下所示:

screenshot of log items

如果您想将其与早期的 Django 一起使用版本,请参阅此答案的此早期版本

Here's a more extensive admin configuration for viewing all log entries that relies on Django 2.1 view-only permissions:

from django.contrib import admin
from django.contrib.admin.models import LogEntry, DELETION
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.urls import reverse

@admin.register(LogEntry)
class LogEntryAdmin(admin.ModelAdmin):
    date_hierarchy = 'action_time'
    readonly_fields = ('action_time',)
    list_filter = ['user', 'content_type']
    search_fields = ['object_repr', 'change_message']
    list_display = ['__str__', 'content_type', 'action_time', 'user', 'object_link']

    # keep only view permission
    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

    def object_link(self, obj):
        if obj.action_flag == DELETION:
            link = obj.object_repr
        else:
            ct = obj.content_type
            try:
                link = mark_safe('<a href="%s">%s</a>' % (
                                 reverse('admin:%s_%s_change' % (ct.app_label, ct.model),
                                         args=[obj.object_id]),
                                 escape(obj.object_repr),
                ))
            except NoReverseMatch:
                link = obj.object_repr
        return link
    object_link.admin_order_field = 'object_repr'
    object_link.short_description = 'object'

    def queryset(self, request):
        return super(LogEntryAdmin, self).queryset(request) \
            .prefetch_related('content_type')

It is based on this Django snippet and the result looks like this:

screenshot of log entries

If you want to use it with earlier Django versions, see this earlier revision of this answer.

灯下孤影 2024-08-28 05:13:09

根据我的经验,有几点:

  • 将所有字段设置为只读是很好的。
    一个原因显然是因为这些是日志,不应该是可变的,但另一个原因是性能。例如,如果您允许更改用户,那么如果您有数十万用户(如我的情况),则单独加载更改页面可能会出现问题。否则,您可以使用raw_id_fields
  • 内容类型过滤器值未按模型排序,因此不友好,但没有很好的通用解决方案可供共享。
  • 我还为操作创建了过滤器,因为原始模型没有 CHOICES 字段,并且仅使用 action_flag 作为过滤器将显示 1,2,3 作为选项,这不是'非常用户友好:

    类 ActionFlagFilter(admin.SimpleListFilter):
        title = '操作标志过滤器'
    
        参数名称 = '动作标志'
    
        def 查找(自身、请求、model_admin):
            返回 (
                (添加,“添加”),
                (改变,“改变”),
                (删除,“删除”),
            )
    
        def 查询集(自身,请求,查询集):
            如果 self.value():
                返回queryset.filter(action_flag=self.value())
            返回查询集
    

Few points from my experience:

  • It's good to make all fields read only.
    One reason is obviously because those are logs and should not be mutable, but another is performance. If you allow changing users for example, loading of change page on it's own can be issue if you have hundreds of thousands of users as in my case. Otherwise you can use raw_id_fields.
  • Content type filter values are unsorted by model so it's unfriendly, but don't have nice generic solution to share.
  • I also created filter for action as orignal model does not have CHOICES field and using just action_flag as filter will show 1,2,3 as choices, which isn't very user friendly:

    class ActionFlagFilter(admin.SimpleListFilter):
        title = 'Action flag filter'
    
        parameter_name = 'action_flag'
    
        def lookups(self, request, model_admin):
            return (
                (ADDITION, "Add"),
                (CHANGE, "Change"),
                (DELETION, "Delete"),
            )
    
        def queryset(self, request, queryset):
            if self.value():
                return queryset.filter(action_flag=self.value())
            return queryset
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文