App Engine Python SDK version 1.7.4 (2)
[gae.git] / python / lib / django_1_4 / django / contrib / messages / storage / base.py
blob65e8526b5c554f4f8f06cd975dcb11e78c1b3bf8
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):
10 """
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
13 or template.
14 """
16 def __init__(self, level, message, extra_tags=None):
17 self.level = int(level)
18 self.message = message
19 self.extra_tags = extra_tags
21 def _prepare(self):
22 """
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).
28 """
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)
39 def _get_tags(self):
40 label_tag = force_unicode(LEVEL_TAGS.get(self.level, ''),
41 strings_only=True)
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])
45 elif extra_tags:
46 return extra_tags
47 elif label_tag:
48 return label_tag
49 return ''
50 tags = property(_get_tags)
53 class BaseStorage(object):
54 """
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.
59 """
61 def __init__(self, request, *args, **kwargs):
62 self.request = request
63 self._queued_messages = []
64 self.used = False
65 self.added_new = False
66 super(BaseStorage, self).__init__(*args, **kwargs)
68 def __len__(self):
69 return len(self._loaded_messages) + len(self._queued_messages)
71 def __iter__(self):
72 self.used = True
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
81 @property
82 def _loaded_messages(self):
83 """
84 Returns a list of loaded messages, retrieving them first if they have
85 not been loaded yet.
86 """
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):
93 """
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
110 not be stored.
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:
123 message._prepare()
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)
134 if self.used:
135 return self._store(self._queued_messages, response)
136 elif self.added_new:
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``).
147 if not message:
148 return
149 # Check that the message level is not less than the recording level.
150 level = int(level)
151 if level < self.level:
152 return
153 # Add the message.
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)
167 return self._level
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'):
177 del self._level
178 else:
179 self._level = int(value)
181 level = property(_get_level, _set_level, _set_level)