Django项目仅Firefox浏览器出现提交内容重复入库问题
问题根因
- Firefox和Chrome/Safari的表单提交逻辑存在差异:你现有代码中手动调用
submit()触发一次提交后,Firefox不会因为按钮被设置为disabled就拦截按钮的默认提交行为,等于单次点击会触发两次提交;Chrome、Safari默认会拦截已禁用按钮的后续提交行为,所以不会出现问题。 - 代码没有做事件触发前置校验,若事件被多次触发(比如Firefox的点击判定阈值更低,快速点击会触发两次click事件),也会导致重复执行提交逻辑。
parents('form:first')的写法存在小概率匹配异常的问题,若表单结构层级有调整可能选错提交对象。
修复方案
前端兼容修复
优先优化JS逻辑,适配Firefox的事件机制:
$('.prevent_multiple').click(function(e) { // 阻止默认提交行为和事件冒泡,避免重复触发 e.preventDefault(); e.stopPropagation(); // 前置校验按钮状态,已禁用直接终止逻辑 if ($(this).prop('disabled')) return; // 禁用按钮 $(this).prop('disabled', true); // 用closest匹配最近的表单元素,匹配更准确 $(this).closest('form').submit(); });
如果仍有异常,可以改为绑定表单的submit事件,抹平不同浏览器的点击行为差异:
// 绑定所有带防重复提交按钮的表单的提交事件 $('form:has(.prevent_multiple)').on('submit', function(e) { const $submitBtn = $(this).find('.prevent_multiple'); // 按钮已禁用则拦截本次提交 if ($submitBtn.prop('disabled')) { e.preventDefault(); return false; } $submitBtn.prop('disabled', true); });
后端兜底防护
前端防护存在被绕过的可能性,必须加后端幂等校验,彻底杜绝重复提交问题:
- 渲染表单页面时,生成唯一的随机令牌,同时存入用户session和表单的隐藏输入框
- 接收提交请求时,先校验请求携带的令牌是否存在于当前用户的session中:
- 存在:先删除session中的该令牌,再执行后续业务逻辑
- 不存在:直接返回重复提交错误
Django可以通过自定义中间件或者表单装饰器快速实现该逻辑,无需修改原有业务代码。
内容的提问来源于stack exchange,提问作者user16350436
相关产品推荐
相关产品推荐

