Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 121 lines (90 sloc) 3.876 kb
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
# coding:utf-8

"""
utils around django messages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
http://docs.djangoproject.com/en/dev/ref/contrib/messages/
:copyleft: 2010-2011 by the django-tools team, see AUTHORS for more details.
:license: GNU GPL v3 or above, see LICENSE for more details.
"""

import inspect
import warnings

from django.conf import settings
from django.contrib import messages
from django.contrib.messages.storage.fallback import FallbackStorage

from django_tools.middlewares import ThreadLocal
from django_tools.utils.stack_info import get_stack_info


STACK_LIMIT = 6 # Display only the last X stack lines
MAX_FILEPATH_LEN = 50 # Cut filepath in stack info message


class FileLikeMessages(object):
    """
Simple layer around messages, to get a file-like object.
usage e.g.:
page_msg = FileLikeMessages(request, messages.INFO)
page_msg.write("This is it!")
page_msg("Call works's, too.")
"""
    def __init__(self, request, msg_level):
        self.request = request
        self.msg_level = msg_level

    def write(self, txt):
        messages.add_message(self.request, self.msg_level, txt)

    __call__ = write


#------------------------------------------------------------------------------


class StackInfoStorage(FallbackStorage):
    """
Message storage like LegacyFallbackStorage, except, every message
would have a stack info, witch is helpful, for debugging.
Stack info would only be added, if...
...settings.DEBUG == True
or
...settings.MESSAGE_DEBUG == True
Put this into your settings:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MESSAGE_STORAGE = "django_tools.utils.messages.StackInfoStorage"
Template e.g.:
~~~~~~~~~~~~~~
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}{% if message.stack_info %} title="click for stack info" onclick="alert('Stack info (limit: {{ message.stack_limit }}, url: [{{ message.full_path }}]):\n\n{{ message.stack_info }}');"{% endif %}>
{{ message }}
</li>
{% endfor %}
</ul>
"""
    _add_stackinfo = settings.DEBUG or getattr(settings, "MESSAGE_DEBUG", False)

    def add(self, *args, **kwargs):
        """ Add stackinfo to the message """
        super(StackInfoStorage, self).add(*args, **kwargs)

        if self._add_stackinfo:
            # info: self._queued_messages is a normal list, defined in BaseStorage()
            message_list = self._queued_messages
            try:
                last_message = message_list[-1]
            except IndexError:
                return

            last_message.full_path = self.request.get_full_path()
            last_message.stack_limit = STACK_LIMIT

            stack_info = get_stack_info(filepath_filter="django_tools", stack_limit=STACK_LIMIT, max_filepath_len=MAX_FILEPATH_LEN)
            stack_info_safe = "\\n".join([l.replace("\n", "\\n").replace("'", "&#x27;") for l in stack_info])
            last_message.stack_info = stack_info_safe


#------------------------------------------------------------------------------


def failsafe_message(msg, level=messages.INFO):
    """
Display a message to the user.
Use ThreadLocalMiddleware to get the current request object.
If no request object is available, create a warning.
"""
    request = ThreadLocal.get_current_request()
    if request:
        # create a normal user message
        try:
            messages.add_message(request, level, msg)
        except Exception, err:
            # e.g.:
            # Without the django.contrib.messages middleware,
            # messages can only be added to authenticated users.
            msg += " (Error create a message: %s)" % err
        else:
            return

    # fallback: Create a warning
    warnings.warn(msg)
Something went wrong with that request. Please try again.