Ticket #4604: t4604-r9698.diff
File t4604-r9698.diff, 14.7 KB (added by , 16 years ago) |
---|
-
django/contrib/sessions/backends/base.py
diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
a b 33 33 """ 34 34 TEST_COOKIE_NAME = 'testcookie' 35 35 TEST_COOKIE_VALUE = 'worked' 36 MESSAGES_NAME = '_messages' 36 37 37 38 def __init__(self, session_key=None): 38 39 self._session_key = session_key … … 82 83 83 84 def delete_test_cookie(self): 84 85 del self[self.TEST_COOKIE_NAME] 86 87 def get_messages(self): 88 return self.get(self.MESSAGES_NAME, []) 89 90 def get_and_delete_messages(self): 91 return self.pop(self.MESSAGES_NAME, []) 92 93 def create_message(self, message): 94 messages = self.get(self.MESSAGES_NAME) 95 if messages is None: 96 messages = [] 97 self[self.MESSAGES_NAME] = messages 98 messages.append(message) 99 self.modified = True 85 100 86 101 def encode(self, session_dict): 87 102 "Returns the given session dictionary pickled and encoded as a string." -
django/contrib/sessions/tests.py
diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py
a b 18 18 'dog' 19 19 >>> db_session.pop('some key', 'does not exist') 20 20 'does not exist' 21 >>> db_session.get_messages() 22 [] 23 >>> db_session.create_message('first post') 24 >>> db_session.get_messages() 25 ['first post'] 26 >>> db_session.get_and_delete_messages() 27 ['first post'] 28 >>> db_session.get_and_delete_messages() 29 [] 30 >>> db_session.create_message('hello') 31 >>> db_session.create_message('world') 32 >>> db_session.get_and_delete_messages() 33 ['hello', 'world'] 21 34 >>> db_session.save() 22 35 >>> db_session.exists(db_session.session_key) 23 36 True … … 69 82 'dog' 70 83 >>> file_session.pop('some key', 'does not exist') 71 84 'does not exist' 85 >>> file_session.get_messages() 86 [] 87 >>> file_session.create_message('first post') 88 >>> file_session.get_messages() 89 ['first post'] 90 >>> file_session.get_and_delete_messages() 91 ['first post'] 92 >>> file_session.get_and_delete_messages() 93 [] 94 >>> file_session.create_message('hello') 95 >>> file_session.create_message('world') 96 >>> file_session.get_and_delete_messages() 97 ['hello', 'world'] 72 98 >>> file_session.save() 73 99 >>> file_session.exists(file_session.session_key) 74 100 True … … 131 157 'dog' 132 158 >>> cache_session.pop('some key', 'does not exist') 133 159 'does not exist' 160 >>> cache_session.get_messages() 161 [] 162 >>> cache_session.create_message('first post') 163 >>> cache_session.get_messages() 164 ['first post'] 165 >>> cache_session.get_and_delete_messages() 166 ['first post'] 167 >>> cache_session.get_and_delete_messages() 168 [] 169 >>> cache_session.create_message('hello') 170 >>> cache_session.create_message('world') 171 >>> cache_session.get_and_delete_messages() 172 ['hello', 'world'] 134 173 >>> cache_session.save() 135 174 >>> cache_session.delete(cache_session.session_key) 136 175 >>> cache_session.exists(cache_session.session_key) -
django/core/context_processors.py
diff --git a/django/core/context_processors.py b/django/core/context_processors.py
a b 8 8 """ 9 9 10 10 from django.conf import settings 11 from django.utils.encoding import StrAndUnicode 12 13 # LazyMessages is used by the `messages` and `auth` context processors. 14 15 class LazyMessages(StrAndUnicode): 16 """ 17 A lazy proxy for session and authentication messages. 18 """ 19 def __init__(self, request): 20 self.request = request 21 22 def __iter__(self): 23 return iter(self.messages) 24 25 def __len__(self): 26 return len(self.messages) 27 28 def __nonzero__(self): 29 return bool(self.messages) 30 31 def __unicode__(self): 32 return unicode(self.messages) 33 34 def __getitem__(self, *args, **kwargs): 35 return self.messages.__getitem__(*args, **kwargs) 36 37 def _get_messages(self): 38 if hasattr(self, '_messages'): 39 return self._messages 40 # First, retrieve any messages for the user. 41 if hasattr(self.request, 'user') and \ 42 hasattr(self.request.user, 'get_and_delete_messages'): 43 self._messages = self.request.user.get_and_delete_messages() 44 else: 45 self._messages = [] 46 # Next, retrieve any messages for the session. 47 if hasattr(self.request, 'session'): 48 self._messages += self.request.session.get_and_delete_messages() 49 return self._messages 50 messages = property(_get_messages) 11 51 12 52 def auth(request): 13 53 """ … … 22 62 else: 23 63 from django.contrib.auth.models import AnonymousUser 24 64 user = AnonymousUser() 25 return{65 context_extras = { 26 66 'user': user, 27 'messages': user.get_and_delete_messages(),28 67 'perms': PermWrapper(user), 29 68 } 69 # Add authentication (and session) LazyMessages to the context too. 70 context_extras.update(messages(request)) 71 return context_extras 72 73 def messages(request): 74 """ 75 Returns messages for the session and the current user. 76 77 Note that this processor is only useful to use explicity if you are not 78 using the (enabled by default) auth processor, as it also provides the 79 messages (by calling this method). 80 81 The messages are lazy loaded, so no messages are retrieved and deleted 82 unless requested from the template. 83 84 Both contrib.session and contrib.auth are optional. If neither is provided, 85 no 'messages' variable will be added to the context. 86 """ 87 if hasattr(request, 'session') or hasattr(request, 'user'): 88 return {'messages': LazyMessages(request)} 89 return {} 30 90 31 91 def debug(request): 32 92 "Returns context variables helpful for debugging." -
docs/ref/templates/api.txt
diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt
a b 352 352 logged in). 353 353 354 354 * ``messages`` -- A list of messages (as strings) for the currently 355 logged-in user. Behind the scenes, this calls 356 ``request.user.get_and_delete_messages()`` for every request. That method 357 collects the user's messages and deletes them from the database. 355 logged-in user. 358 356 359 Note that messages are set with ``user.message_set.create``. 357 .. versionadded:: 1.1 358 359 This ``messages`` list now also contains session messages. 360 361 The messages are not retrieved and cleared (using 362 ``get_and_delete_messages``) until the ``messages`` variable is accessed 363 in a template whereas previously, this context processor called 364 ``request.user.get_and_delete_messages()`` behind the scenes for every 365 request. 366 367 See the :ref:`authentication messages docs<auth-messages>` or 368 :ref:`session messages docs<sess-messages>` for information on creating 369 messages. 360 370 361 371 * ``perms`` -- An instance of 362 372 ``django.core.context_processors.PermWrapper``, representing the … … 404 414 ``RequestContext`` will contain a variable ``request``, which is the current 405 415 :class:`~django.http.HttpRequest`. Note that this processor is not enabled by default; 406 416 you'll have to activate it. 417 418 .. _messages-context-processor: 419 420 django.core.context_processors.messages 421 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 422 423 If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every 424 ``RequestContext`` will contain a variable ``messages``, which is a list of 425 messages (as strings) for the current session and the currently logged-in user. 426 See the :ref:`session messages docs<sess-messages>` or the 427 :ref:`authentication messages docs<auth-messages>` for more information on 428 using messages. 429 430 Note that this processor is only useful if you are not using the (enabled by 431 default) ``auth`` processor, as it also provides the ``messages`` variable. 432 433 The messages are not retrieved and cleared (using ``get_and_delete_messages``) 434 until the ``messages`` variable is accessed in a template. 435 436 Here's an example of template code that displays messages made available by this 437 context processor: 438 439 .. code-block:: html+django 440 441 {% if messages %} 442 <ul> 443 {% for message in messages %} 444 <li>{{ message }}</li> 445 {% endfor %} 446 </ul> 447 {% endif %} 407 448 408 449 Writing your own context processors 409 450 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -
docs/topics/auth.txt
diff --git a/docs/topics/auth.txt b/docs/topics/auth.txt
a b 1151 1151 access to a members-only portion of your site, or send them members-only e-mail 1152 1152 messages. 1153 1153 1154 .. _auth-messages: 1155 1154 1156 Messages 1155 1157 ======== 1156 1158 1157 The message system is a lightweight way to queue messages for given users. 1159 The user message system is a lightweight way to queue messages for given users. 1160 To send messages to anonymous users, use :ref:`session messages<sess-messages>`. 1158 1161 1159 1162 A message is associated with a :class:`~django.contrib.auth.models.User`. 1160 1163 There's no concept of expiration or timestamps. … … 1186 1189 1187 1190 When you use :class:`~django.template.context.RequestContext`, the currently 1188 1191 logged-in user and his/her messages are made available in the 1189 :ref:`template context <ref-templates-api>` as the template variable1190 ``{{ messages }}``. Here's an example of template code that displays messages:: 1192 :ref:`template context <ref-templates-api>` as the ``{{ messages }}`` template 1193 variable. 1191 1194 1192 {% if messages %} 1193 <ul> 1194 {% for message in messages %} 1195 <li>{{ message }}</li> 1196 {% endfor %} 1197 </ul> 1198 {% endif %} 1195 .. versionadded:: 1.1 1199 1196 1200 Note that :class:`~django.template.context.RequestContext` calls 1201 :meth:`~django.contrib.auth.models.User.get_and_delete_messages` behind the 1202 scenes, so any messages will be deleted even if you don't display them. 1197 The ``{{ messages }}`` template variable will also contain session messages. 1198 For more information, see :ref:`messages-context-processor` 1203 1199 1204 Finally, note that this messages framework only works with users in the user 1205 database. To send messages to anonymous users, use the 1206 :ref:`session framework <topics-http-sessions>`. 1200 Also note that previously, ``RequestContext`` directly called 1201 ``get_and_delete_messages`` behind the scenes, so any messages were deleted even 1202 if not displayed. Messages are now only deleted if the ``{{ messages }}`` 1203 variable is accessed in a template. 1207 1204 1208 1205 .. _authentication-backends: 1209 1206 -
docs/topics/http/sessions.txt
diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
a b 266 266 request.session.set_test_cookie() 267 267 return render_to_response('foo/login_form.html') 268 268 269 .. _sess-messages: 270 271 Messages 272 ======== 273 274 .. versionadded:: 1.1 275 276 The session message system provides a simple way to queue messages for all 277 (anonymous or authenticated) site visitors. To associate messages with users in 278 the user database, use the :ref:`authentication message framework<auth-messages>`. 279 280 Messages are associated with a session, therefore a message only lasts as long 281 as a session is valid (see `browser-length sessions vs. persistent sessions`_). 282 283 The message system relies on the session middleware and is accessed via 284 ``request.session``. The API is simple: 285 286 * To create a new message, use 287 ``request.session.create_message(message='message text').`` 288 289 * To retrieve the messages, use ``request.session.get_messages()``, 290 which returns a list of any messages (strings) in the session's queue. 291 292 * To retrieve and delete messages, use 293 ``request.session.get_and_delete_messages()``, which returns the list of 294 any messages in the session's queue and then deletes the messages from the 295 queue. 296 297 The :ref:`messages-context-processor` context processor makes both session 298 messages and user messages available to templates. 299 269 300 Using sessions out of views 270 301 =========================== 271 302 -
new file tests/regressiontests/messages/__init__.py
diff --git a/tests/regressiontests/messages/__init__.py b/tests/regressiontests/messages/__init__.py new file mode 100644
- + 1 -
new file tests/regressiontests/messages/tests.py
diff --git a/tests/regressiontests/messages/models.py b/tests/regressiontests/messages/models.py new file mode 100644 diff --git a/tests/regressiontests/messages/tests.py b/tests/regressiontests/messages/tests.py new file mode 100644
- + 1 """ 2 >>> from django.core import context_processors 3 >>> from django.http import HttpRequest 4 5 Set up request with a fake user and session (just enough to test getting and 6 deleting 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 20 Run the messages context processor, and pull out the messages context variable. 21 >>> context = context_processors.messages(request) 22 >>> messages = context['messages'] 23 24 The messages context variable is a LazyMessages class. The messages haven't 25 actually been retreived (and deleted) yet. 26 >>> messages.__class__ 27 <class 'django.core.context_processors.LazyMessages'> 28 29 When any of the following methods are called, the messages are retreived from 30 the session (and user if contrib.auth is installed) from the LazyMessages 31 object to be retreived: __iter__, __len__, __nonzero__, __unicode__, 32 __getitem__ 33 >>> len(messages) 34 Getting and deleting any user messages... 35 Getting and deleting any session messages... 36 3 37 38 When messages are retreived, messages are deleted from the session (and user if 39 contrib.auth is installed). 40 >>> request.user.messages 41 [] 42 >>> request.session.messages 43 [] 44 45 The messages are still available to the LazyMessages instance because it caches 46 them. 47 >>> for message in messages: 48 ... print message 49 User message 50 Message 1 51 Second message 52 >>> messages[-1] 53 'Second message' 54 55 Both contrib.sessions and contrib.auth are optional. If neither are provided, 56 no 'messages' variable will be added to the context. 57 >>> del request.user 58 >>> request.session = FakeMessageObj('session', []) 59 >>> context = context_processors.messages(request) 60 >>> messages = context['messages'] 61 >>> if messages: 62 ... print 'messages found!' 63 Getting and deleting any session messages... 64 65 >>> del request.session 66 >>> request.user = FakeMessageObj('user', []) 67 >>> context = context_processors.messages(request) 68 >>> messages = context['messages'] 69 >>> if messages: 70 ... print 'messages found!' 71 Getting and deleting any user messages... 72 73 >>> del request.user 74 >>> context = context_processors.messages(request) 75 >>> context 76 {} 77 """