Flask提交特征选择表单报400 Bad Request错误如何解决
问题根因
提交请求返回400 Bad Request是前后端表单交互逻辑存在多处不匹配导致的,具体问题如下:
- 表单范围错误:X/Y特征选择的下拉框全部放在文件上传的form标签外部,提交时这些字段不会被发送到后端,后端读取
x_columns[]、y_columns[]字段时找不到对应键,直接触发400错误。 - 文件上传配置错误:form标签未添加
enctype="multipart/form-data"属性,无法正常传输文件;后端错误使用request.form读取上传文件,Flask接收上传文件必须通过request.files获取对象。 - 多选值读取方式错误:多选下拉框返回多值,直接用
request.form['key']只能读取单个值,必须使用request.form.getlist('key')获取所有选中项的列表。 - 多选插件初始化错误:下拉框设置的id为
x、y,初始化插件时错误使用$('#x_columns[]')、$('#y_columns[]')作为选择器,无法匹配DOM元素,插件未生效。 - 模型参数错误:GRNN初始化时sigma参数传入了Python内置的
input函数,属于无效参数,训练时会报错。 - 模板传参错误:调用
render_template时传入MSE值未指定参数名,模板无法正常读取该值。 - 冗余元素冲突:页面存在
<p name="y_columns[]"> dogru</p>的冗余标签,会和Y列选择的字段名产生冲突。
修正后代码
前端index.html
<!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="multiselect/jquery.multiselect.js"></script> <link rel="stylesheet" href="multiselect/jquery.multiselect.css"> <style> .container{ padding:20px; position: relative; } .result{ margin: 20px; padding: 10px; border: 1px solid #eee; } </style> </head> <body> <!-- 所有提交元素纳入同一表单,添加文件上传必需的enctype属性 --> <form action="/data" method="post" enctype="multipart/form-data"> <input type="file" name="upload_file" required> <br><br> <div class="container"> <select name="x_columns[]" multiple id="x"> <option value="X1">X1</option> <option value="X2">X2</option> <option value="X3">X3</option> <option value="X4">X4</option> <option value="X5">X5</option> <option value="X6">X6</option> <option value="Y">Y</option> </select> </div> <div class="container"> <select name="y_columns[]" multiple id="y"> <option value="X1">X1</option> <option value="X2">X2</option> <option value="X3">X3</option> <option value="X4">X4</option> <option value="X5">X5</option> <option value="X6">X6</option> <option value="Y">Y</option> </select> </div> <br> <input type="submit" value="开始训练"> {% if mse_IGRNN %} <div class="result"> <p>GRNN模型测试集MSE:{{ mse_IGRNN }}</p> <h4>数据集预览</h4> {{ data | safe }} </div> {% endif %} </form> <script> // 修正选择器,通过id匹配元素初始化多选插件 $('#x').multiselect({ columns: 1, placeholder: '选择X特征列' }); $('#y').multiselect({ columns: 1, placeholder: '选择Y标签列' }); </script> </body> </html>
后端app.py
import pandas as pd import io from flask import Flask,render_template,request from sklearn.model_selection import train_test_split from sklearn import preprocessing from pyGRNN import GRNN from sklearn.metrics import mean_squared_error as MSE app = Flask(__name__) @app.route('/',methods=['GET']) def index(): return render_template('index.html') @app.route('/data',methods=['POST']) def show_data(): # 正确读取上传文件 upload_file = request.files['upload_file'] # 兼容csv和excel格式读取 if upload_file.filename.endswith('.csv'): data = pd.read_csv(io.BytesIO(upload_file.read())) else: data = pd.read_excel(upload_file) # 读取多选的列名 x_names = request.form.getlist('x_columns[]') y_names = request.form.getlist('y_columns[]') # 非空校验 if not x_names or not y_names: return "请至少选择1个X特征列和1个Y标签列", 400 X = data[x_names] Y = data[y_names] x_train, x_test, y_train, y_test = train_test_split(preprocessing.minmax_scale(X), Y, test_size=0.2, random_state=42) # 修正GRNN初始化参数,sigma传入合法数值 IGRNN = GRNN(bnds=(0, None), calibration='None', kernel='RBF', method='L-BFGS-B', n_restarts_optimizer=0, n_splits=5, seed=42, sigma=0.5) IGRNN.fit(x_train, y_train.values.ravel()) y_pred = IGRNN.predict(x_test) mse_IGRNN = MSE(y_test, y_pred) # 模板传参指定参数名,只返回前10行数据预览避免页面过长 return render_template('index.html', mse_IGRNN=mse_IGRNN, data=data.head(10).to_html()) if __name__=='__main__': app.run(debug=True)
注意:你使用的UCI公开数据集为csv格式,代码中已经做了格式兼容,不需要手动转成excel。
内容的提问来源于stack exchange,提问作者Nazli
相关产品推荐
相关产品推荐

