history view for modeladmin

pull/7571/head
Matt Westcott 2021-09-15 14:37:27 +01:00
rodzic 718232ead4
commit 57f150522d
5 zmienionych plików z 90 dodań i 3 usunięć

Wyświetl plik

@ -59,7 +59,7 @@ class ModelAdminURLFinder:
class PageAdminURLHelper(AdminURLHelper):
def get_action_url(self, action, *args, **kwargs):
if action in ('add', 'edit', 'delete', 'unpublish', 'copy'):
if action in ('add', 'edit', 'delete', 'unpublish', 'copy', 'history'):
url_name = 'wagtailadmin_pages:%s' % action
target_url = reverse(url_name, args=args, kwargs=kwargs)
return '%s?next=%s' % (target_url, quote(self.index_url))

Wyświetl plik

@ -17,7 +17,8 @@ from .helpers import (
PageButtonHelper, PagePermissionHelper, PermissionHelper)
from .menus import GroupMenuItem, ModelAdminMenuItem, SubMenu
from .mixins import ThumbnailMixin # NOQA
from .views import ChooseParentView, CreateView, DeleteView, EditView, IndexView, InspectView
from .views import (
ChooseParentView, CreateView, DeleteView, EditView, HistoryView, IndexView, InspectView)
class WagtailRegisterable:
@ -84,6 +85,7 @@ class ModelAdmin(WagtailRegisterable):
inspect_view_fields = []
inspect_view_fields_exclude = []
inspect_view_enabled = False
history_view_enabled = True
empty_value_display = '-'
list_filter = ()
list_select_related = False
@ -97,12 +99,14 @@ class ModelAdmin(WagtailRegisterable):
edit_view_class = EditView
inspect_view_class = InspectView
delete_view_class = DeleteView
history_view_class = HistoryView
choose_parent_view_class = ChooseParentView
index_template_name = ''
create_template_name = ''
edit_template_name = ''
inspect_template_name = ''
delete_template_name = ''
history_template_name = ''
choose_parent_template_name = ''
search_handler_class = DjangoORMSearchHandler
extra_search_kwargs = {}
@ -420,6 +424,11 @@ class ModelAdmin(WagtailRegisterable):
view_class = self.delete_view_class
return view_class.as_view(**kwargs)(request)
def history_view(self, request, instance_pk):
kwargs = {'model_admin': self, 'instance_pk': instance_pk}
view_class = self.history_view_class
return view_class.as_view(**kwargs)(request)
def get_edit_handler(self, instance, request):
"""
Returns the appropriate edit_handler for this modeladmin class.
@ -484,6 +493,15 @@ class ModelAdmin(WagtailRegisterable):
"""
return self.inspect_template_name or self.get_templates('inspect')
def get_history_template(self):
"""
Returns a template to be used when rendering 'history_view'. If a
template is specified by the 'history_template_name' attribute, that
will be used. Otherwise, a list of preferred template names are
returned.
"""
return self.history_template_name or self.get_templates('history')
def get_create_template(self):
"""
Returns a template to be used when rendering 'create_view'. If a
@ -559,6 +577,13 @@ class ModelAdmin(WagtailRegisterable):
self.inspect_view,
name=self.url_helper.get_action_url_name('inspect')),
)
if self.history_view_enabled:
urls = urls + (
re_path(
self.url_helper.get_action_url_pattern('history'),
self.history_view,
name=self.url_helper.get_action_url_name('history')),
)
if self.is_pagemodel:
urls = urls + (
re_path(

Wyświetl plik

@ -0,0 +1 @@
{% extends "wagtailadmin/generic/index.html" %}

Wyświetl plik

@ -1,15 +1,19 @@
import datetime
from io import BytesIO
from unittest import mock
from django.contrib.auth.models import Group
from django.contrib.contenttypes.models import ContentType
from django.core import checks
from django.test import TestCase
from django.utils.timezone import make_aware
from openpyxl import load_workbook
from wagtail.admin.admin_url_finder import AdminURLFinder
from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface
from wagtail.contrib.modeladmin.helpers.search import DjangoORMSearchHandler
from wagtail.core.models import Page
from wagtail.core.models import ModelLogEntry, Page
from wagtail.images.models import Image
from wagtail.images.tests.utils import get_test_image_file
from wagtail.tests.modeladmintest.models import Author, Book, Publisher, RelatedLink, Token
@ -623,6 +627,26 @@ class TestEditorAccess(TestCase, WagtailTestUtils):
self.assertRedirects(response, '/admin/')
class TestHistoryView(TestCase, WagtailTestUtils):
fixtures = ['modeladmintest_test.json']
def setUp(self):
self.login()
ModelLogEntry.objects.create(
content_type=ContentType.objects.get_for_model(Book),
label="The Lord of the Rings",
action='wagtail.create',
timestamp=make_aware(datetime.datetime(2021, 9, 30, 10, 1, 0)),
object_id='1',
)
def test_simple(self):
response = self.client.get('/admin/modeladmintest/book/history/1/')
self.assertEqual(response.status_code, 200)
self.assertContains(response, '<td>Created</td>', html=True)
self.assertContains(response, '<div class="human-readable-date" title="Sept. 30, 2021, 10:01 a.m.">')
class TestQuoting(TestCase, WagtailTestUtils):
fixtures = ['modeladmintest_test.json']
expected_status_code = 200

Wyświetl plik

@ -27,10 +27,14 @@ from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy
from django.views.generic import TemplateView
from django.views.generic.edit import FormView
from django.views.generic.list import MultipleObjectMixin
from wagtail.admin import messages
from wagtail.admin.ui.tables import Column, DateColumn, Table, UserColumn
from wagtail.admin.views.generic.base import WagtailAdminTemplateMixin
from wagtail.admin.views.mixins import SpreadsheetExportMixin
from wagtail.core.log_actions import log
from wagtail.core.log_actions import registry as log_registry
from .forms import ParentChooserForm
@ -958,3 +962,36 @@ class InspectView(InstanceSpecificView):
def get_template_names(self):
return self.model_admin.get_inspect_template()
class HistoryView(MultipleObjectMixin, WagtailAdminTemplateMixin, InstanceSpecificView):
page_title = gettext_lazy('History')
paginate_by = 50
columns = [
Column('message', label=gettext_lazy("Action")),
UserColumn('user', blank_display_name='system'),
DateColumn('timestamp', label=gettext_lazy("Date")),
]
def get_page_subtitle(self):
return str(self.instance)
def get_template_names(self):
return self.model_admin.get_history_template()
def get_queryset(self):
return log_registry.get_logs_for_instance(self.instance).prefetch_related('user__wagtail_userprofile')
def get_context_data(self, **kwargs):
self.object_list = self.get_queryset()
context = super().get_context_data(**kwargs)
index_url = self.url_helper.get_action_url('history', quote(self.instance.pk))
table = Table(
self.columns, context['object_list'], base_url=index_url, ordering=self.get_ordering()
)
context['table'] = table
context['media'] = table.media
context['index_url'] = index_url
context['is_paginated'] = True
return context