From 989d52ef0525a27435ba8042c403b658e174b9e9 Mon Sep 17 00:00:00 2001 From: Marco Sirabella Date: Fri, 18 Aug 2023 18:16:52 -0700 Subject: [PATCH] Expose change reason to admin form Fixes #853 --- AUTHORS.rst | 1 + CHANGES.rst | 1 + simple_history/admin.py | 25 +++++++++++++++++++++++- simple_history/tests/tests/test_admin.py | 14 +++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 875e0173b..12eeb4383 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -90,6 +90,7 @@ Authors - Lucas Wiman - Maciej "RooTer" UrbaƄski - Marcelo Canina (`marcanuy `_) +- Marco Sirabella - Mark Davidoff - Martin Bachwerk - Marty Alchin diff --git a/CHANGES.rst b/CHANGES.rst index 0e6660d5c..596676194 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -24,6 +24,7 @@ Unreleased ``HistoricalRecords.context.request``) under some circumstances (gh-1188) - Made ``HistoryRequestMiddleware`` async-capable (gh-1209) - Fixed error when setting ``table_name`` with ``inherit=True`` (gh-1195) +- Allow setting change reason on admin panel modifications (gh-1232) 3.3.0 (2023-03-08) ------------------ diff --git a/simple_history/admin.py b/simple_history/admin.py index 34e3033fe..36aa395c2 100644 --- a/simple_history/admin.py +++ b/simple_history/admin.py @@ -1,4 +1,4 @@ -from django import http +from django import forms, http from django.apps import apps as django_apps from django.conf import settings from django.contrib import admin @@ -6,6 +6,7 @@ from django.contrib.admin.utils import unquote from django.contrib.auth import get_permission_codename, get_user_model from django.core.exceptions import PermissionDenied +from django.forms import fields from django.shortcuts import get_object_or_404, render from django.urls import re_path, reverse from django.utils.encoding import force_str @@ -224,9 +225,31 @@ def render_history_view(self, request, template, context, **kwargs): def save_model(self, request, obj, form, change): """Set special model attribute to user for reference after save""" + obj._change_reason = form.cleaned_data["change_reason"] obj._history_user = request.user super().save_model(request, obj, form, change) + class form(forms.ModelForm): + change_reason = forms.CharField(required=False) + + def get_fields(self, request, obj=None): + return [ + field + for field in super().get_fields(request, obj) + if field != "change_reason" + ] + + def get_fieldsets(self, request, obj=None): + return super().get_fieldsets(request, obj) + [ + ( + "History", + { + "classes": ["collapse"], + "fields": ["change_reason"], + }, + ) + ] + @property def content_type_model_cls(self): """Returns the ContentType model class.""" diff --git a/simple_history/tests/tests/test_admin.py b/simple_history/tests/tests/test_admin.py index 2b441030b..5093157a3 100644 --- a/simple_history/tests/tests/test_admin.py +++ b/simple_history/tests/tests/test_admin.py @@ -218,6 +218,20 @@ def test_history_user_on_save_in_admin(self): [p.history_user for p in Poll.history.all()], [self.user, self.user] ) + def test_history_change_reason_on_save_in_admin(self): + self.login() + + change_reason = "New change reason" + # Ensure polls created via admin interface save correct user + poll_data = { + "question": "new poll?", + "pub_date_0": "2012-01-01", + "pub_date_1": "10:00:00", + "change_reason": change_reason, + } + self.client.post(reverse("admin:tests_poll_add"), data=poll_data) + self.assertEqual(Poll.history.get().history_change_reason, change_reason) + def test_underscore_in_pk(self): self.login() book = Book(isbn="9780147_513731")