1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 | # DEPRECATED: Django has cookie based messages since version 1.2
#
# -*- coding: iso-8859-1 -*-
# $Id: sessionutils.py 322 2009-04-22 10:53:04Z tguettler $
# $HeadURL: svn+ssh://svnserver/svn/djangotools/trunk/utils/sessionutils.py $
u'''
http://www.djangosnippets.org/snippets/1459/
Modify the Session class of django. Create some extra methods.
This way of hacking django is easier than running a modified version.
MessageCookieMiddleware Usage:
def view(request):
if request.method=='POST':
....
request.session.create_message(u'Your changes have been saved.')
return django.http.ResponseRedirect(...)
In the code or template where you create your HTML head, you need to insert:
request.session.get_and_delete_messages()
'''
# Python
import os
import sys
import random
from hashlib import sha1
import pickle
# Django
from django.utils.html import mark_safe
from django.utils.html import conditional_escape as escape
from django.utils.encoding import StrAndUnicode
# Project
from django.conf import settings
KNOWN_LOGLEVELS=['info', 'error']
COOKIE_NAME='%s_messages' % (settings.SESSION_COOKIE_NAME)
class MessageCookieMiddleware(object):
def process_request(self, request):
session=getattr(request, 'session', None)
if session is None:
return
cookie=request.COOKIES.get(COOKIE_NAME)
if cookie:
session._messages=decode(cookie)
else:
session._messages=Messages()
session._messages_modified=False
def process_response(self, request, response):
session=getattr(request, 'session', None)
if session is None:
return response
messages=getattr(session, '_messages', None)
if messages is None:
return response
if not session._messages_modified:
return response
if not messages:
response.delete_cookie(COOKIE_NAME)
else:
response.set_cookie(COOKIE_NAME, encode(messages))
return response
def get_messages(self):
u'Normaly not needed. Use get_and_delete_messages()'
messages=getattr(self, '_messages', None)
if messages is None:
raise AttributeError('session has no attribute _messages. MessageCookieMiddleware in settings.MIDDLEWARE_CLASSES?')
return messages
def get_and_delete_messages(self):
messages=self.get_messages()
if messages:
messages=Messages(messages) # copy
self._messages=Messages()
self._messages_modified=True
return messages
class Messages(list, StrAndUnicode):
def __unicode__(self):
if not self:
return u''
return mark_safe(u'<ul class="messages">%s</ul>' % u''.join([unicode(m) for m in self]))
def __repr__(self):
return '<%s object %s messages: %s>' % (self.__class__.__name__, len(self),
u'; '.join([m.message for m in self]))
class Message(object):
def __init__(self, message, loglevel='info'):
self.message=message
assert loglevel in KNOWN_LOGLEVELS, loglevel
self.loglevel=loglevel
def __unicode__(self):
return mark_safe(u'<li class="message-%s">%s</li>' % (self.loglevel, escape(self.message)))
def create_message(self, message, loglevel='info'):
messages=self.get_messages()
messages.append(Message(message, loglevel))
self._messages_modified = True
# encode and decode based on from http://www.djangosnippets.org/snippets/1064/
def encode(value):
assert value
value = pickle.dumps(value)
hash = sha1(value + settings.SECRET_KEY)
return '%s$%s' % (hash.hexdigest(), value)
def decode(cookie):
u'''
unpickling of untrusted data is dangerous. Uses settings.SECRET_KEY to
create a sha1 signature.
'''
assert cookie
s = cookie.split('$', 1)
hash, value = s
should = sha1(value + settings.SECRET_KEY).hexdigest()
if should != hash:
raise Exception('verify of sha1 signed cookie failed. should!=hash (%s!=%s)' % (
should, hash))
return pickle.loads(value)
def get_dir(self):
session_dir=os.path.join(settings.MEDIA_ROOT, 'sessions', self.session_key)
if not os.path.exists(session_dir):
os.mkdir(session_dir)
return session_dir
def get_tempfile(self, extension='', basename=None):
u'''
extensions: txt, png, pdf, ...
'''
if not basename:
if extension:
dot='.'
else:
dot=''
basename='%s%s%s' % (random.randint(0, sys.maxint), dot, extension)
path=os.path.join(self.get_dir(), basename)
url='%ssessions/%s/%s' % (settings.MEDIA_URL, self.session_key, basename)
return (path, url)
# Start Hacking Django
from django.contrib.sessions.backends.base import SessionBase
SessionBase.get_messages=get_messages
SessionBase.get_and_delete_messages=get_and_delete_messages
SessionBase.create_message=create_message
SessionBase.get_dir=get_dir
SessionBase.get_tempfile=get_tempfile
# End Hacking Django
|
Comments
SmilyChris created an application which can be used for cookie based messages:
django-notify
#
With Django 1.2 this snippet is deprecated, since django has a message framework with cookie support now.
#