我使用messages
向模板添加Flash消息(正如您所期望的那样)。
我遇到的问题是,如果您双击指向生成消息的页面的链接,则该消息会出现两次。
我正在使用该消息告诉用户我已经将它们重定向到了他们期望的位置。他们不需要两次相同的消息。
我理解这里的逻辑,但我想知道如何删除重复的消息。
最终我希望这是一个middleware
所以它可以涵盖所有请求。
答案 0 :(得分:6)
我在中间件中遇到了同样的问题,但我更喜欢使用我正在使用的信息调用的一个小包装器:
from django.contrib.messages import info
from django.contrib.messages import get_messages
def info_once_only(request, msg):
"""
Just add the message once
:param request:
:param msg:
:return:
"""
if msg not in [m.message for m in get_messages(request)]:
info(request, msg)
class PaymentsMiddleware(object):
@staticmethod
def process_request(request):
"""
Put up a message letting a new user know that they are being dealt with.
:param request:
:return:
"""
if hasattr(request, 'user'):
user_profile = request.user.get_profile()
if user_profile and user_profile.is_suspended:
info_once_only(
request,
"Hi {username}, your account has been suspended, we'll be in touch shortly.".format(
username=request.user.username))
return None
答案 1 :(得分:5)
遇到同样的问题并找到另一种解决方案,使用自定义MESSAGE_STORAGE:
from django.contrib.messages.storage.session import SessionStorage
from django.contrib.messages.storage.base import Message
class DedupMessageMixin(object):
def __iter__(self):
msgset = [tuple(m.__dict__.items())
for m in super(DedupMessageMixin, self).__iter__()]
return iter([Message(**dict(m)) for m in set(msgset)])
class SessionDedupStorage(DedupMessageMixin, SessionStorage):
pass
# in settings
MESSAGE_STORAGE = 'some.where.SessionDedupStorage'
这对于可以直接播放消息的代码也可以正常工作,例如在视图中。 由于它是mixin,因此您可以轻松地将其重用于其他邮件存储。
以下是避免存储重复项的替代方法:
from django.contrib.messages.storage.session import SessionStorage
from itertools import chain
class DedupMessageMixin(object):
def add(self, level, message, extra_tags):
messages = chain(self._loaded_messages, self._queued_messages)
for m in messages:
if m.message == message:
return
return super(DedupMessageMixin, self).add(level, message, extra_tags)
答案 2 :(得分:1)
选择自定义TEMPLATE_CONTEXT_PROCESSORS
。
使用简单的自定义版本替换默认消息上下文处理器('django.contrib.messages.context_processors.messages',
):
from django.contrib.messages.api import get_messages
def messages(request):
"""Remove duplicate messages
"""
messages = []
unique_messages = []
for m in get_messages(request):
if m.message not in messages:
messages.append(m.message)
unique_messages.append(m)
return {'messages': unique_messages}
答案 3 :(得分:1)
对于那些使用Paul Whipp's建议的人。
def info_once_only(request, msg):
if msg not in [m.message for m in get_messages(request)]:
info(request, msg)
请注意,对get_messages(request)
进行迭代会将每封邮件标记为“清除”,这样用户就不会看到除info_once_only(request, msg)
传递的邮件之外的任何邮件。
您应该设置storage.used = False
,以便其他所有邮件都不会被清除。
def info_once_only(request, msg):
storage = get_messages(request)
if msg not in [m.message for m in storage]:
info(request, msg)
storage.used = False
请参阅official documentation中的相应部分。
答案 4 :(得分:0)
我决定使用修改后的保罗方法。 我使用标准消息呼叫,但我导入:
from myapp.utils import Messages as messages
在utils.py
文件中,我有:
from django.contrib.messages import (get_messages,
error as _error, info as _info, success as _success, warning as _warning)
class Messages:
@classmethod
def error(cls, request, msg):
cls._add_if_unique(request, msg, _error)
@classmethod
def info(cls, request, msg):
cls._add_if_unique(request, msg, _info)
@classmethod
def success(cls, request, msg):
cls._add_if_unique(request, msg, _success)
@classmethod
def warning(cls, request, msg):
cls._add_if_unique(request, msg, _warning)
@classmethod
def _add_if_unique(cls, request, msg, msg_method):
storage = get_messages(request)
if msg not in [m.message for m in storage]:
msg_method(request, msg)
storage.used = False # iterating over get_messages mark them as gone, so lets prevent this