diff --git a/.gitignore b/.gitignore index b992ac6..a661e32 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ *.pyc *.db local_settings.py +.pydevproject +.project diff --git a/src/auditlog/admin.py b/src/auditlog/admin.py index 5f985f5..f3f5c7d 100644 --- a/src/auditlog/admin.py +++ b/src/auditlog/admin.py @@ -1,9 +1,18 @@ from django.contrib import admin from .models import LogEntry +from .mixins import LogEntryAdminMixin +from .filters import ResourceTypeFilter + + +class LogEntryAdmin(admin.ModelAdmin, LogEntryAdminMixin): + list_display = ['created', 'resource_url', 'action', 'msg_short', 'user_url'] + search_fields = ['timestamp', 'object_repr', 'changes', 'actor__full_name'] + list_filter = ['action', ResourceTypeFilter] + readonly_fields = ['created', 'resource_url', 'action', 'user_url', 'msg'] + fieldsets = [ + (None, {'fields': ['created', 'user_url', 'resource_url']}), + ('Changes', {'fields': ['action', 'msg']}), + ] -class LogEntryAdmin(admin.ModelAdmin): - list_display = ('object_pk', 'object_repr', 'actor', 'action', 'changes', 'timestamp') - list_filter = ('content_type',) admin.site.register(LogEntry, LogEntryAdmin) - diff --git a/src/auditlog/filters.py b/src/auditlog/filters.py new file mode 100644 index 0000000..c5b651a --- /dev/null +++ b/src/auditlog/filters.py @@ -0,0 +1,16 @@ +from django.contrib.admin import SimpleListFilter + + +class ResourceTypeFilter(SimpleListFilter): + title = 'Resource Type' + parameter_name = 'resource_type' + + def lookups(self, request, model_admin): + qs = model_admin.get_queryset(request) + types = qs.values_list('content_type_id', 'content_type__model') + return list(types.order_by('content_type__model').distinct()) + + def queryset(self, request, queryset): + if self.value() is None: + return queryset + return queryset.filter(content_type_id=self.value()) diff --git a/src/auditlog/mixins.py b/src/auditlog/mixins.py new file mode 100644 index 0000000..a50907a --- /dev/null +++ b/src/auditlog/mixins.py @@ -0,0 +1,56 @@ +import json + +from django.conf import settings +from django.core import urlresolvers + +MAX = 75 + + +class LogEntryAdminMixin(object): + + def created(self, obj): + return obj.timestamp.strftime('%Y-%m-%d %H:%M:%S') + created.short_description = 'Created' + + def user_url(self, obj): + if obj.actor: + app_label, model = settings.AUTH_USER_MODEL.split('.') + viewname = 'admin:%s_%s_change' % (app_label, model.lower()) + link = urlresolvers.reverse(viewname, args=[obj.actor.id]) + return u'%s' % (link, obj.actor.full_name or obj.actor.email) + return 'system' + user_url.allow_tags = True + user_url.short_description = 'User' + + def resource_url(self, obj): + app_label, model = obj.content_type.app_label, obj.content_type.model + viewname = 'admin:%s_%s_change' % (app_label, model) + link = urlresolvers.reverse(viewname, args=[obj.object_id]) + return u'%s' % (link, obj.object_repr) + resource_url.allow_tags = True + resource_url.short_description = 'Resource' + + def msg_short(self, obj): + if obj.action == 2: + return '' # delete + changes = json.loads(obj.changes) + s = '' if len(changes) == 1 else 's' + fields = ', '.join(changes.keys()) + if len(fields) > MAX: + i = fields.rfind(' ', 0, MAX) + fields = fields[:i] + ' ..' + return '%d change%s: %s' % (len(changes), s, fields) + msg_short.short_description = 'Changes' + + def msg(self, obj): + if obj.action == 2: + return '' # delete + changes = json.loads(obj.changes) + msg = '
| # | Field | From | To |
|---|---|---|---|
| %s | %s | %s | %s |