Как обуздать Django messages?

Привет всем!
Имею давнюю проблему с выдачей в шаблоне django messages. Мне лично они нужны в одном случае, всего на одной странице. Поэтому во view я устанавливаю сообщение и редирект:
if not available_cars:
				carstoshow = None
				messages.error(request, 'Ваш диапазон дат занят для данного объекта.')
				return redirect('car_detail', pk=car_used_id)


Показываю сообщение в шаблоне стандартным способом:
{% if messages %}
<div class="alert alert-warning">
<div class="container text-center">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</div>
</div>
{% endif %}

Все работало отлично. Но попробовав несколько раз login/logout, на той странице мне выдается куча сообщений связаных с django-allauth аутентификацией(то же и в админке):
6f15480572a74ba0882ca412e77eedad.png6ab10c5c1e1445d69e2a02bc37184dc2.png

Пробовал устанавливать своё сообщение как messages.error, messages.info и тд. Чтобы отсеить ненужные в шаблоне:
{% if messages.тип_моих_сообщений %}
{% for message in messages.тип_моих_сообщений %}

ничего не выходит: либо вся куча , либо ничего.

Вопрос: как можно допустить только мои сообщения.

Спасибо, буду признателен любой помощи
  • Вопрос задан
  • 4971 просмотр
Решения вопроса 1
winordie
@winordie
Лучшая документация -- исходники
Давайте посмотрим как работает framework messages.

https://github.com/django/django/blob/master/djang...
def messages(request):
    return {
        'messages': get_messages(request),
        'DEFAULT_MESSAGE_LEVELS': DEFAULT_LEVELS,
    }
...
def get_messages(request):
    if hasattr(request, '_messages'):
        return request._messages
    else:
        return []

Так messages попадают на страницу. Т.е. они берутся из request._messages. Как же они туда попадают?

https://github.com/django/django/blob/master/djang...
class MessageMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request._messages = default_storage(request)
...
def default_storage(request):
    return import_string(settings.MESSAGE_STORAGE)(request)
...
MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'

Значит в request._messages у нас лежит FallbackStorage(request)

Перейдем к нашему коду
messages.error(request, 'Ваш диапазон дат занят для данного объекта.')

Что тут происходит? Посмотрим:
https://github.com/django/django/blob/master/djang...
def error(request, message, extra_tags='', fail_silently=False):
    add_message(request, constants.ERROR, message, extra_tags=extra_tags,
                fail_silently=fail_silently)
...
def add_message(request, level, message, extra_tags='', fail_silently=False):
    if not isinstance(request, HttpRequest):
        raise TypeError("add_message() argument must be an HttpRequest object, "
                        "not '%s'." % request.__class__.__name__)
    if hasattr(request, '_messages'):
        return request._messages.add(level, message, extra_tags)  # *** THIS ***
    if not fail_silently:
        raise MessageFailure('You cannot add messages without installing '
                    'django.contrib.messages.middleware.MessageMiddleware')

Ага, вызывается метод add знакомого нам объекта FallbackStorage.
Ему передается в качестве параметров:
- level = constants.ERROR = 40
- message = 'Ваш диапазон дат занят для данного объекта.'
- extra_tags = ''

Посмотрим на этот метод
https://github.com/django/django/blob/master/djang...
def add(self, level, message, extra_tags=''):
        if not message:
            return
        level = int(level)
        if level < self.level:
            return
        # Add the message.
        self.added_new = True
        message = Message(level, message, extra_tags=extra_tags)
        self._queued_messages.append(message)
...
def _get_level(self):
        if not hasattr(self, '_level'):
            self._level = getattr(settings, 'MESSAGE_LEVEL', constants.INFO)
        return self._level

Из этого кода можно сделать вывод что сообщение попадает в очередь сообщений если его уровень более или равен тому который задан в settings.MESSAGE_LEVEL (по умолчанию = contants.INFO = 20)

Таким образом чтобы добавлялись только наши сообщения необходимо:
1) в settings.py установить
# settings.py
...
MY_SUPER_ERROR = 80
MESSAGE_LEVEL = MY_SUPER_ERROR
...

2) Во вью писать
if not available_cars:
        carstoshow = None
        messages.add_message(request, settings.MY_SUPER_ERROR, 'Ваш диапазон дат занят для данного объекта.')
        return redirect('car_detail', pk=car_used_id)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы