You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask 3.x中如何正确标记富文本Flash消息?兼容旧版写法

解决新版Flask中富文本Flash消息的问题

核心原因

升级后,Redis会话存储的序列化器不再支持Markup对象的编码,同时Flask默认会对字符串类型的Flash消息自动转义HTML标签,导致两种情况都无法正常显示富文本。

可行解决方案

方案1:模板中使用safe过滤器(最简便)

Flash时传入原始HTML字符串,在模板中通过safe过滤器告诉Flask该内容是安全的,无需转义:

  1. 后端代码:
flash('<b>This</b> is a <b>WARNING</b>.', category="warning")
  1. 模板代码:
{% with messages = get_flashed_messages(with_categories=true) %}
  {% if messages %}
    {% for category, message in messages %}
      <div class="alert alert-{{ category }}">
        {{ message|safe }}
      </div>
    {% endfor %}
  {% endif %}
{% endwith %}

注意:确保所有Flash消息的内容都是可信来源,避免XSS攻击风险。

方案2:自定义会话序列化器(适配Markup对象)

如果坚持要使用Markup对象传递消息,可以自定义Redis会话的序列化器,支持Markup类型的编码和解码:

  1. 自定义序列化器:
from flask import Flask
from flask_redis import FlaskRedis
from markupsafe import Markup
import json

class MarkupSupportingJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Markup):
            # 将Markup对象转为带标识的字符串
            return {"__markup__": str(obj)}
        return super().default(obj)

def markup_decoder(obj):
    if "__markup__" in obj:
        return Markup(obj["__markup__"])
    return obj

app = Flask(__name__)
app.config['REDIS_URL'] = 'redis://localhost:6379/0'

# 初始化Redis并指定自定义序列化器
redis_store = FlaskRedis(app)
redis_store.connection_pool.connection_kwargs['encoder'] = MarkupSupportingJSONEncoder()
redis_store.connection_pool.connection_kwargs['decoder'] = markup_decoder

# 正常使用Markup对象Flash
@app.route('/')
def index():
    flash(Markup('<b>This</b> is a <b>WARNING</b>.'), category="warning")
    return 'Check the flash message'
  1. 模板代码无需修改:因为取出的仍然是Markup对象,Flask会自动识别为安全内容。

方案3:封装Flash工具函数

封装一个工具函数,自动处理Markup对象的存储和渲染,兼顾兼容性:

from flask import flash as flask_flash
from markupsafe import Markup

def flash(message, category='message'):
    if isinstance(message, Markup):
        # 存储时转为带标记的字符串
        flask_flash(('__markup__', str(message)), category=category)
    else:
        flask_flash(message, category=category)

对应的模板处理逻辑:

{% with messages = get_flashed_messages(with_categories=true) %}
  {% if messages %}
    {% for category, message in messages %}
      <div class="alert alert-{{ category }}">
        {% if message is iterable and message[0] == '__markup__' %}
          {{ message[1]|safe }}
        {% else %}
          {{ message }}
        {% endif %}
      </div>
    {% endfor %}
  {% endif %}
{% endwith %}

内容的提问来源于stack exchange,提问作者cteljr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 03:45:10