View all log entries in the admin

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from django.contrib.admin.models import LogEntry, DELETION
from django.utils.html import escape
from django.core.urlresolvers import reverse


class LogEntryAdmin(admin.ModelAdmin):

    date_hierarchy = 'action_time'

    readonly_fields = LogEntry._meta.get_all_field_names()

    list_filter = [
        'user',
        'content_type',
        'action_flag'
    ]

    search_fields = [
        'object_repr',
        'change_message'
    ]


    list_display = [
        'action_time',
        'user',
        'content_type',
        'object_link',
        'action_flag',
        'change_message',
    ]

    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return request.user.is_superuser and request.method != 'POST'

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

    def object_link(self, obj):
        if obj.action_flag == DELETION:
            link = escape(obj.object_repr)
        else:
            ct = obj.content_type
            link = u'<a href="%s">%s</a>' % (
                reverse('admin:%s_%s_change' % (ct.app_label, ct.model), args=[obj.object_id]),
                escape(obj.object_repr),
            )
        return link
    object_link.allow_tags = True
    object_link.admin_order_field = 'object_repr'
    object_link.short_description = u'object'
    
    def queryset(self, request):
        return super(LogEntryAdmin, self).queryset(request) \
            .prefetch_related('content_type')


admin.site.register(LogEntry, LogEntryAdmin)

More like this

  1. Admin log entries management utils by frankban 2 years, 7 months ago
  2. View all log entries in the admin 2 by tgandor 4 months, 1 week ago
  3. Add buttons in admin forms by mamat 5 years, 7 months ago
  4. Simple solution for model schema evolution / database changelog by kahless 6 years, 10 months ago
  5. Extended logging module by onlinehero 4 years, 9 months ago

Comments

djibril (on July 11, 2011):

Useful snippet! Thanks I think some small things are needed:

  1. in imports from django.core.urlresolvers import reverse

  2. change : object_link_field.allow_tags = True object_link_field.admin_order_field = 'object_repr' object_link_field.short_description = u'object'

to object_link.allow_tags = True object_link.admin_order_field = 'object_repr' object_link.short_description = u'object'

#

jakub (on July 12, 2011):

Thanks for pointing out the errors. It was copied from my project and I made some last changes introducing the errors here in the form. I've updated the snippet so it should work out of the box now.

#

Zorpix (on August 6, 2013):

When I put this in my app, it gave me a reverse error. To fix it, I had to change:

else: ct = obj.content_type link = u'[HTML_REMOVED]%s[HTML_REMOVED]' % ( reverse('admin:%s_%s_change' % (ct.app_label, ct.model), args=[obj.object_id]), escape(obj.object_repr), ) return link

to: else: ct = obj.content_type return u'[HTML_REMOVED][HTML_REMOVED]

#

rwmcfa1 (on August 19, 2013):

i would suggest adding an override for the queryset method to avoid a very large number of queries for content_type.

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

for me that reduces the number of queries from ~100 to ~8.

#

tgandor (on December 11, 2013):

The comment by Zorpix was cut out by the "HTML-filtering" ('t was just code... should just HTML-escape it, right?)

Anyway, I used this snippet to much enjoyment, but also found issues:

  1. Crashes on non-reversible admin URLs (e.g. removed objects, or objects which are not registered in the admin site)
  2. Filtering by users - my site has over 600 users, and only 10-20 staff. The list_filter on all users was totally impractical, and scrolled over many screens.

I made a few tweaks to get rid of these problems, and came up with this:

https://djangosnippets.org/snippets/3009/

#

(Forgotten your password?)