Code

Ticket #4604: messages-r8347.diff

File messages-r8347.diff, 12.7 KB (added by john, 6 years ago)

Updated messages.7.diff to avoid rejects with django.core.context_processors.py

Line 
1Index: django/core/context_processors.py
2===================================================================
3--- django/core/context_processors.py   (revision 8347)
4+++ django/core/context_processors.py   (working copy)
5@@ -8,7 +8,46 @@
6 """
7 
8 from django.conf import settings
9+from django.utils.encoding import StrAndUnicode
10 
11+# LazyMessages is used by the `messages` and `auth` context processors.
12+class LazyMessages(StrAndUnicode):
13+    """
14+    A lazy proxy for session and authentication messages.
15+    """
16+    def __init__(self, request):
17+        self.request = request
18+   
19+    def __iter__(self):
20+        return iter(self.messages)
21+   
22+    def __len__(self):
23+        return len(self.messages)
24+   
25+    def __nonzero__(self):
26+        return bool(self.messages)
27+   
28+    def __unicode__(self):
29+        return unicode(self.messages)
30+   
31+    def __getitem__(self, *args, **kwargs):
32+        return self.messages.__getitem__(*args, **kwargs)
33+   
34+    def _get_messages(self):
35+        if hasattr(self, '_messages'):
36+            return self._messages
37+        # First, retreive any messages for the user.
38+        if hasattr(self.request, 'user') and \
39+           hasattr(self.request.user, 'get_and_delete_messages'):
40+            self._messages = self.request.user.get_and_delete_messages()
41+        else:
42+            self._messages = []
43+        # Next, retrieve any messages for the session.
44+        if hasattr(self.request, 'session'):
45+            self._messages += self.request.session.get_and_delete_messages()
46+        return self._messages
47+    messages = property(_get_messages)
48+
49 def auth(request):
50     """
51     Returns context variables required by apps that use Django's authentication
52@@ -22,12 +61,32 @@
53     else:
54         from django.contrib.auth.models import AnonymousUser
55         user = AnonymousUser()
56-    return {
57+    context_extras = {
58         'user': user,
59-        'messages': user.get_and_delete_messages(),
60         'perms': PermWrapper(user),
61     }
62+    # Add authentication (and session) LazyMessages to the context too.
63+    context_extras.update(messages(request))
64+    return context_extras
65 
66+def messages(request):
67+    """
68+    Returns messages for the session and the current user.
69+
70+    Note that this processor is only useful to use explicity if you are not
71+    using the (enabled by default) auth processor, as it also provides the
72+    messages (by calling this method).
73+
74+    The messages are lazy loaded, so no messages are retreived and deleted
75+    unless requested from the template.
76+
77+    Both contrib.session and contrib.auth are optional. If neither is provided,
78+    no 'messages' variable will be added to the context.
79+    """
80+    if hasattr(request, 'session') or hasattr(request, 'user'):
81+        return {'messages': LazyMessages(request)}
82+    return {}
83+
84 def debug(request):
85     "Returns context variables helpful for debugging."
86     context_extras = {}
87@@ -83,3 +142,4 @@
88     def __iter__(self):
89         # I am large, I contain multitudes.
90         raise TypeError("PermWrapper is not iterable.")
91+
92Index: django/contrib/sessions/tests.py
93===================================================================
94--- django/contrib/sessions/tests.py    (revision 8347)
95+++ django/contrib/sessions/tests.py    (working copy)
96@@ -16,6 +16,19 @@
97 'dog'
98 >>> db_session.pop('some key', 'does not exist')
99 'does not exist'
100+>>> db_session.get_messages()
101+[]
102+>>> db_session.create_message('first post')
103+>>> db_session.get_messages()
104+['first post']
105+>>> db_session.get_and_delete_messages()
106+['first post']
107+>>> db_session.get_and_delete_messages()
108+[]
109+>>> db_session.create_message('hello')
110+>>> db_session.create_message('world')
111+>>> db_session.get_and_delete_messages()
112+['hello', 'world']
113 >>> db_session.save()
114 >>> db_session.exists(db_session.session_key)
115 True
116@@ -46,6 +59,19 @@
117 'dog'
118 >>> file_session.pop('some key', 'does not exist')
119 'does not exist'
120+>>> file_session.get_messages()
121+[]
122+>>> file_session.create_message('first post')
123+>>> file_session.get_messages()
124+['first post']
125+>>> file_session.get_and_delete_messages()
126+['first post']
127+>>> file_session.get_and_delete_messages()
128+[]
129+>>> file_session.create_message('hello')
130+>>> file_session.create_message('world')
131+>>> file_session.get_and_delete_messages()
132+['hello', 'world']
133 >>> file_session.save()
134 >>> file_session.exists(file_session.session_key)
135 True
136@@ -83,6 +109,19 @@
137 'dog'
138 >>> cache_session.pop('some key', 'does not exist')
139 'does not exist'
140+>>> cache_session.get_messages()
141+[]
142+>>> cache_session.create_message('first post')
143+>>> cache_session.get_messages()
144+['first post']
145+>>> cache_session.get_and_delete_messages()
146+['first post']
147+>>> cache_session.get_and_delete_messages()
148+[]
149+>>> cache_session.create_message('hello')
150+>>> cache_session.create_message('world')
151+>>> cache_session.get_and_delete_messages()
152+['hello', 'world']
153 >>> cache_session.save()
154 >>> cache_session.delete(cache_session.session_key)
155 >>> cache_session.exists(cache_session.session_key)
156Index: django/contrib/sessions/backends/base.py
157===================================================================
158--- django/contrib/sessions/backends/base.py    (revision 8347)
159+++ django/contrib/sessions/backends/base.py    (working copy)
160@@ -33,6 +33,7 @@
161     """
162     TEST_COOKIE_NAME = 'testcookie'
163     TEST_COOKIE_VALUE = 'worked'
164+    MESSAGES_NAME = '_messages'
165 
166     def __init__(self, session_key=None):
167         self._session_key = session_key
168@@ -83,6 +84,20 @@
169     def delete_test_cookie(self):
170         del self[self.TEST_COOKIE_NAME]
171 
172+    def get_messages(self):
173+            return self.get(self.MESSAGES_NAME, [])
174+
175+    def get_and_delete_messages(self):
176+            return self.pop(self.MESSAGES_NAME, [])
177+
178+    def create_message(self, message):
179+        messages = self.get(self.MESSAGES_NAME)
180+        if messages is None:
181+            messages = []
182+            self[self.MESSAGES_NAME] = messages
183+        messages.append(message)
184+        self.modified = True
185+
186     def encode(self, session_dict):
187         "Returns the given session dictionary pickled and encoded as a string."
188         pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
189Index: docs/authentication.txt
190===================================================================
191--- docs/authentication.txt     (revision 8347)
192+++ docs/authentication.txt     (working copy)
193@@ -975,8 +975,11 @@
194 Messages
195 ========
196 
197-The message system is a lightweight way to queue messages for given users.
198+The user message system is a lightweight way to queue messages for given users.
199+To send messages to anonymous users, use `session messages`_.
200 
201+.. _session framework: ../sessions/#messages
202+
203 A message is associated with a ``User``. There's no concept of expiration or
204 timestamps.
205 
206@@ -1002,24 +1005,20 @@
207             context_instance=RequestContext(request))
208 
209 When you use ``RequestContext``, the currently logged-in user and his/her
210-messages are made available in the `template context`_ as the template variable
211-``{{ messages }}``. Here's an example of template code that displays messages::
212+messages are made available in the `template context`_ as the ``{{ messages }}``
213+template variable.
214 
215-    {% if messages %}
216-    <ul>
217-        {% for message in messages %}
218-        <li>{{ message }}</li>
219-        {% endfor %}
220-    </ul>
221-    {% endif %}
222+**New in Django development version**
223 
224-Note that ``RequestContext`` calls ``get_and_delete_messages`` behind the
225-scenes, so any messages will be deleted even if you don't display them.
226+The ``{{ messages }}`` template variable will also contain session messages.
227+For more information, see `django.core.context_processors.messages`_.
228 
229-Finally, note that this messages framework only works with users in the user
230-database. To send messages to anonymous users, use the `session framework`_.
231+.. _django.core.context_processors.messages: ../templates_python/#django-core-context_processors-messages
232 
233-.. _session framework: ../sessions/
234+Also note that previously, ``RequestContext`` directly called
235+``get_and_delete_messages`` behind the scenes, so any messages were deleted even
236+if not displayed. Messages are now only deleted if the ``{{ messages }}``
237+variable is accessed in a template.
238 
239 Other authentication sources
240 ============================
241Index: docs/sessions.txt
242===================================================================
243--- docs/sessions.txt   (revision 8347)
244+++ docs/sessions.txt   (working copy)
245@@ -262,6 +262,39 @@
246         request.session.set_test_cookie()
247         return render_to_response('foo/login_form.html')
248 
249+Messages
250+========
251+
252+**New in Django development version**
253+
254+The session message system provides a simple way to queue messages for all
255+(anonymous or authenticated) site visitors. To associate messages with users in
256+the user database, use the `authentication message framework`_.
257+
258+.. _authentication message framework: ../authentication/#messages
259+
260+Messages are associated with a session, therefore a message only lasts as long
261+as a session is valid (see `browser-length sessions vs. persistent sessions`_).
262+
263+The message system relies on the session middleware and is accessed via
264+``request.session``. The API is simple:
265+
266+    * To create a new message, use
267+      ``request.session.create_message(message='message text').``
268+
269+    * To retreive the messages, use ``request.session.get_messages()``,
270+      which returns a list of any messages (strings) in the session's queue.
271+
272+    * To retrieve and delete messages, use
273+      ``request.session.get_and_delete_messages()``, which returns the list of
274+      any messages in the session's queue and then deletes the messages from the
275+      queue.
276+
277+The `django.core.context_processors.messages`_ context processor makes both
278+session messages and user messages available to templates.
279+
280+.. _django.core.context_processors.messages: ../templates_python/#django-core-context_processors-messages
281+
282 Using sessions out of views
283 ===========================
284 
285Index: docs/templates_python.txt
286===================================================================
287--- docs/templates_python.txt   (revision 8347)
288+++ docs/templates_python.txt   (working copy)
289@@ -346,20 +346,29 @@
290       logged in). See the `user authentication docs`_.
291 
292     * ``messages`` -- A list of messages (as strings) for the currently
293-      logged-in user. Behind the scenes, this calls
294-      ``request.user.get_and_delete_messages()`` for every request. That method
295-      collects the user's messages and deletes them from the database.
296+      logged-in user.
297 
298-      Note that messages are set with ``user.message_set.create``. See the
299-      `message docs`_ for more.
300+      **New in Django development version**
301 
302+      This ``messages`` list now also contains session messages.
303+
304+      The messages are not retrieved and cleared (using
305+      ``get_and_delete_messages``) until the ``messages`` variable is accessed
306+      in a template whereas previously, this context processor called
307+      ``request.user.get_and_delete_messages()`` behind the scenes for every
308+      request.
309+
310+      See the `authentication message docs`_ or `session message docs`_ for
311+      information on creating messages.
312+
313     * ``perms`` -- An instance of
314       ``django.core.context_processors.PermWrapper``, representing the
315       permissions that the currently logged-in user has. See the `permissions
316       docs`_.
317 
318 .. _user authentication docs: ../authentication/#users
319-.. _message docs: ../authentication/#messages
320+.. _authentication message docs: ../authentication/#messages
321+.. _session message docs: ../sessions/#messages
322 .. _permissions docs: ../authentication/#permissions
323 
324 django.core.context_processors.debug
325@@ -411,6 +420,32 @@
326 `HttpRequest object`_. Note that this processor is not enabled by default;
327 you'll have to activate it.
328 
329+django.core.context_processors.messages
330+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
331+
332+If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
333+``RequestContext`` will contain a variable ``messages``, which is a list of
334+messages (as strings) for the current session and the currently logged-in user.
335+See the `session messages docs`_ or the `authentication messages docs`_ for more
336+information on using messages.
337+
338+Note that this processor is only useful if you are not using the (enabled by
339+default) ``auth`` processor, as it also provides the ``messages`` variable.
340+
341+The messages are not retrieved and cleared (using ``get_and_delete_messages``)
342+until the ``messages`` variable is accessed in a template.
343+
344+Here's an example of template code that displays messages made available by this
345+context processor::
346+
347+       {% if messages %}
348+       <ul>
349+           {% for message in messages %}
350+           <li>{{ message }}</li>
351+           {% endfor %}
352+       </ul>
353+       {% endif %}
354+
355 Writing your own context processors
356 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
357