Flask 3.x中如何正确标记富文本Flash消息?兼容旧版写法
解决新版Flask中富文本Flash消息的问题
核心原因
升级后,Redis会话存储的序列化器不再支持Markup对象的编码,同时Flask默认会对字符串类型的Flash消息自动转义HTML标签,导致两种情况都无法正常显示富文本。
可行解决方案
方案1:模板中使用safe过滤器(最简便)
Flash时传入原始HTML字符串,在模板中通过safe过滤器告诉Flask该内容是安全的,无需转义:
- 后端代码:
flash('<b>This</b> is a <b>WARNING</b>.', category="warning")
- 模板代码:
{% 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类型的编码和解码:
- 自定义序列化器:
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'
- 模板代码无需修改:因为取出的仍然是
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
相关产品推荐
相关产品推荐

