添加JS后Django表单无法识别提交按钮,跳转异常求助
解决Django表单延迟提交后无法识别提交按钮的问题
问题根源
当使用JavaScript的form.submit()方法提交表单时,浏览器不会自动将触发提交的按钮的name和value包含到POST数据中,而Django后端正是通过检测request.POST里的按钮name来区分不同操作的,所以会出现无法识别点击按钮的情况。另外你代码里还有个笔误:模板中按钮的name是add_ingredient,但视图里判断的是add_ingredients(多了个s),这本来就会导致原逻辑异常,需要先修正。
解决方案
通过添加隐藏输入框存储点击的按钮标识,再在延迟提交时将该标识传入后端,具体步骤如下:
1. 修改模板表单,添加隐藏输入框
在表单的{% csrf_token %}下方添加一个隐藏输入,用来存储触发提交的按钮名称:
<form id="form" class="form" method="post" action="{% url 'core:add_ingredient' menu_item.id %}"> {% csrf_token %} <!-- 添加隐藏输入框 --> <input type="hidden" id="submit_action" name="submit_action" value=""> {{ form.as_p }} <div class="button-container"> <button id="another-ingredient-button" type="submit" name="add_ingredient">Add Another Ingredient</button> <button type="submit" name="substitute">Add Substitute</button> <button class="done" type="submit" name="done">Done</button> </div> </form>
2. 修改JavaScript代码,记录触发按钮
在表单的submit事件中,获取触发提交的按钮,将其name存入隐藏输入框,再执行延迟提交:
const alertBox = document.getElementById('alert-box') const form = document.getElementById('form') const submitActionInput = document.getElementById('submit_action') form.addEventListener('submit', (e) => { // 获取触发提交的按钮 const submitButton = e.submitter; if (submitButton) { submitActionInput.value = submitButton.name; } e.preventDefault(); alertBox.style.display = 'block'; setTimeout(() => { form.submit(); alertBox.style.display = 'none'; }, 1000); });
3. 修正Django视图逻辑
先修正笔误,再同时兼容原按钮name和新的隐藏字段,确保两种提交方式都能识别:
form = MenuItemForm(request.POST or None, request.FILES or None) if request.method != 'POST': form = MenuItemForm() else: # 获取提交动作标识,优先取隐藏字段,兼容原按钮提交 submit_action = request.POST.get('submit_action') # 修正笔误:模板里是add_ingredient,不是add_ingredients if 'add_ingredient' in request.POST or submit_action == 'add_ingredient': if form.is_valid(): menu_item = form.save(commit=False) menu_item.menu = menu_instance menu_item.save() return redirect('core:add_ingredient', menu_item_id=menu_item.id) elif 'substitute' in request.POST or submit_action == 'substitute': # 补充substitute对应的处理逻辑 if form.is_valid(): menu_item = form.save(commit=False) menu_item.menu = menu_instance menu_item.save() # 替换为substitute对应的跳转视图 return redirect('core:add_substitute', menu_item_id=menu_item.id) elif 'done' in request.POST or submit_action == 'done': if form.is_valid(): menu_item = form.save(commit=False) menu_item.menu = menu_instance menu_item.save() return redirect('core:edit_menu')
额外说明
e.submitter是HTML5新增的属性,可直接获取触发提交的按钮,若需兼容旧浏览器,可改为监听每个提交按钮的click事件来记录按钮名称:// 给所有submit按钮加点击监听 document.querySelectorAll('button[type="submit"]').forEach(btn => { btn.addEventListener('click', () => { submitActionInput.value = btn.name; }); });- 你原视图中没有处理
substitute按钮的逻辑,需要补充对应的跳转或业务代码,否则点击该按钮会默认执行done的逻辑。
内容的提问来源于stack exchange,提问作者JimmyFl0
相关产品推荐
相关产品推荐

