simple middleware and context processor for session-based messaging with types Heavily inspired by patches on ticket 4604. Differs in that in this a notification has type.
Installation:
- add notifications.NotificationMiddleware to MIDDLEWARE_CLASSES
- and notifications.notifications to TEMPLATE_CONTEXT_PROCESSORS
That assumes notifications.py is on pythonpath. If notifications.py lives in your project dir, prefix those with '(projectname).'
Example use:
- request.notifications.create('Some bland information message.')
- request.notifications.create('Some more exciting error message.', 'error')
Example template code:
{% if notifications %}
<ul id="notifications">
{% for notification in notifications %}<li class="{{ notification.type }}">{{ notification.content }}</li>
{% endfor %}
</ul>
{% endif %}
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 | '''
simple middleware and context processor for session-based messaging with types
Heavily inspired by patches on ticket 4604. Differs in that in this a notification
has type.
Installation:
add notifications.NotificationMiddleware to MIDDLEWARE_CLASSES
and notifications.notifications to TEMPLATE_CONTEXT_PROCESSORS
That assumes notifications.py is on pythonpath. If notifications.py lives in
your project dir, prefix those with '(projectname).'
Example use:
request.notifications.create('Some bland information message.')
request.notifications.create('Some more exciting error message.', 'error')
Example template code:
{% if notifications %}
<ul id="notifications">
{% for notification in notifications %}<li class="{{ notification.type }}">{{ notification.content }}</li>
{% endfor %}
</ul>
{% endif %}
Example styling:
points to names of famfam icons and assumes structure like
#notifications, #notifications li {
list-style: none;
list-style-type: none;
margin-left: 0;
}
.information, .error, .success, .warning {
margin-top: 0.4em;
border: 1px solid #9bb8d9;
padding: 6px 6px 6px 30px;
}
.information {
background: #dedfff url('../icons/information.png') 6px 50% no-repeat;
color: #406299;
}
.error {
background: #ffe1da url('../icons/exclamation.png') 6px 50% no-repeat;
border-color: #f34f4f;
color: #be0b0b;
}
.success {
background: #e2f9e3 url('../icons/accept.png') 6px 50% no-repeat;
border-color: #9c9;
color: #080;
}
.warning {
background:#fff8bf url('../icons/error.png') 6px 50% no-repeat;
border-color: #ffd324;
color:#eb830c;
}
'''
from django.utils.encoding import StrAndUnicode
DEFAULT_TYPE = 'information'
class NotificationMiddleware:
def process_request(self, request):
request.__class__.notifications = Notifications(request.session)
return None
class Notifications:
def __init__(self, session):
self.session = session
self.SESSION_VARIABLE = '_notifications'
def get(self):
return self.session.get(self.SESSION_VARIABLE, [])
def get_and_clear(self):
return self.session.pop(self.SESSION_VARIABLE, [])
def create(self, message, type=DEFAULT_TYPE):
"""creates a notification
arguments:
message: text content of notification
type: optional type (defaults to the value of DEFAULT_TYPE)
"""
notifications = self.session.get(self.SESSION_VARIABLE)
if notifications is None:
notifications = []
self.session[self.SESSION_VARIABLE] = notifications
notifications.append({'content': message, 'type': type})
self.session.modified = True
def notifications(request):
"""
Returns notifications for the session and the current user.
Note that this processor is only useful to use explicity if you are not
using the (enabled by default) auth processor, as it also provides the
notifications (by calling this method).
The notifications are lazy loaded, so no notifications are retreived and deleted
unless requested from the template.
Both contrib.session and contrib.auth are optional. If neither is provided,
no 'notifications' variable will be added to the context.
"""
if hasattr(request, 'session') or hasattr(request, 'user'):
return {'notifications': LazyNotifications(request)}
return {}
class LazyNotifications(StrAndUnicode):
"""
A lazy proxy for session and authentication notifications.
"""
def __init__(self, request):
self.request = request
def __iter__(self):
return iter(self.notifications)
def __len__(self):
return len(self.notifications)
def __nonzero__(self):
return bool(self.notifications)
def __unicode__(self):
return unicode(self.notifications)
def __getitem__(self, *args, **kwargs):
return self.notifications.__getitem__(*args, **kwargs)
def _get_notifications(self):
if hasattr(self, '_notifications'):
return self._notifications
# First, retreive any notifications for the user.
if hasattr(self.request, 'user') and \
hasattr(self.request.user, 'get_and_delete_messages'):
self._notifications = [{'content': message, 'type': DEFAULT_TYPE} for
message in self.request.user.get_and_delete_messages()]
else:
self._notifications = []
# Next, retrieve any notifications for the session.
if hasattr(self.request, 'session'):
self._notifications += self.request.notifications.get_and_clear()
return self._notifications
notifications = property(_get_notifications)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 9 months ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months, 1 week ago
- Serializer factory with Django Rest Framework by julio 1 year, 4 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
- Help text hyperlinks by sa2812 1 year, 5 months ago
Comments
Great! I was just looking for passing error type with messages.. Thanks
BTW it is NotificationMiddleware not Notification
Installation: add notifications.NotificationMiddleware to MIDDLEWARE_CLASSES
#
@Akram thanks, fixed that typo.
#
I don't understand this:
Why do you add this to the class for every request? Why not request.notifications=...?
I guess this is not thread safe since all threads use the same request class.
#
Hi,
I think you need to call unicode on the following part:
notifications.append({'content': unicode(message), 'type': type})
This way, it can convert gettext string before adding it to the session.
Thanks!
#
Has anyone had any issues with this. I'm getting weird results. Sometimes there is a long delay after setting the notification and actually having it displayed. It seems very random though.
#
Please login first before commenting.