Ticket #4604: messages.diff

File messages.diff, 11.9 KB (added by SmileyChris, 8 years ago)

Rewritten version, new core context processor which grabs messages from both user and session

  • django/conf/global_settings.py

     
    154154    'django.core.context_processors.debug',
    155155    'django.core.context_processors.i18n',
    156156    'django.core.context_processors.media',
     157    'django.core.context_processors.messages',
    157158#    'django.core.context_processors.request',
    158159)
    159160
  • django/core/context_processors.py

     
    88"""
    99
    1010from django.conf import settings
     11from django.utils.functional import memoize, lazy
    1112
    1213def auth(request):
    1314    """
     
    2425        user = AnonymousUser()
    2526    return {
    2627        'user': user,
    27         'messages': user.get_and_delete_messages(),
    2828        'perms': PermWrapper(user),
    2929    }
    3030
     31class LazyMessages(object):
     32    def __init__(self, request):
     33        self.request = request
     34    def __iter__(self):
     35        return self.messages.__iter__()
     36    def __len__(self):
     37        return len(self.messages)
     38    def __nonzero__(self):
     39        return bool(self.messages)
     40    def __unicode__(self):
     41        return unicode(self.messages)
     42    def _get_messages(self):
     43        if hasattr(self, '_messages'):
     44            return self._messages
     45        # First, retreive any messages for the user.
     46        if hasattr(self.request, 'user') and \
     47           hasattr(self.request.user, 'get_and_delete_messages'):
     48            self._messages = self.request.user.get_and_delete_messages()
     49        else:
     50            self._messages = []
     51        # Next, retrieve any messages for the session.
     52        self._messages += self.request.session.get_and_delete_messages()
     53        return self._messages
     54    messages = property(_get_messages)
     55
     56def messages(request):
     57    """
     58    Return messages for the session and the current user.
     59
     60    The messages are lazy loaded, so no messages are retreived and deleted
     61    unless requested from the template.
     62    """
     63    return {
     64        'messages': LazyMessages(request)
     65    }
     66
    3167def debug(request):
    3268    "Returns context variables helpful for debugging."
    3369    context_extras = {}
  • django/contrib/sessions/tests.py

     
    1616'dog'
    1717>>> db_session.pop('some key', 'does not exist')
    1818'does not exist'
     19>>> db_session.get_messages()
     20[]
     21>>> db_session.create_message('first post')
     22>>> db_session.get_messages()
     23['first post']
     24>>> db_session.get_and_delete_messages()
     25['first post']
     26>>> db_session.get_and_delete_messages()
     27[]
     28>>> db_session.create_message('hello')
     29>>> db_session.create_message('world')
     30>>> db_session.get_and_delete_messages()
     31['hello', 'world']
    1932>>> db_session.save()
    2033>>> db_session.exists(db_session.session_key)
    2134True
     
    3346'dog'
    3447>>> file_session.pop('some key', 'does not exist')
    3548'does not exist'
     49>>> file_session.get_messages()
     50[]
     51>>> file_session.create_message('first post')
     52>>> file_session.get_messages()
     53['first post']
     54>>> file_session.get_and_delete_messages()
     55['first post']
     56>>> file_session.get_and_delete_messages()
     57[]
     58>>> file_session.create_message('hello')
     59>>> file_session.create_message('world')
     60>>> file_session.get_and_delete_messages()
     61['hello', 'world']
    3662>>> file_session.save()
    3763>>> file_session.exists(file_session.session_key)
    3864True
     
    5783'dog'
    5884>>> cache_session.pop('some key', 'does not exist')
    5985'does not exist'
     86>>> cache_session.get_messages()
     87[]
     88>>> cache_session.create_message('first post')
     89>>> cache_session.get_messages()
     90['first post']
     91>>> cache_session.get_and_delete_messages()
     92['first post']
     93>>> cache_session.get_and_delete_messages()
     94[]
     95>>> cache_session.create_message('hello')
     96>>> cache_session.create_message('world')
     97>>> cache_session.get_and_delete_messages()
     98['hello', 'world']
    6099>>> cache_session.save()
    61100>>> cache_session.delete(cache_session.session_key)
    62101>>> cache_session.exists(cache_session.session_key)
  • django/contrib/sessions/backends/base.py

     
    1818    """
    1919    TEST_COOKIE_NAME = 'testcookie'
    2020    TEST_COOKIE_VALUE = 'worked'
     21    MESSAGES_NAME = '_messages'
    2122
    2223    def __init__(self, session_key=None):
    2324        self._session_key = session_key
     
    6869    def delete_test_cookie(self):
    6970        del self[self.TEST_COOKIE_NAME]
    7071
     72    def get_messages(self):
     73            return self.get(self.MESSAGES_NAME, [])
     74
     75    def get_and_delete_messages(self):
     76            return self.pop(self.MESSAGES_NAME, [])
     77
     78    def create_message(self, message):
     79        messages = self.get(self.MESSAGES_NAME)
     80        if messages is None:
     81            messages = []
     82            self[self.MESSAGES_NAME] = messages
     83        messages.append(message)
     84        self.modified = True
     85
    7186    def encode(self, session_dict):
    7287        "Returns the given session dictionary pickled and encoded as a string."
    7388        pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
  • docs/sessions.txt

     
    193193        request.session.set_test_cookie()
    194194        return render_to_response('foo/login_form.html')
    195195
     196Messages
     197========
     198
     199**New in Django development version**
     200
     201The session message system provides a simple way to queue messages for all
     202(anonymous or authenticated) site visitors. To associate messages with users in
     203the user database, use the `authentication message framework`_.
     204
     205.. _authentication message framework: ../authentication/#messages
     206
     207Messages are associated with a session, therefore a message only lasts as long
     208as a session is valid (see `browser-length sessions vs. persistent sessions`_).
     209
     210The message system relies on the session middleware and is accessed via
     211``request.session``. The API is simple:
     212
     213    * To create a new message, use
     214      ``request.session.create_message(message='message text').``
     215
     216    * To retreive the messages, use ``request.session.get_messages()``,
     217      which returns a list of any messages (strings) in the session's queue.
     218
     219    * To retrieve and delete messages, use
     220      ``request.session.get_and_delete_messages()``, which returns the list of
     221      any messages in the session's queue and then deletes the messages from the
     222      queue.
     223
     224The `django.core.context_processors.messages`_ context processor makes both
     225session messages and user messages available to templates.
     226
     227.. _django.core.context_processors.messages: ../templates_python/#django-core-context_processors-messages
     228
    196229Using sessions out of views
    197230===========================
    198231
  • docs/authentication.txt

     
    956956Messages
    957957========
    958958
    959 The message system is a lightweight way to queue messages for given users.
     959The user message system is a lightweight way to queue messages for given users.
     960To send messages to anonymous users, use `session messages`_.
    960961
     962.. _session framework: ../sessions/#messages
     963
    961964A message is associated with a ``User``. There's no concept of expiration or
    962965timestamps.
    963966
     
    983986            context_instance=RequestContext(request))
    984987
    985988When you use ``RequestContext``, the currently logged-in user and his/her
    986 messages are made available in the `template context`_ as the template variable
    987 ``{{ messages }}``. Here's an example of template code that displays messages::
     989messages are made available in the `template context`_ as the ``{{ messages }}``
     990template variable.
    988991
    989     {% if messages %}
    990     <ul>
    991         {% for message in messages %}
    992         <li>{{ message }}</li>
    993         {% endfor %}
    994     </ul>
    995     {% endif %}
     992**New in Django development version**
    996993
    997 Note that ``RequestContext`` calls ``get_and_delete_messages`` behind the
    998 scenes, so any messages will be deleted even if you don't display them.
     994The ``{{ messages }}`` template variable will also contain session messages.
     995For more information, see `django.core.context_processors.messages`_.
    999996
    1000 Finally, note that this messages framework only works with users in the user
    1001 database. To send messages to anonymous users, use the `session framework`_.
     997.. _django.core.context_processors.messages: ../templates_python/#django-core-context_processors-messages
    1002998
    1003 .. _session framework: ../sessions/
     999Also note that previously, ``RequestContext`` directly called
     1000``get_and_delete_messages`` behind the scenes, so any messages were deleted even
     1001if not displayed. Messages are now only deleted if the ``{{ messages }}``
     1002variable is accessed in a template.
    10041003
    10051004Other authentication sources
    10061005============================
  • docs/templates_python.txt

     
    295295    ("django.core.context_processors.auth",
    296296    "django.core.context_processors.debug",
    297297    "django.core.context_processors.i18n",
    298     "django.core.context_processors.media")
     298    "django.core.context_processors.media",
     299    "django.core.context_processors.messages")
    299300
    300301Each processor is applied in order. That means, if one processor adds a
    301302variable to the context and a second processor adds a variable with the same
     
    345346      logged-in user (or an ``AnonymousUser`` instance, if the client isn't
    346347      logged in). See the `user authentication docs`_.
    347348
    348     * ``messages`` -- A list of messages (as strings) for the currently
    349       logged-in user. Behind the scenes, this calls
    350       ``request.user.get_and_delete_messages()`` for every request. That method
    351       collects the user's messages and deletes them from the database.
    352 
    353349      Note that messages are set with ``user.message_set.create``. See the
    354350      `message docs`_ for more.
    355351
     
    358354      permissions that the currently logged-in user has. See the `permissions
    359355      docs`_.
    360356
    361 .. _user authentication docs: ../authentication/#users
    362 .. _message docs: ../authentication/#messages
    363 .. _permissions docs: ../authentication/#permissions
     357**New in Django development version**
    364358
     359Previously, a ``messages`` variable was also added to ``RequestContext``
     360containing a list of messages for the currently logged-in user. This
     361functionality has been moved to the `django.core.context_processors.messages`_
     362context processor.
     363
    365364django.core.context_processors.debug
    366365~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    367366
     
    409408`HttpRequest object`_. Note that this processor is not enabled by default;
    410409you'll have to activate it.
    411410
     411django.core.context_processors.messages
     412~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     413
     414If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
     415``RequestContext`` will contain a variable ``messages``, which is a list of
     416messages (as strings) containing any messages for the current session (see
     417`session messages`_) or the currently logged-in user (see `auth messages`_).
     418
     419The messages are not retrieved and cleared (using ``get_and_delete_messages``)
     420until the ``messages`` variable is accessed in a template.
     421
     422Here's an example of template code that displays messages made available by this
     423context processor::
     424
     425        {% if messages %}
     426        <ul>
     427            {% for message in messages %}
     428            <li>{{ message }}</li>
     429            {% endfor %}
     430        </ul>
     431        {% endif %}
     432
     433.. _session messages: ../sessions/#messages
     434.. _auth messages: ../authentication/#messages
     435
    412436Writing your own context processors
    413437~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    414438
Back to Top