from django.contrib import admin from django.templatetags.static import static from django.contrib.admin.templatetags.admin_urls import add_preserved_filters from django.contrib.admin.utils import unquote from django.http import HttpResponseRedirect from django.urls import NoReverseMatch, reverse from django.utils.html import format_html from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ from orchestra.admin.utils import admin_date, admin_link class LogEntryAdmin(admin.ModelAdmin): list_display = ( 'display_action_time', 'user_link', 'display_message', ) list_filter = ( 'action_flag', ('user', admin.RelatedOnlyFieldListFilter), ('content_type', admin.RelatedOnlyFieldListFilter), ) date_hierarchy = 'action_time' search_fields = ('object_repr', 'change_message', 'user__username') fields = ( 'user_link', 'content_object_link', 'display_action_time', 'display_action', 'change_message' ) readonly_fields = ( 'user_link', 'content_object_link', 'display_action_time', 'display_action', ) actions = None list_select_related = ('user', 'content_type') list_display_links = None user_link = admin_link('user') display_action_time = admin_date('action_time', short_description=_("Time")) @admin.display( description=_("Message"), ordering='action_flag', ) @mark_safe def display_message(self, log): edit = format_html('', **{ 'url': reverse('admin:admin_logentry_change', args=(log.pk,)), 'img': static('admin/img/icon-changelink.svg'), }) if log.is_addition(): return _('Added "%(link)s". %(edit)s') % { 'link': self.content_object_link(log), 'edit': edit } elif log.is_change(): return _('Changed "%(link)s" - %(changes)s %(edit)s') % { 'link': self.content_object_link(log), 'changes': log.get_change_message(), 'edit': edit, } elif log.is_deletion(): return _('Deleted "%(object)s." %(edit)s') % { 'object': log.object_repr, 'edit': edit, } @admin.display( description=_("Action"), ordering='action_flag', ) def display_action(self, log): if log.is_addition(): return _("Added") elif log.is_change(): return _("Changed") return _("Deleted") @admin.display( description=_("Content object"), ordering='object_repr', ) def content_object_link(self, log): ct = log.content_type view = 'admin:%s_%s_change' % (ct.app_label, ct.model) try: url = reverse(view, args=(log.object_id,)) except NoReverseMatch: return log.object_repr return format_html('{}', url, log.object_repr) def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): """ Add rel_opts and object to context """ if not add and 'edit' in request.GET.urlencode(): context.update({ 'rel_opts': obj.content_type.model_class()._meta, 'object': obj, }) return super(LogEntryAdmin, self).render_change_form( request, context, add, change, form_url, obj) def response_change(self, request, obj): """ save and continue preserve edit query string """ response = super(LogEntryAdmin, self).response_change(request, obj) if 'edit' in request.GET.urlencode() and 'edit' not in response.url: return HttpResponseRedirect(response.url + '?edit=True') return response def response_post_save_change(self, request, obj): """ save redirect to object history """ if 'edit' in request.GET.urlencode(): opts = obj.content_type.model_class()._meta view = 'admin:%s_%s_history' % (opts.app_label, opts.model_name) post_url = reverse(view, args=(obj.object_id,)) preserved_filters = self.get_preserved_filters(request) post_url = add_preserved_filters({ 'preserved_filters': preserved_filters, 'opts': opts }, post_url) return HttpResponseRedirect(post_url) return super(LogEntryAdmin, self).response_post_save_change(request, obj) def has_add_permission(self, *args, **kwargs): return False def has_delete_permission(self, *args, **kwargs): return False def log_addition(self, *args, **kwargs): pass def log_change(self, *args, **kwargs): pass def log_deletion(self, *args, **kwargs): pass admin.site.register(admin.models.LogEntry, LogEntryAdmin)