Flask重定向导致/confirm-order路由POST请求重复发送问题求助
问题根因
- Session操作顺序错误:当前POST处理逻辑是先读取
session['text']、session['note'],再执行pop操作。如果两个请求间隔极短,第一个请求还没完成session修改,第二个请求进入时仍能读取到未被清除的会话数据,就会触发重复创建订单。 - 缺少无效请求拦截:GET和POST请求中都没有判断会话数据是否存在,当会话数据已被清除时直接读取
session['key']会抛出KeyError,触发服务端500错误,表现为浏览器提示无法访问站点。 - 无重复提交拦截:原生表单没有阻止重复点击的逻辑,用户误双击、网络延迟导致用户重复点击都会触发多次POST请求。
修复方案
- 调整session操作逻辑,优先做幂等判断
修改confirm_order路由的处理逻辑,先弹出会话数据,判断存在后再执行业务逻辑:
@views.route('/confirm-order', methods=['GET', 'POST']) @login_required def confirm_order(): if request.method == 'POST': # 先弹出数据,后续重复请求拿不到数据直接拦截 text = session.pop('text', None) note = session.pop('note', None) if not text or not note: return redirect(url_for('views.home')) create_order(current_user, text, note) return redirect(url_for('views.home')) elif request.method == 'GET': # GET请求也要加判断,避免直接访问路由抛出异常 text = session.get('text') note = session.get('note') if not text or not note: return redirect(url_for('views.home')) sample_list = get_samples(text, note) return render_template("confirm.html", user=current_user, sample_list=sample_list)
- 新增表单重复点击拦截
在form标签添加原生提交事件处理,点击提交后直接禁用按钮,不需要引入外部JS:
<form method="POST" onsubmit="document.getElementById('submit_btn').disabled = true;">
- 新增订单幂等校验(适合生产环境)
在首页生成唯一订单令牌存入session,创建订单时先校验令牌是否已被使用,从数据层避免重复订单:
# 首页路由POST逻辑新增 import uuid session['order_token'] = uuid.uuid4().hex # create_order函数修改,同时需要给Order表新增order_token字段存储唯一令牌 def create_order(user, text, note, order_token): # 先查询是否存在同令牌的订单 exist_order = Order.query.filter_by(user_id=user.id, order_token=order_token).first() if exist_order: return exist_order new_order = Order( user_id=current_user.id, text=text, status='submitted', note=note, order_token=order_token ) db.session.add(new_order) db.session.commit() return new_order
内容的提问来源于stack exchange,提问作者Rainie
相关产品推荐
相关产品推荐

