You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask项目点击按钮遇KeyError及JS加载动画失效问题求助

Flask表单提交问题:KeyError与JS加载失效修复方案

问题描述

我是Python Flask Web开发初学者,迁移程序到服务器时遇到以下问题:

  • 预期点击「Check Price」按钮后:按钮消失、获取输入框值、显示spinner加载模块
  • 实际异常:
    • 未给表单输入框设置id时,触发「user-input-field未找到」KeyError
    • 添加id='user-input-field'后,JS模块失效(spinner不显示),且后端获取的输入框值为None
    • 修改表单输入框的id则再次出现KeyError

问题根源

  1. JS失效+输入值为None:点击按钮触发hideFunction()后,代码将输入框设为disabled = true,导致表单提交时该字段不会被发送到后端,因此request.form.get('user-input-field')返回None;同时表单提交会立即刷新页面,JS修改的DOM状态被重置,spinner来不及展示。
  2. KeyError:输入框的name属性与后端获取参数不一致,或者后端直接用request.form['user-input-field'](而非get)取值时,若字段不存在会抛出KeyError。

修复方案

方案1:使用AJAX异步提交(推荐)

通过AJAX提交表单,避免页面刷新,保留JS的DOM修改效果,同时正常传递表单数据。

修改HTML中的JS代码

const hideFunction = (event) => {
  // 阻止表单默认提交行为
  event.preventDefault();
  
  const textInputField = document.getElementById('user-input-field');
  const buttonContainer = document.getElementById('button_container');
  const spinnerContainer = document.getElementById('spinner-block');

  const inputValue = textInputField.value.trim();
  if (inputValue !== '') {
    buttonContainer.style.display = 'none';
    spinnerContainer.style.display = 'block';
    textInputField.disabled = true;

    // 发起AJAX请求提交数据
    fetch('/competitive_list', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: `user-input-field=${encodeURIComponent(inputValue)}`
    })
    .then(response => response.text())
    .then(data => {
      // 替换页面内容为后端返回的结果
      document.querySelector('.card-body').innerHTML = data;
    })
    .catch(error => {
      // 提交失败后恢复按钮状态
      buttonContainer.style.display = 'block';
      spinnerContainer.style.display = 'none';
      textInputField.disabled = false;
      console.error('提交出错:', error);
    });
  } else {
    buttonContainer.style.display = 'block';
    spinnerContainer.style.display = 'none';
  }
}

修改按钮的onclick事件

传递event参数以阻止默认提交:

<button type="submit" class="btn btn-primary" onclick="hideFunction(event)">Check price</button>

方案2:调整同步提交的JS逻辑(简单但体验差)

如果不想用AJAX,只需移除禁用输入框的代码,保证表单能正常发送数据:

const hideFunction = () => {
  const textInputField = document.getElementById('user-input-field');
  const buttonContainer = document.getElementById('button_container');
  const spinnerContainer = document.getElementById('spinner-block');

  if (textInputField.value.trim() !== '') {
    buttonContainer.style.display = 'none';
    spinnerContainer.style.display = 'block';
    // 移除禁用输入框的代码,避免数据无法提交
    // textInputField.disabled = true;
  } else {
    buttonContainer.style.display = 'block';
    spinnerContainer.style.display = 'none';
  }
}

注意:此方式下页面会立即刷新,spinner仅能短暂显示,用户体验不如AJAX。

后端代码调整

确保密钥设置(用于flash消息),并定义d变量避免NameError:

from flask import Flask, request, render_template, flash
import time

app = Flask(__name__)
app.secret_key = 'your-custom-secret-key'  # 必须设置才能使用flash消息

@app.route('/competitive_list', methods=["GET", "POST"])
def competitive_list():
    if request.method == 'POST':            
        user_input_name = request.form.get('user-input-field')
        print(user_input_name)        
        time.sleep(2)
        # 替换为实际业务逻辑生成的数据
        d = {"product_name": user_input_name, "price": "¥99"}
        return render_template('competitive_list.html',                               
                               sample=d,
                               table=True,
                               button=True
                               )
    else:        
        return render_template('competitive_list.html',
                               button=True
                               )

关键注意事项

  • 表单输入框的name属性必须与后端request.form.get的参数完全一致(此处为user-input-field),否则会触发KeyError。
  • 同步提交表单时,禁用输入框会导致字段数据无法被发送到后端,需避免此操作。
  • AJAX提交能实现无刷新加载,更符合预期的用户体验。

内容的提问来源于stack exchange,提问作者Максим Игрок

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 04:11:10