Django

Code

Ticket #4604: messages.2.diff

File messages.2.diff, 15.3 kB (added by SmileyChris, 2 years ago)

More tests

  • django/conf/global_settings.py

    old new  
    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

    old new  
    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        if hasattr(self.request, 'session'): 
     53            self._messages += self.request.session.get_and_delete_messages() 
     54        return self._messages 
     55    messages = property(_get_messages) 
     56 
     57def messages(request): 
     58    """ 
     59    Return messages for the session and the current user. 
     60 
     61    The messages are lazy loaded, so no messages are retreived and deleted 
     62    unless requested from the template. 
     63     
     64    Both contrib.session and contrib.auth are optional. If neither is provided, 
     65    no 'messages' variable will be added to the context. 
     66    """ 
     67    if hasattr(request, 'session') or hasattr(request, 'user'): 
     68        return {'messages': LazyMessages(request)} 
     69    return {} 
     70 
    3171def debug(request): 
    3272    "Returns context variables helpful for debugging." 
    3373    context_extras = {} 
  • django/contrib/sessions/tests.py

    old new  
    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

    old new  
    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) 
  • tests/regressiontests/messages/tests.py

    old new  
     1""" 
     2>>> from django.core import context_processors 
     3>>> from django.http import HttpRequest 
     4 
     5Set up request with a fake user and session (just enough to test getting and 
     6deleting messages). 
     7>>> request = HttpRequest() 
     8>>> class FakeMessageObj: 
     9...     def __init__(self, object, messages): 
     10...         self.messages = messages 
     11...         self.object = object 
     12...     def get_and_delete_messages(self): 
     13...         print 'Getting and deleting any %s messages...' % self.object 
     14...         m = self.messages 
     15...         self.messages = [] 
     16...         return m 
     17>>> request.user = FakeMessageObj('user', ['User message']) 
     18>>> request.session = FakeMessageObj('session', ['Message 1', 'Second message']) 
     19 
     20Run the messages context processor, and pull out the messages context variable. 
     21>>> context = context_processors.messages(request) 
     22>>> messages = context['messages'] 
     23 
     24The messages context variable is a LazyMessages class. The messages haven't 
     25actually been retreived (and deleted) yet. 
     26>>> messages.__class__ 
     27<class 'django.core.context_processors.LazyMessages'> 
     28 
     29When any of the following methods are called, the messages are retreived from 
     30the session (and user if contrib.auth is installed) from the LazyMessages 
     31object to be retreived: __iter__, __len__, __nonzero__, __unicode__ 
     32>>> len(messages) 
     33Getting and deleting any user messages... 
     34Getting and deleting any session messages... 
     353 
     36 
     37When messages are retreived, messages are deleted from the session (and user if 
     38contrib.auth is installed). 
     39>>> request.user.messages 
     40[] 
     41>>> request.session.messages 
     42[] 
     43 
     44The messages are still available to the LazyMessages instance because it caches 
     45them. 
     46>>> for message in messages: 
     47...     print message 
     48User message 
     49Message 1 
     50Second message 
     51 
     52Both contrib.sessions and contrib.auth are optional. If neither are provided, 
     53no 'messages' variable will be added to the context. 
     54>>> del request.user 
     55>>> request.session = FakeMessageObj('session', []) 
     56>>> context = context_processors.messages(request) 
     57>>> messages = context['messages'] 
     58>>> if messages: 
     59...     print 'messages found!' 
     60Getting and deleting any session messages... 
     61 
     62>>> del request.session 
     63>>> request.user = FakeMessageObj('user', []) 
     64>>> context = context_processors.messages(request) 
     65>>> messages = context['messages'] 
     66>>> if messages: 
     67...     print 'messages found!' 
     68Getting and deleting any user messages... 
     69 
     70>>> del request.user 
     71>>> context = context_processors.messages(request) 
     72>>> context 
     73{} 
     74""" 
  • docs/sessions.txt

    old new  
    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

    old new  
    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

    old new  
    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