~ubuntu-branches/ubuntu/quantal/python-django/quantal-security

« back to all changes in this revision

Viewing changes to django/contrib/messages/storage/base.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2010-05-21 07:52:55 UTC
  • mfrom: (1.3.6 upstream)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: james.westby@ubuntu.com-20100521075255-ii78v1dyfmyu3uzx
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from django.conf import settings
 
2
from django.utils.encoding import force_unicode, StrAndUnicode
 
3
from django.contrib.messages import constants, utils
 
4
 
 
5
 
 
6
LEVEL_TAGS = utils.get_level_tags()
 
7
 
 
8
 
 
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
    """
 
15
 
 
16
    def __init__(self, level, message, extra_tags=None):
 
17
        self.level = int(level)
 
18
        self.message = message
 
19
        self.extra_tags = extra_tags
 
20
 
 
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.
 
25
 
 
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)
 
31
 
 
32
    def __eq__(self, other):
 
33
        return isinstance(other, Message) and self.level == other.level and \
 
34
                                              self.message == other.message
 
35
 
 
36
    def __unicode__(self):
 
37
        return force_unicode(self.message)
 
38
 
 
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)
 
51
 
 
52
 
 
53
class BaseStorage(object):
 
54
    """
 
55
    This is the base backend for temporary message storage.
 
56
 
 
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
    """
 
60
 
 
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)
 
67
 
 
68
    def __len__(self):
 
69
        return len(self._loaded_messages) + len(self._queued_messages)
 
70
 
 
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)
 
77
 
 
78
    def __contains__(self, item):
 
79
        return item in self._loaded_messages or item in self._queued_messages
 
80
 
 
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
 
91
 
 
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)``.
 
98
 
 
99
        **This method must be implemented by a subclass.**
 
100
 
 
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``.
 
104
        """
 
105
        raise NotImplementedError()
 
106
 
 
107
    def _store(self, messages, response, *args, **kwargs):
 
108
        """
 
109
        Stores a list of messages, returning a list of any messages which could
 
110
        not be stored.
 
111
 
 
112
        One type of object must be able to be stored, ``Message``.
 
113
 
 
114
        **This method must be implemented by a subclass.**
 
115
        """
 
116
        raise NotImplementedError()
 
117
 
 
118
    def _prepare_messages(self, messages):
 
119
        """
 
120
        Prepares a list of messages for storage.
 
121
        """
 
122
        for message in messages:
 
123
            message._prepare()
 
124
 
 
125
    def update(self, response):
 
126
        """
 
127
        Stores all unread messages.
 
128
 
 
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.
 
132
        """
 
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)
 
139
 
 
140
    def add(self, level, message, extra_tags=''):
 
141
        """
 
142
        Queues a message to be stored.
 
143
 
 
144
        The message is only queued if it contained something and its level is
 
145
        not less than the recording level (``self.level``).
 
146
        """
 
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)
 
157
 
 
158
    def _get_level(self):
 
159
        """
 
160
        Returns the minimum recorded level.
 
161
 
 
162
        The default level is the ``MESSAGE_LEVEL`` setting. If this is
 
163
        not found, the ``INFO`` level is used.
 
164
        """
 
165
        if not hasattr(self, '_level'):
 
166
            self._level = getattr(settings, 'MESSAGE_LEVEL', constants.INFO)
 
167
        return self._level
 
168
 
 
169
    def _set_level(self, value=None):
 
170
        """
 
171
        Sets a custom minimum recorded level.
 
172
 
 
173
        If set to ``None``, the default level will be used (see the
 
174
        ``_get_level`` method).
 
175
        """
 
176
        if value is None and hasattr(self, '_level'):
 
177
            del self._level
 
178
        else:
 
179
            self._level = int(value)
 
180
 
 
181
    level = property(_get_level, _set_level, _set_level)