diff --git a/django/contrib/messages/api.py b/django/contrib/messages/api.py index 4164f2785b..715973761e 100644 --- a/django/contrib/messages/api.py +++ b/django/contrib/messages/api.py @@ -1,4 +1,5 @@ from django.contrib.messages import constants +from django.contrib.messages.storage import default_storage from django.utils.functional import lazy, memoize __all__ = ( @@ -44,6 +45,34 @@ def get_messages(request): return lazy(memoize(get_user().get_and_delete_messages, {}, 0), list)() +def get_level(request): + """ + Returns the minimum level of messages to be recorded. + + The default level is the ``MESSAGE_LEVEL`` setting. If this is not found, + the ``INFO`` level is used. + """ + if hasattr(request, '_messages'): + storage = request._messages + else: + storage = default_storage(request) + return storage.level + + +def set_level(request, level): + """ + Sets the minimum level of messages to be recorded, returning ``True`` if + the level was recorded successfully. + + If set to ``None``, the default level will be used (see the ``get_level`` + method). + """ + if not hasattr(request, '_messages'): + return False + request._messages.level = level + return True + + def debug(request, message, extra_tags='', fail_silently=False): """ Adds a message with the ``DEBUG`` level. diff --git a/django/contrib/messages/tests/base.py b/django/contrib/messages/tests/base.py index 6ca9185f62..d0edce95da 100644 --- a/django/contrib/messages/tests/base.py +++ b/django/contrib/messages/tests/base.py @@ -3,11 +3,11 @@ from django.test import TestCase from django.conf import settings from django.utils.translation import ugettext_lazy from django.contrib.messages import constants, utils +from django.contrib.messages.api import MessageFailure, get_level, set_level from django.contrib.messages.storage import default_storage, base from django.contrib.messages.storage.base import Message from django.core.urlresolvers import reverse from django.contrib.auth.models import User -from django.contrib.messages.api import MessageFailure def add_level_messages(storage): @@ -41,16 +41,19 @@ class BaseTest(TestCase): if hasattr(settings, setting): self._remembered_settings[setting] = getattr(settings, setting) delattr(settings._wrapped, setting) - # backup these manually because we do not want them deleted + # Backup these manually because we do not want them deleted. self._middleware_classes = settings.MIDDLEWARE_CLASSES self._template_context_processors = \ settings.TEMPLATE_CONTEXT_PROCESSORS self._installed_apps = settings.INSTALLED_APPS + self._message_storage = settings.MESSAGE_STORAGE + settings.MESSAGE_STORAGE = '%s.%s' % (self.storage_class.__module__, + self.storage_class.__name__) def tearDown(self): for setting in self.restore_settings: self.restore_setting(setting) - # restore these manually (see above) + # Restore these manually (see above). settings.MIDDLEWARE_CLASSES = self._middleware_classes settings.TEMPLATE_CONTEXT_PROCESSORS = \ self._template_context_processors @@ -319,25 +322,48 @@ class BaseTest(TestCase): self.assert_(storage.added_new) def test_default_level(self): + # get_level works even with no storage on the request. + request = self.get_request() + self.assertEqual(get_level(request), constants.INFO) + + # get_level returns the default level if it hasn't been set. storage = self.get_storage() + request._messages = storage + self.assertEqual(get_level(request), constants.INFO) + + # Only messages of sufficient level get recorded. add_level_messages(storage) self.assertEqual(len(storage), 5) def test_low_level(self): - storage = self.get_storage() - storage.level = 5 + request = self.get_request() + storage = self.storage_class(request) + request._messages = storage + + self.assert_(set_level(request, 5)) + self.assertEqual(get_level(request), 5) + add_level_messages(storage) self.assertEqual(len(storage), 6) def test_high_level(self): - storage = self.get_storage() - storage.level = 30 + request = self.get_request() + storage = self.storage_class(request) + request._messages = storage + + self.assert_(set_level(request, 30)) + self.assertEqual(get_level(request), 30) + add_level_messages(storage) self.assertEqual(len(storage), 2) def test_settings_level(self): + request = self.get_request() + storage = self.storage_class(request) + settings.MESSAGE_LEVEL = 29 - storage = self.get_storage() + self.assertEqual(get_level(request), 29) + add_level_messages(storage) self.assertEqual(len(storage), 3) diff --git a/docs/ref/contrib/messages.txt b/docs/ref/contrib/messages.txt index 7cfe4ae85a..554e70b1f2 100644 --- a/docs/ref/contrib/messages.txt +++ b/docs/ref/contrib/messages.txt @@ -137,8 +137,11 @@ Constant Purpose ``ERROR`` An action was **not** successful or some other failure occurred =========== ======== -The `MESSAGE_LEVEL`_ setting can be used to change the minimum recorded -level. Attempts to add messages of a level less than this will be ignored. +The `MESSAGE_LEVEL`_ setting can be used to change the minimum recorded level +(or it can be `changed per request`_). Attempts to add messages of a level less +than this will be ignored. + +.. _`changed per request`: `Changing the minimum recorded level per-request`_ Message tags ------------ @@ -245,22 +248,27 @@ provide a mapping via the `MESSAGE_TAGS`_ setting. Changing the minimum recorded level per-request ----------------------------------------------- -The minimum recorded level can be set per request by changing the ``level`` -attribute of the messages storage instance:: +The minimum recorded level can be set per request via the ``set_level`` +method:: from django.contrib import messages # Change the messages level to ensure the debug message is added. - messages.get_messages(request).level = messages.DEBUG + messages.set_level(request, messages.DEBUG) messages.debug(request, 'Test message...') # In another request, record only messages with a level of WARNING and higher - messages.get_messages(request).level = messages.WARNING + messages.set_level(request, messages.WARNING) messages.success(request, 'Your profile was updated.') # ignored messages.warning(request, 'Your account is about to expire.') # recorded # Set the messages level back to default. - messages.get_messages(request).level = None + messages.set_level(request, None) + +Similarly, the current effective level can be retrieved with ``get_level``:: + + from django.contrib import messages + current_level = messages.get_level(request) For more information on how the minimum recorded level functions, see `Message levels`_ above.