diff options
| author | Akash Kumar Sen <Akash-Kumar-Sen@users.noreply.github.com> | 2023-06-12 08:50:55 +0530 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-10-31 18:06:44 +0100 |
| commit | 40b3975e7d3e1464a733c69171ad7d38f8814280 (patch) | |
| tree | dabd02bf22c82b52556931bb7c633b28753f6ab0 /tests/admin_utils | |
| parent | 45e0c5892f84b5bb47999cbe16eabb5a13293d85 (diff) | |
Fixed #34462 -- Made admin log actions in bulk.
This also deprecates ModelAdmin.log_deletion() and
LogEntryManager.log_action().
Diffstat (limited to 'tests/admin_utils')
| -rw-r--r-- | tests/admin_utils/models.py | 24 | ||||
| -rw-r--r-- | tests/admin_utils/test_logentry.py | 143 |
2 files changed, 139 insertions, 28 deletions
diff --git a/tests/admin_utils/models.py b/tests/admin_utils/models.py index 243f314b03..8e812e27eb 100644 --- a/tests/admin_utils/models.py +++ b/tests/admin_utils/models.py @@ -1,4 +1,5 @@ from django.contrib import admin +from django.contrib.admin.models import LogEntry, LogEntryManager from django.db import models from django.utils.translation import gettext_lazy as _ @@ -86,3 +87,26 @@ class VehicleMixin(Vehicle): class Car(VehicleMixin): pass + + +class InheritedLogEntryManager(LogEntryManager): + model = LogEntry + + def log_action( + self, + user_id, + content_type_id, + object_id, + object_repr, + action_flag, + change_message="", + ): + return LogEntry.objects.create( + user_id=user_id, + content_type_id=content_type_id, + object_id=str(object_id), + # Changing actual repr to test repr + object_repr="Test Repr", + action_flag=action_flag, + change_message=change_message, + ) diff --git a/tests/admin_utils/test_logentry.py b/tests/admin_utils/test_logentry.py index b700fe54b9..20bbcccb1c 100644 --- a/tests/admin_utils/test_logentry.py +++ b/tests/admin_utils/test_logentry.py @@ -8,9 +8,10 @@ from django.contrib.contenttypes.models import ContentType from django.test import TestCase, override_settings from django.urls import reverse from django.utils import translation +from django.utils.deprecation import RemovedInDjango60Warning from django.utils.html import escape -from .models import Article, ArticleProxy, Car, Site +from .models import Article, ArticleProxy, Car, InheritedLogEntryManager, Site @override_settings(ROOT_URLCONF="admin_utils.urls") @@ -26,14 +27,22 @@ class LogEntryTests(TestCase): title="Title", created=datetime(2008, 3, 12, 11, 54), ) - content_type_pk = ContentType.objects.get_for_model(Article).pk - LogEntry.objects.log_action( + cls.a2 = Article.objects.create( + site=cls.site, + title="Title 2", + created=datetime(2009, 3, 12, 11, 54), + ) + cls.a3 = Article.objects.create( + site=cls.site, + title="Title 3", + created=datetime(2010, 3, 12, 11, 54), + ) + LogEntry.objects.log_actions( cls.user.pk, - content_type_pk, - cls.a1.pk, - repr(cls.a1), + [cls.a1], CHANGE, change_message="Changed something", + single_object=True, ) def setUp(self): @@ -227,18 +236,95 @@ class LogEntryTests(TestCase): logentry = LogEntry.objects.first() self.assertEqual(repr(logentry), str(logentry.action_time)) + # RemovedInDjango60Warning. def test_log_action(self): - content_type_pk = ContentType.objects.get_for_model(Article).pk - log_entry = LogEntry.objects.log_action( - self.user.pk, - content_type_pk, - self.a1.pk, - repr(self.a1), - CHANGE, - change_message="Changed something else", - ) + msg = "LogEntryManager.log_action() is deprecated. Use log_actions() instead." + content_type_val = ContentType.objects.get_for_model(Article).pk + with self.assertWarnsMessage(RemovedInDjango60Warning, msg): + log_entry = LogEntry.objects.log_action( + self.user.pk, + content_type_val, + self.a1.pk, + repr(self.a1), + CHANGE, + change_message="Changed something else", + ) self.assertEqual(log_entry, LogEntry.objects.latest("id")) + def test_log_actions(self): + queryset = Article.objects.all().order_by("-id") + msg = "Deleted Something" + content_type = ContentType.objects.get_for_model(self.a1) + self.assertEqual(len(queryset), 3) + with self.assertNumQueries(1): + LogEntry.objects.log_actions( + self.user.pk, + queryset, + DELETION, + change_message=msg, + ) + logs = ( + LogEntry.objects.filter(action_flag=DELETION) + .order_by("id") + .values_list( + "user", + "content_type", + "object_id", + "object_repr", + "action_flag", + "change_message", + ) + ) + expected_log_values = [ + ( + self.user.pk, + content_type.id, + str(obj.pk), + str(obj), + DELETION, + msg, + ) + for obj in queryset + ] + self.assertSequenceEqual(logs, expected_log_values) + + # RemovedInDjango60Warning. + def test_log_action_fallback(self): + LogEntry.objects2 = InheritedLogEntryManager() + queryset = Article.objects.all().order_by("-id") + content_type = ContentType.objects.get_for_model(self.a1) + self.assertEqual(len(queryset), 3) + msg = ( + "The usage of log_action() is deprecated. Implement log_actions() instead." + ) + with self.assertNumQueries(3): + with self.assertWarnsMessage(RemovedInDjango60Warning, msg): + LogEntry.objects2.log_actions(self.user.pk, queryset, DELETION) + log_values = ( + LogEntry.objects.filter(action_flag=DELETION) + .order_by("id") + .values_list( + "user", + "content_type", + "object_id", + "object_repr", + "action_flag", + "change_message", + ) + ) + expected_log_values = [ + ( + self.user.pk, + content_type.id, + str(obj.pk), + "Test Repr", + DELETION, + "", + ) + for obj in queryset + ] + self.assertSequenceEqual(log_values, expected_log_values) + def test_recentactions_without_content_type(self): """ If a LogEntry is missing content_type it will not display it in span @@ -248,7 +334,7 @@ class LogEntryTests(TestCase): link = reverse("admin:admin_utils_article_change", args=(quote(self.a1.pk),)) should_contain = """<a href="%s">%s</a>""" % ( escape(link), - escape(repr(self.a1)), + escape(str(self.a1)), ) self.assertContains(response, should_contain) should_contain = "Article" @@ -320,28 +406,29 @@ class LogEntryTests(TestCase): self.assertEqual(log.get_action_flag_display(), display_name) def test_hook_get_log_entries(self): - LogEntry.objects.log_action( + LogEntry.objects.log_actions( self.user.pk, - ContentType.objects.get_for_model(Article).pk, - self.a1.pk, - "Article changed", + [self.a1], CHANGE, change_message="Article changed message", + single_object=True, ) c1 = Car.objects.create() - LogEntry.objects.log_action( + LogEntry.objects.log_actions( self.user.pk, - ContentType.objects.get_for_model(Car).pk, - c1.pk, - "Car created", + [c1], ADDITION, change_message="Car created message", + single_object=True, ) + exp_str_article = escape(str(self.a1)) + exp_str_car = escape(str(c1)) + response = self.client.get(reverse("admin:index")) - self.assertContains(response, "Article changed") - self.assertContains(response, "Car created") + self.assertContains(response, exp_str_article) + self.assertContains(response, exp_str_car) # site "custom_admin" only renders log entries of registered models response = self.client.get(reverse("custom_admin:index")) - self.assertContains(response, "Article changed") - self.assertNotContains(response, "Car created") + self.assertContains(response, exp_str_article) + self.assertNotContains(response, exp_str_car) |
