Index: django/conf/global_settings.py
===================================================================
--- django/conf/global_settings.py	(revision 6894)
+++ django/conf/global_settings.py	(working copy)
@@ -154,6 +154,7 @@
     'django.core.context_processors.debug',
     'django.core.context_processors.i18n',
     'django.core.context_processors.media',
+    'django.core.context_processors.messages',
 #    'django.core.context_processors.request',
 )
 
Index: django/core/context_processors.py
===================================================================
--- django/core/context_processors.py	(revision 6894)
+++ django/core/context_processors.py	(working copy)
@@ -24,10 +24,49 @@
         user = AnonymousUser()
     return {
         'user': user,
-        'messages': user.get_and_delete_messages(),
         'perms': PermWrapper(user),
     }
 
+class LazyMessages(object):
+    def __init__(self, request):
+        self.request = request
+    def __iter__(self):
+        return self.messages.__iter__()
+    def __len__(self):
+        return len(self.messages)
+    def __nonzero__(self):
+        return bool(self.messages)
+    def __unicode__(self):
+        return unicode(self.messages)
+    def _get_messages(self):
+        if hasattr(self, '_messages'):
+            return self._messages
+        # First, retreive any messages for the user.
+        if hasattr(self.request, 'user') and \
+           hasattr(self.request.user, 'get_and_delete_messages'):
+            self._messages = self.request.user.get_and_delete_messages()
+        else:
+            self._messages = []
+        # Next, retrieve any messages for the session.
+        if hasattr(self.request, 'session'):
+            self._messages += self.request.session.get_and_delete_messages()
+        return self._messages
+    messages = property(_get_messages)
+
+def messages(request):
+    """
+    Return messages for the session and the current user.
+
+    The messages are lazy loaded, so no messages are retreived and deleted
+    unless requested from the template.
+    
+    Both contrib.session and contrib.auth are optional. If neither is provided,
+    no 'messages' variable will be added to the context.
+    """
+    if hasattr(request, 'session') or hasattr(request, 'user'):
+        return {'messages': LazyMessages(request)}
+    return {}
+
 def debug(request):
     "Returns context variables helpful for debugging."
     context_extras = {}
Index: django/contrib/sessions/tests.py
===================================================================
--- django/contrib/sessions/tests.py	(revision 6894)
+++ django/contrib/sessions/tests.py	(working copy)
@@ -16,6 +16,19 @@
 'dog'
 >>> db_session.pop('some key', 'does not exist')
 'does not exist'
+>>> db_session.get_messages()
+[]
+>>> db_session.create_message('first post')
+>>> db_session.get_messages()
+['first post']
+>>> db_session.get_and_delete_messages()
+['first post']
+>>> db_session.get_and_delete_messages()
+[]
+>>> db_session.create_message('hello')
+>>> db_session.create_message('world')
+>>> db_session.get_and_delete_messages()
+['hello', 'world']
 >>> db_session.save()
 >>> db_session.exists(db_session.session_key)
 True
@@ -33,6 +46,19 @@
 'dog'
 >>> file_session.pop('some key', 'does not exist')
 'does not exist'
+>>> file_session.get_messages()
+[]
+>>> file_session.create_message('first post')
+>>> file_session.get_messages()
+['first post']
+>>> file_session.get_and_delete_messages()
+['first post']
+>>> file_session.get_and_delete_messages()
+[]
+>>> file_session.create_message('hello')
+>>> file_session.create_message('world')
+>>> file_session.get_and_delete_messages()
+['hello', 'world']
 >>> file_session.save()
 >>> file_session.exists(file_session.session_key)
 True
@@ -57,6 +83,19 @@
 'dog'
 >>> cache_session.pop('some key', 'does not exist')
 'does not exist'
+>>> cache_session.get_messages()
+[]
+>>> cache_session.create_message('first post')
+>>> cache_session.get_messages()
+['first post']
+>>> cache_session.get_and_delete_messages()
+['first post']
+>>> cache_session.get_and_delete_messages()
+[]
+>>> cache_session.create_message('hello')
+>>> cache_session.create_message('world')
+>>> cache_session.get_and_delete_messages()
+['hello', 'world']
 >>> cache_session.save()
 >>> cache_session.delete(cache_session.session_key)
 >>> cache_session.exists(cache_session.session_key)
