Browse Source

[5.0.x] Fixed #34923 -- Avoided initializing LEVEL_TAGS when importing django.contrib.messages.

Regression in b7fe36ad37fb18c4bc7932c0aec6ae4f299b9622.

Thanks James Gillard for the report.

Backport of 311718feb5f1fb9ff794bbac0cda48cfc3410de8 from main
Mariusz Felisiak 1 year ago
parent
commit
00805ff436

+ 2 - 1
django/contrib/messages/apps.py

@@ -2,12 +2,13 @@ from django.apps import AppConfig
 from django.contrib.messages.storage import base
 from django.contrib.messages.utils import get_level_tags
 from django.core.signals import setting_changed
+from django.utils.functional import SimpleLazyObject
 from django.utils.translation import gettext_lazy as _
 
 
 def update_level_tags(setting, **kwargs):
     if setting == "MESSAGE_TAGS":
-        base.LEVEL_TAGS = get_level_tags()
+        base.LEVEL_TAGS = SimpleLazyObject(get_level_tags)
 
 
 class MessagesConfig(AppConfig):

+ 2 - 1
django/contrib/messages/storage/base.py

@@ -1,7 +1,8 @@
 from django.conf import settings
 from django.contrib.messages import constants, utils
+from django.utils.functional import SimpleLazyObject
 
-LEVEL_TAGS = utils.get_level_tags()
+LEVEL_TAGS = SimpleLazyObject(utils.get_level_tags)
 
 
 class Message:

+ 21 - 0
tests/messages_tests/tests.py

@@ -1,5 +1,6 @@
 from unittest import mock
 
+from django.conf import settings
 from django.contrib.messages import Message, add_message, constants
 from django.contrib.messages.storage import base
 from django.contrib.messages.test import MessagesTestMixin
@@ -63,6 +64,26 @@ class TestLevelTags(SimpleTestCase):
     def test_override_settings_level_tags(self):
         self.assertEqual(base.LEVEL_TAGS, self.message_tags)
 
+    def test_lazy(self):
+        # Don't use @override_settings to avoid calling the setting_changed
+        # signal.
+        old_message_tags = getattr(settings, "MESSAGE_TAGS", None)
+        settings.MESSAGE_TAGS = {constants.ERROR: "bad"}
+        try:
+            self.assertEqual(base.LEVEL_TAGS[constants.ERROR], "bad")
+        finally:
+            if old_message_tags is None:
+                del settings.MESSAGE_TAGS
+            else:
+                settings.MESSAGE_TAGS = old_message_tags
+
+    @override_settings(MESSAGE_TAGS=message_tags)
+    def test_override_settings_lazy(self):
+        # The update_level_tags handler has been called at least once before
+        # running this code when using @override_settings.
+        settings.MESSAGE_TAGS = {constants.ERROR: "very-bad"}
+        self.assertEqual(base.LEVEL_TAGS[constants.ERROR], "very-bad")
+
 
 class FakeResponse:
     def __init__(self):