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
)