Django:从存储中删除重复邮件
我正在使用Django:从存储中删除重复邮件,django,django-middleware,django-messages,Django,Django Middleware,Django Messages,我正在使用messages将flash消息添加到模板中(正如您所期望的那样) 我遇到的问题是,如果双击指向生成消息的页面的链接,则消息会出现两次 我使用该消息告诉用户,我已将他们的预期目的地重定向。他们没有;我不需要同样的信息两次 我理解这里的逻辑,但我想知道如何删除重复的消息 单击url 生成消息,保存在存储器中 在页面呈现之前再次单击url 生成第二条消息,保存在存储器中 响应添加来自存储的所有消息 呈现两条消息 最终,我希望这是一个中间件,因此它可以覆盖所有请求。选择了自定义模板\u上
messages
将flash消息添加到模板中(正如您所期望的那样)
我遇到的问题是,如果双击指向生成消息的页面的链接,则消息会出现两次
我使用该消息告诉用户,我已将他们的预期目的地重定向。他们没有;我不需要同样的信息两次
我理解这里的逻辑,但我想知道如何删除重复的消息
- 单击url
- 生成消息,保存在存储器中
- 在页面呈现之前再次单击url
- 生成第二条消息,保存在存储器中
- 响应添加来自存储的所有消息
- 呈现两条消息
最终,我希望这是一个
中间件
,因此它可以覆盖所有请求。选择了自定义模板\u上下文\u处理器
将默认消息上下文处理器('django.contrib.messages.context\u 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}
遇到相同的问题并找到了另一个解决方案,使用自定义邮件存储:
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)
我在中间件中也遇到了同样的问题,但我更喜欢在我使用的信息调用周围使用一个小包装器:
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
对于那些使用建议的人
def info_once_only(request, msg):
if msg not in [m.message for m in get_messages(request)]:
info(request, msg)
请注意,迭代get\u messages(request)
会将每条消息标记为“待清除”,因此用户将不会看到任何消息,只有一条消息只传递到info\u一次(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
请参阅中的相应部分。我决定使用改良的保罗方法。 我使用标准消息呼叫,但我导入:
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
重复问题?这与表单无关。如果用户在进入页面之前,我应该重定向他们并显示一条消息。