Django框架下onbeforeunload事件触发表单提交失败如何解决?
问题根因
- 浏览器为了避免阻塞用户的页面卸载/跳转流程,默认会拦截
onbeforeunload事件中所有会触发页面跳转的操作(包括同步表单提交、触发submit按钮点击),只有同步的DOM修改这类极快完成的操作才会被执行,这就是你p标签内容修改成功但表单没提交的核心原因。 - 你写的两个提交逻辑本身冲突:调用
submit()后即使没被拦截,表单已经触发提交流程,后续的$('#save').click()也不会生效。
可行解决方案
推荐使用浏览器专门为页面卸载场景设计的navigator.sendBeacon()API实现,该API的请求由浏览器后台保证发送,不会被拦截,也不会阻塞页面卸载。
具体实现步骤
- 先从Django页面的cookie中拿到CSRF Token,Django默认的CSRF Token存储在名为
csrftoken的cookie中 - 在
onbeforeunload事件中收集表单数据,通过sendBeacon发送给后端接口 - 后端适配接收数据逻辑即可
代码示例
前端修改
window.onbeforeunload = function(e){ // 原有DOM修改逻辑保留 document.getElementById("demo1").innerHTML="No"; // 收集表单数据 const form = document.getElementById('all_questions'); const formData = new FormData(form); // 从cookie获取CSRF Token适配Django校验 function getCookie(name) { let value = "; " + document.cookie; let parts = value.split("; " + name + "="); if (parts.length === 2) return parts.pop().split(";").shift(); } formData.append('csrfmiddlewaretoken', getCookie('csrftoken')); // 发送请求,下方url替换为你原有表单对应的后端提交地址 navigator.sendBeacon("/your-form-submit-url/", formData); }
后端适配说明
原有表单提交的业务逻辑可以基本复用,仅需要把提交成功后的页面跳转逻辑改为直接返回200状态码即可,sendBeacon不需要处理前端响应。
备选方案(不推荐)
如果一定要用原生表单提交的方式,可以给form标签添加target="_blank"属性,让表单提交跳转至新页面,但是会导致用户关闭/刷新页面时弹出多余的空白标签页,体验极差,不建议使用。
内容的提问来源于stack exchange,提问作者zinc
相关产品推荐
相关产品推荐

