1
from django.conf import settings
2
from django.utils.encoding import force_unicode, StrAndUnicode
3
from django.contrib.messages import constants, utils
6
LEVEL_TAGS = utils.get_level_tags()
9
class Message(StrAndUnicode):
11
Represents an actual message that can be stored in any of the supported
12
storage classes (typically session- or cookie-based) and rendered in a view
16
def __init__(self, level, message, extra_tags=None):
17
self.level = int(level)
18
self.message = message
19
self.extra_tags = extra_tags
23
Prepares the message for serialization by forcing the ``message``
24
and ``extra_tags`` to unicode in case they are lazy translations.
26
Known "safe" types (None, int, etc.) are not converted (see Django's
27
``force_unicode`` implementation for details).
29
self.message = force_unicode(self.message, strings_only=True)
30
self.extra_tags = force_unicode(self.extra_tags, strings_only=True)
32
def __eq__(self, other):
33
return isinstance(other, Message) and self.level == other.level and \
34
self.message == other.message
36
def __unicode__(self):
37
return force_unicode(self.message)
40
label_tag = force_unicode(LEVEL_TAGS.get(self.level, ''),
42
extra_tags = force_unicode(self.extra_tags, strings_only=True)
43
if extra_tags and label_tag:
44
return u' '.join([extra_tags, label_tag])
50
tags = property(_get_tags)
53
class BaseStorage(object):
55
This is the base backend for temporary message storage.
57
This is not a complete class; to be a usable storage backend, it must be
58
subclassed and the two methods ``_get`` and ``_store`` overridden.
61
def __init__(self, request, *args, **kwargs):
62
self.request = request
63
self._queued_messages = []
65
self.added_new = False
66
super(BaseStorage, self).__init__(*args, **kwargs)
69
return len(self._loaded_messages) + len(self._queued_messages)
73
if self._queued_messages:
74
self._loaded_messages.extend(self._queued_messages)
75
self._queued_messages = []
76
return iter(self._loaded_messages)
78
def __contains__(self, item):
79
return item in self._loaded_messages or item in self._queued_messages
82
def _loaded_messages(self):
84
Returns a list of loaded messages, retrieving them first if they have
87
if not hasattr(self, '_loaded_data'):
88
messages, all_retrieved = self._get()
89
self._loaded_data = messages or []
90
return self._loaded_data
92
def _get(self, *args, **kwargs):
94
Retrieves a list of stored messages. Returns a tuple of the messages
95
and a flag indicating whether or not all the messages originally
96
intended to be stored in this storage were, in fact, stored and
97
retrieved; e.g., ``(messages, all_retrieved)``.
99
**This method must be implemented by a subclass.**
101
If it is possible to tell if the backend was not used (as opposed to
102
just containing no messages) then ``None`` should be returned in
103
place of ``messages``.
105
raise NotImplementedError()
107
def _store(self, messages, response, *args, **kwargs):
109
Stores a list of messages, returning a list of any messages which could
112
One type of object must be able to be stored, ``Message``.
114
**This method must be implemented by a subclass.**
116
raise NotImplementedError()
118
def _prepare_messages(self, messages):
120
Prepares a list of messages for storage.
122
for message in messages:
125
def update(self, response):
127
Stores all unread messages.
129
If the backend has yet to be iterated, previously stored messages will
130
be stored again. Otherwise, only messages added after the last
131
iteration will be stored.
133
self._prepare_messages(self._queued_messages)
135
return self._store(self._queued_messages, response)
137
messages = self._loaded_messages + self._queued_messages
138
return self._store(messages, response)
140
def add(self, level, message, extra_tags=''):
142
Queues a message to be stored.
144
The message is only queued if it contained something and its level is
145
not less than the recording level (``self.level``).
149
# Check that the message level is not less than the recording level.
151
if level < self.level:
154
self.added_new = True
155
message = Message(level, message, extra_tags=extra_tags)
156
self._queued_messages.append(message)
158
def _get_level(self):
160
Returns the minimum recorded level.
162
The default level is the ``MESSAGE_LEVEL`` setting. If this is
163
not found, the ``INFO`` level is used.
165
if not hasattr(self, '_level'):
166
self._level = getattr(settings, 'MESSAGE_LEVEL', constants.INFO)
169
def _set_level(self, value=None):
171
Sets a custom minimum recorded level.
173
If set to ``None``, the default level will be used (see the
174
``_get_level`` method).
176
if value is None and hasattr(self, '_level'):
179
self._level = int(value)
181
level = property(_get_level, _set_level, _set_level)