From 5d5149cd18aa846be88ebcfae5997268359f67bb Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 2 Apr 2011 08:36:04 +0000 Subject: [PATCH] Advanced deprecation of user-based messages and the LegacyFallbackStorage in contrib.messages. git-svn-id: http://code.djangoproject.com/svn/django/trunk@15975 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/conf/global_settings.py | 2 +- django/contrib/auth/models.py | 22 ------ django/contrib/messages/api.py | 2 - .../contrib/messages/storage/user_messages.py | 64 ----------------- django/contrib/messages/tests/__init__.py | 2 - django/contrib/messages/tests/base.py | 42 ----------- .../contrib/messages/tests/user_messages.py | 70 ------------------- docs/ref/contrib/messages.txt | 30 +------- 8 files changed, 2 insertions(+), 232 deletions(-) delete mode 100644 django/contrib/messages/storage/user_messages.py delete mode 100644 django/contrib/messages/tests/user_messages.py diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 50dbeeecac..c669285299 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -502,7 +502,7 @@ CSRF_COOKIE_DOMAIN = None ############ # Class to use as messges backend -MESSAGE_STORAGE = 'django.contrib.messages.storage.user_messages.LegacyFallbackStorage' +MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage' # Default values of MESSAGE_LEVEL and MESSAGE_TAGS are defined within # django.contrib.messages to avoid imports in this settings file. diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index 57d4b93e61..e0a7636086 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -345,13 +345,6 @@ class User(models.Model): return _user_has_module_perms(self, app_label) - def get_and_delete_messages(self): - messages = [] - for m in self.message_set.all(): - messages.append(m.message) - m.delete() - return messages - def email_user(self, subject, message, from_email=None): "Sends an email to this User." from django.core.mail import send_mail @@ -387,21 +380,6 @@ class User(models.Model): return self._profile_cache -class Message(models.Model): - """ - The message system is a lightweight way to queue messages for given - users. A message is associated with a User instance (so it is only - applicable for registered users). There's no concept of expiration or - timestamps. Messages are created by the Django admin after successful - actions. For example, "The poll Foo was created successfully." is a - message. - """ - user = models.ForeignKey(User, related_name='_message_set') - message = models.TextField(_('message')) - - def __unicode__(self): - return self.message - class AnonymousUser(object): id = None username = '' diff --git a/django/contrib/messages/api.py b/django/contrib/messages/api.py index 65fd188bf0..1079ae17db 100644 --- a/django/contrib/messages/api.py +++ b/django/contrib/messages/api.py @@ -20,8 +20,6 @@ def add_message(request, level, message, extra_tags='', fail_silently=False): """ if hasattr(request, '_messages'): return request._messages.add(level, message, extra_tags) - if hasattr(request, 'user') and request.user.is_authenticated(): - return request.user.message_set.create(message=message) if not fail_silently: raise MessageFailure('Without the django.contrib.messages ' 'middleware, messages can only be added to ' diff --git a/django/contrib/messages/storage/user_messages.py b/django/contrib/messages/storage/user_messages.py deleted file mode 100644 index 17f0c55290..0000000000 --- a/django/contrib/messages/storage/user_messages.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -Storages used to assist in the deprecation of contrib.auth User messages. - -""" -from django.contrib.messages import constants -from django.contrib.messages.storage.base import BaseStorage, Message -from django.contrib.auth.models import User -from django.contrib.messages.storage.fallback import FallbackStorage - - -class UserMessagesStorage(BaseStorage): - """ - Retrieves messages from the User, using the legacy user.message_set API. - - This storage is "read-only" insofar as it can only retrieve and delete - messages, not store them. - """ - session_key = '_messages' - - def _get_messages_queryset(self): - """ - Returns the QuerySet containing all user messages (or ``None`` if - request.user is not a contrib.auth User). - """ - user = getattr(self.request, 'user', None) - if isinstance(user, User): - return user._message_set.all() - - def add(self, *args, **kwargs): - raise NotImplementedError('This message storage is read-only.') - - def _get(self, *args, **kwargs): - """ - Retrieves a list of messages assigned to the User. This backend never - stores anything, so all_retrieved is assumed to be False. - """ - queryset = self._get_messages_queryset() - if queryset is None: - # This is a read-only and optional storage, so to ensure other - # storages will also be read if used with FallbackStorage an empty - # list is returned rather than None. - return [], False - messages = [] - for user_message in queryset: - messages.append(Message(constants.INFO, user_message.message)) - return messages, False - - def _store(self, messages, *args, **kwargs): - """ - Removes any messages assigned to the User and returns the list of - messages (since no messages are stored in this read-only storage). - """ - queryset = self._get_messages_queryset() - if queryset is not None: - queryset.delete() - return messages - - -class LegacyFallbackStorage(FallbackStorage): - """ - Works like ``FallbackStorage`` but also handles retrieving (and clearing) - contrib.auth User messages. - """ - storage_classes = (UserMessagesStorage,) + FallbackStorage.storage_classes diff --git a/django/contrib/messages/tests/__init__.py b/django/contrib/messages/tests/__init__.py index 84581e00e4..f3f6b653d0 100644 --- a/django/contrib/messages/tests/__init__.py +++ b/django/contrib/messages/tests/__init__.py @@ -2,5 +2,3 @@ from django.contrib.messages.tests.cookie import CookieTest from django.contrib.messages.tests.fallback import FallbackTest from django.contrib.messages.tests.middleware import MiddlewareTest from django.contrib.messages.tests.session import SessionTest -from django.contrib.messages.tests.user_messages import \ - UserMessagesTest, LegacyFallbackTest diff --git a/django/contrib/messages/tests/base.py b/django/contrib/messages/tests/base.py index 28fde7050d..932ca277db 100644 --- a/django/contrib/messages/tests/base.py +++ b/django/contrib/messages/tests/base.py @@ -60,9 +60,6 @@ class BaseTest(TestCase): self.storage_class.__name__) self.old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS settings.TEMPLATE_DIRS = () - self.save_warnings_state() - warnings.filterwarnings('ignore', category=DeprecationWarning, - module='django.contrib.auth.models') def tearDown(self): for setting in self.restore_settings: @@ -74,7 +71,6 @@ class BaseTest(TestCase): settings.INSTALLED_APPS = self._installed_apps settings.MESSAGE_STORAGE = self._message_storage settings.TEMPLATE_DIRS = self.old_TEMPLATE_DIRS - self.restore_warnings_state() def restore_setting(self, setting): if setting in self._remembered_settings: @@ -226,44 +222,6 @@ class BaseTest(TestCase): for msg in data['messages']: self.assertContains(response, msg) - @skipUnlessAuthIsInstalled - def test_middleware_disabled_auth_user(self): - """ - Tests that the messages API successfully falls back to using - user.message_set to store messages directly when the middleware is - disabled. - """ - settings.MESSAGE_LEVEL = constants.DEBUG - user = User.objects.create_user('test', 'test@example.com', 'test') - self.client.login(username='test', password='test') - settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) - settings.INSTALLED_APPS.remove( - 'django.contrib.messages', - ) - settings.MIDDLEWARE_CLASSES = list(settings.MIDDLEWARE_CLASSES) - settings.MIDDLEWARE_CLASSES.remove( - 'django.contrib.messages.middleware.MessageMiddleware', - ) - settings.TEMPLATE_CONTEXT_PROCESSORS = \ - list(settings.TEMPLATE_CONTEXT_PROCESSORS) - settings.TEMPLATE_CONTEXT_PROCESSORS.remove( - 'django.contrib.messages.context_processors.messages', - ) - data = { - 'messages': ['Test message %d' % x for x in xrange(10)], - } - show_url = reverse('django.contrib.messages.tests.urls.show') - for level in ('debug', 'info', 'success', 'warning', 'error'): - add_url = reverse('django.contrib.messages.tests.urls.add', - args=(level,)) - response = self.client.post(add_url, data, follow=True) - self.assertRedirects(response, show_url) - self.assertTrue('messages' in response.context) - context_messages = list(response.context['messages']) - for msg in data['messages']: - self.assertTrue(msg in context_messages) - self.assertContains(response, msg) - def test_middleware_disabled_anon_user(self): """ Tests that, when the middleware is disabled and a user is not logged diff --git a/django/contrib/messages/tests/user_messages.py b/django/contrib/messages/tests/user_messages.py deleted file mode 100644 index dad552c6fe..0000000000 --- a/django/contrib/messages/tests/user_messages.py +++ /dev/null @@ -1,70 +0,0 @@ -from django import http -from django.contrib.auth.models import User -from django.contrib.messages.storage.user_messages import UserMessagesStorage,\ - LegacyFallbackStorage -from django.contrib.messages.tests.base import skipUnlessAuthIsInstalled -from django.contrib.messages.tests.cookie import set_cookie_data -from django.contrib.messages.tests.fallback import FallbackTest -from django.test import TestCase - - -class UserMessagesTest(TestCase): - - def setUp(self): - self.user = User.objects.create(username='tester') - - def test_add(self): - storage = UserMessagesStorage(http.HttpRequest()) - self.assertRaises(NotImplementedError, storage.add, 'Test message 1') - - def test_get_anonymous(self): - # Ensure that the storage still works if no user is attached to the - # request. - storage = UserMessagesStorage(http.HttpRequest()) - self.assertEqual(len(storage), 0) - - def test_get(self): - storage = UserMessagesStorage(http.HttpRequest()) - storage.request.user = self.user - self.user.message_set.create(message='test message') - - self.assertEqual(len(storage), 1) - self.assertEqual(list(storage)[0].message, 'test message') - -UserMessagesTest = skipUnlessAuthIsInstalled(UserMessagesTest) - - -class LegacyFallbackTest(FallbackTest, TestCase): - storage_class = LegacyFallbackStorage - - def setUp(self): - super(LegacyFallbackTest, self).setUp() - self.user = User.objects.create(username='tester') - - def get_request(self, *args, **kwargs): - request = super(LegacyFallbackTest, self).get_request(*args, **kwargs) - request.user = self.user - return request - - def test_get_legacy_only(self): - request = self.get_request() - storage = self.storage_class(request) - self.user.message_set.create(message='user message') - - # Test that the message actually contains what we expect. - self.assertEqual(len(storage), 1) - self.assertEqual(list(storage)[0].message, 'user message') - - def test_get_legacy(self): - request = self.get_request() - storage = self.storage_class(request) - cookie_storage = self.get_cookie_storage(storage) - self.user.message_set.create(message='user message') - set_cookie_data(cookie_storage, ['cookie']) - - # Test that the message actually contains what we expect. - self.assertEqual(len(storage), 2) - self.assertEqual(list(storage)[0].message, 'user message') - self.assertEqual(list(storage)[1], 'cookie') - -LegacyFallbackTest = skipUnlessAuthIsInstalled(LegacyFallbackTest) diff --git a/docs/ref/contrib/messages.txt b/docs/ref/contrib/messages.txt index 838f492fd1..a23faef54d 100644 --- a/docs/ref/contrib/messages.txt +++ b/docs/ref/contrib/messages.txt @@ -83,37 +83,10 @@ Four storage classes are included: Since it is uses SessionStorage, it also requires Django's ``contrib.sessions`` application. -``'django.contrib.messages.storage.user_messages.LegacyFallbackStorage'`` - This is the default temporary storage class. - - This class extends FallbackStorage and adds compatibility methods - to retrieve any messages stored in the user Message model by code that - has not yet been updated to use the new API. This storage is temporary - (because it makes use of code that is pending deprecation) and will be - removed in Django 1.4. At that time, the default storage will become - ``django.contrib.messages.storage.fallback.FallbackStorage``. For more - information, see `LegacyFallbackStorage`_ below. - To write your own storage class, subclass the ``BaseStorage`` class in ``django.contrib.messages.storage.base`` and implement the ``_get`` and ``_store`` methods. -LegacyFallbackStorage -^^^^^^^^^^^^^^^^^^^^^ - -The ``LegacyFallbackStorage`` is a temporary tool to facilitate the transition -from the deprecated ``user.message_set`` API and will be removed in Django 1.4 -according to Django's standard deprecation policy. For more information, see -the full :doc:`release process documentation `. - -In addition to the functionality in the ``FallbackStorage``, it adds a custom, -read-only storage class that retrieves messages from the user ``Message`` -model. Any messages that were stored in the ``Message`` model (e.g., by code -that has not yet been updated to use the messages framework) will be retrieved -first, followed by those stored in a cookie and in the session, if any. Since -messages stored in the ``Message`` model do not have a concept of levels, they -will be assigned the ``INFO`` level by default. - Message levels -------------- @@ -368,14 +341,13 @@ This sets the minimum message that will be saved in the message storage. See MESSAGE_STORAGE --------------- -Default: ``'django.contrib.messages.storage.user_messages.LegacyFallbackStorage'`` +Default: ``'django.contrib.messages.storage.user_messages.FallbackStorage'`` Controls where Django stores message data. Valid values are: * ``'django.contrib.messages.storage.fallback.FallbackStorage'`` * ``'django.contrib.messages.storage.session.SessionStorage'`` * ``'django.contrib.messages.storage.cookie.CookieStorage'`` - * ``'django.contrib.messages.storage.user_messages.LegacyFallbackStorage'`` See `Storage backends`_ for more details.