Index: django/contrib/sessions/backends/base.py
===================================================================
--- django/contrib/sessions/backends/base.py	(revision 6894)
+++ django/contrib/sessions/backends/base.py	(working copy)
@@ -18,6 +18,7 @@
     """
     TEST_COOKIE_NAME = 'testcookie'
     TEST_COOKIE_VALUE = 'worked'
+    MESSAGES_NAME = '_messages'
 
     def __init__(self, session_key=None):
         self._session_key = session_key
@@ -68,6 +69,20 @@
     def delete_test_cookie(self):
         del self[self.TEST_COOKIE_NAME]
 
+    def get_messages(self):
+            return self.get(self.MESSAGES_NAME, [])
+
+    def get_and_delete_messages(self):
+            return self.pop(self.MESSAGES_NAME, [])
+
+    def create_message(self, message):
+        messages = self.get(self.MESSAGES_NAME)
+        if messages is None:
+            messages = []
+            self[self.MESSAGES_NAME] = messages
+        messages.append(message)
+        self.modified = True
+
     def encode(self, session_dict):
         "Returns the given session dictionary pickled and encoded as a string."
         pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
Index: tests/regressiontests/messages/__init__.py
===================================================================
Index: tests/regressiontests/messages/tests.py
===================================================================
--- tests/regressiontests/messages/tests.py	(revision 0)
+++ tests/regressiontests/messages/tests.py	(revision 0)
@@ -0,0 +1,74 @@
+"""
+>>> from django.core import context_processors
+>>> from django.http import HttpRequest
+
+Set up request with a fake user and session (just enough to test getting and
+deleting messages).
+>>> request = HttpRequest()
+>>> class FakeMessageObj:
+...     def __init__(self, object, messages):
+...         self.messages = messages
+...         self.object = object
+...     def get_and_delete_messages(self):
+...         print 'Getting and deleting any %s messages...' % self.object
+...         m = self.messages
+...         self.messages = []
+...         return m
+>>> request.user = FakeMessageObj('user', ['User message'])
+>>> request.session = FakeMessageObj('session', ['Message 1', 'Second message'])
+
+Run the messages context processor, and pull out the messages context variable.
+>>> context = context_processors.messages(request)
+>>> messages = context['messages']
+
+The messages context variable is a LazyMessages class. The messages haven't
+actually been retreived (and deleted) yet.
+>>> messages.__class__
+<class 'django.core.context_processors.LazyMessages'>
+
+When any of the following methods are called, the messages are retreived from
+the session (and user if contrib.auth is installed) from the LazyMessages
+object to be retreived: __iter__, __len__, __nonzero__, __unicode__
+>>> len(messages)
+Getting and deleting any user messages...
+Getting and deleting any session messages...
+3
+
+When messages are retreived, messages are deleted from the session (and user if
+contrib.auth is installed).
+>>> request.user.messages
+[]
+>>> request.session.messages
+[]
+
+The messages are still available to the LazyMessages instance because it caches
+them.
+>>> for message in messages:
+...     print message
+User message
+Message 1
+Second message
+
+Both contrib.sessions and contrib.auth are optional. If neither are provided,
+no 'messages' variable will be added to the context.
+>>> del request.user
+>>> request.session = FakeMessageObj('session', [])
+>>> context = context_processors.messages(request)
+>>> messages = context['messages']
+>>> if messages:
+...     print 'messages found!'
+Getting and deleting any session messages...
+
+>>> del request.session
+>>> request.user = FakeMessageObj('user', [])
+>>> context = context_processors.messages(request)
+>>> messages = context['messages']
+>>> if messages:
+...     print 'messages found!'
+Getting and deleting any user messages...
+
+>>> del request.user
+>>> context = context_processors.messages(request)
+>>> context
+{}
+"""
\ No newline at end of file
Index: tests/regressiontests/messages/models.py
===================================================================
Index: tests/regressiontests/middleware/models.py
===================================================================
Index: docs/sessions.txt
===================================================================
--- docs/sessions.txt	(revision 6894)
+++ docs/sessions.txt	(working copy)
@@ -193,6 +193,39 @@
         request.session.set_test_cookie()
         return render_to_response('foo/login_form.html')
 
+Messages
+========
+
+**New in Django development version**
+
+The session message system provides a simple way to queue messages for all
+(anonymous or authenticated) site visitors. To associate messages with users in
+the user database, use the `authentication message framework`_.
+
+.. _authentication message framework: ../authentication/#messages
+
+Messages are associated with a session, therefore a message only lasts as long
+as a session is valid (see `browser-length sessions vs. persistent sessions`_).
+
+The message system relies on the session middleware and is accessed via
+``request.session``. The API is simple:
+
+    * To create a new message, use
+      ``request.session.create_message(message='message text').``
+
+    * To retreive the messages, use ``request.session.get_messages()``,
+      which returns a list of any messages (strings) in the session's queue.
+
+    * To retrieve and delete messages, use
+      ``request.session.get_and_delete_messages()``, which returns the list of
+      any messages in the session's queue and then deletes the messages from the
+      queue.
+
+The `django.core.context_processors.messages`_ context processor makes both
+session messages and user messages available to templates.
+
+.. _django.core.context_processors.messages: ../templates_python/#django-core-context_processors-messages
+
 Using sessions out of views
 ===========================
 
Index: docs/authentication.txt
===================================================================
--- docs/authentication.txt	(revision 6894)
+++ docs/authentication.txt	(working copy)
@@ -956,8 +956,11 @@
 Messages
 ========
 
-The message system is a lightweight way to queue messages for given users.
+The user message system is a lightweight way to queue messages for given users.
+To send messages to anonymous users, use `session messages`_.
 
+.. _session framework: ../sessions/#messages
+
 A message is associated with a ``User``. There's no concept of expiration or
 timestamps.
 
@@ -983,24 +986,20 @@
             context_instance=RequestContext(request))
 
 When you use ``RequestContext``, the currently logged-in user and his/her
-messages are made available in the `template context`_ as the template variable
-``{{ messages }}``. Here's an example of template code that displays messages::
+messages are made available in the `template context`_ as the ``{{ messages }}``
+template variable.
 
-    {% if messages %}
-    <ul>
-        {% for message in messages %}
-        <li>{{ message }}</li>
-        {% endfor %}
-    </ul>
-    {% endif %}
+**New in Django development version**
 
-Note that ``RequestContext`` calls ``get_and_delete_messages`` behind the
-scenes, so any messages will be deleted even if you don't display them.
+The ``{{ messages }}`` template variable will also contain session messages.
+For more information, see `django.core.context_processors.messages`_.
 
-Finally, note that this messages framework only works with users in the user
-database. To send messages to anonymous users, use the `session framework`_.
+.. _django.core.context_processors.messages: ../templates_python/#django-core-context_processors-messages
 
-.. _session framework: ../sessions/
+Also note that previously, ``RequestContext`` directly called
+``get_and_delete_messages`` behind the scenes, so any messages were deleted even
+if not displayed. Messages are now only deleted if the ``{{ messages }}``
+variable is accessed in a template.
 
 Other authentication sources
 ============================
Index: docs/templates_python.txt
===================================================================
--- docs/templates_python.txt	(revision 6894)
+++ docs/templates_python.txt	(working copy)
@@ -295,7 +295,8 @@
     ("django.core.context_processors.auth",
     "django.core.context_processors.debug",
     "django.core.context_processors.i18n",
-    "django.core.context_processors.media")
+    "django.core.context_processors.media",
+    "django.core.context_processors.messages")
 
 Each processor is applied in order. That means, if one processor adds a
 variable to the context and a second processor adds a variable with the same
@@ -345,11 +346,6 @@
       logged-in user (or an ``AnonymousUser`` instance, if the client isn't
       logged in). See the `user authentication docs`_.
 
-    * ``messages`` -- A list of messages (as strings) for the currently
-      logged-in user. Behind the scenes, this calls
-      ``request.user.get_and_delete_messages()`` for every request. That method
-      collects the user's messages and deletes them from the database.
-
       Note that messages are set with ``user.message_set.create``. See the
       `message docs`_ for more.
 
@@ -358,10 +354,13 @@
       permissions that the currently logged-in user has. See the `permissions
       docs`_.
 
-.. _user authentication docs: ../authentication/#users
-.. _message docs: ../authentication/#messages
-.. _permissions docs: ../authentication/#permissions
+**New in Django development version**
 
+Previously, a ``messages`` variable was also added to ``RequestContext``
+containing a list of messages for the currently logged-in user. This
+functionality has been moved to the `django.core.context_processors.messages`_
+context processor.
+
 django.core.context_processors.debug
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -409,6 +408,31 @@
 `HttpRequest object`_. Note that this processor is not enabled by default;
 you'll have to activate it.
 
+django.core.context_processors.messages
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
+``RequestContext`` will contain a variable ``messages``, which is a list of
+messages (as strings) containing any messages for the current session (see
+`session messages`_) or the currently logged-in user (see `auth messages`_).
+
+The messages are not retrieved and cleared (using ``get_and_delete_messages``)
+until the ``messages`` variable is accessed in a template.
+
+Here's an example of template code that displays messages made available by this
+context processor::
+
+	{% if messages %}
+	<ul>
+	    {% for message in messages %}
+	    <li>{{ message }}</li>
+	    {% endfor %}
+	</ul>
+	{% endif %}
+
+.. _session messages: ../sessions/#messages
+.. _auth messages: ../authentication/#messages
+
 Writing your own context processors
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
