137 lines
4.3 KiB
Python
137 lines
4.3 KiB
Python
from django.contrib import admin
|
|
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
|
|
from django.contrib.contenttypes.models import ContentType
|
|
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 _
|
|
from django.utils.translation import pgettext_lazy
|
|
|
|
|
|
action_names = {
|
|
ADDITION: pgettext_lazy('logentry_admin:action_type', 'Addition'),
|
|
DELETION: pgettext_lazy('logentry_admin:action_type', 'Deletion'),
|
|
CHANGE: pgettext_lazy('logentry_admin:action_type', 'Change'),
|
|
}
|
|
|
|
|
|
class ActionListFilter(admin.SimpleListFilter):
|
|
title = _('action')
|
|
parameter_name = 'action_flag'
|
|
|
|
def lookups(self, request, model_admin): # noqa: D102
|
|
return action_names.items()
|
|
|
|
def queryset(self, request, queryset): # noqa: D102
|
|
if self.value():
|
|
queryset = queryset.filter(action_flag=self.value())
|
|
return queryset
|
|
|
|
|
|
class LogEntryAdmin(admin.ModelAdmin):
|
|
date_hierarchy = 'action_time'
|
|
|
|
readonly_fields = [f.name for f in LogEntry._meta.fields] + [
|
|
'object_link',
|
|
'action_description',
|
|
'user_link',
|
|
'get_change_message',
|
|
]
|
|
|
|
fieldsets = (
|
|
(
|
|
_('Metadata'),
|
|
{'fields': ('action_time', 'user_link', 'action_description', 'object_link',)},
|
|
),
|
|
(
|
|
_('Details'),
|
|
{'fields': ('get_change_message', 'content_type', 'object_id', 'object_repr',)},
|
|
),
|
|
)
|
|
|
|
list_filter = ['content_type', ActionListFilter]
|
|
|
|
search_fields = ['object_repr', 'change_message']
|
|
|
|
list_display_links = [
|
|
'action_time',
|
|
'get_change_message',
|
|
]
|
|
list_display = [
|
|
'action_time',
|
|
'user_link',
|
|
'content_type',
|
|
'object_link',
|
|
'action_description',
|
|
'get_change_message',
|
|
]
|
|
|
|
def has_add_permission(self, request): # noqa: D102
|
|
return False
|
|
|
|
def has_change_permission(self, request, obj=None): # noqa: D102
|
|
return False
|
|
|
|
def has_delete_permission(self, request, obj=None): # noqa: D102
|
|
return False
|
|
|
|
def object_link(self, obj): # noqa: D102
|
|
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 = reverse(
|
|
'admin:{}_{}_change'.format(content_type.app_label, content_type.model),
|
|
args=[obj.object_id],
|
|
)
|
|
object_link = '<a href="{}">{}</a>'.format(url, object_link)
|
|
except NoReverseMatch:
|
|
pass
|
|
return mark_safe(object_link)
|
|
|
|
object_link.admin_order_field = 'object_repr'
|
|
object_link.short_description = _('object')
|
|
|
|
def user_link(self, obj): # noqa: D102
|
|
content_type = ContentType.objects.get_for_model(type(obj.user))
|
|
user_link = escape(force_str(obj.user))
|
|
try:
|
|
# try returning an actual link instead of object repr string
|
|
url = reverse(
|
|
'admin:{}_{}_change'.format(content_type.app_label, content_type.model),
|
|
args=[obj.user.pk],
|
|
)
|
|
user_link = '<a href="{}">{}</a>'.format(url, user_link)
|
|
except NoReverseMatch:
|
|
pass
|
|
return mark_safe(user_link)
|
|
|
|
user_link.admin_order_field = 'user'
|
|
user_link.short_description = _('user')
|
|
|
|
def get_queryset(self, request): # noqa: D102
|
|
queryset = super(LogEntryAdmin, self).get_queryset(request)
|
|
return queryset.prefetch_related('content_type')
|
|
|
|
def get_actions(self, request): # noqa: D102
|
|
actions = super(LogEntryAdmin, self).get_actions(request)
|
|
actions.pop('delete_selected', None)
|
|
return actions
|
|
|
|
def action_description(self, obj): # noqa: D102
|
|
return action_names[obj.action_flag]
|
|
|
|
action_description.short_description = _('action')
|
|
|
|
def get_change_message(self, obj): # noqa: D102
|
|
# TODO: is this still required in newer Django versions?
|
|
return obj.change_message
|
|
|
|
get_change_message.short_description = _('change message')
|
|
|
|
|
|
admin.site.register(LogEntry, LogEntryAdmin)
|