Flask WTForms的FieldList中动态SelectField值被首条覆盖问题
问题原因
所有SelectField提交值被覆盖的核心原因是你手动绕过了WTForms FieldList的自动字段命名逻辑,具体问题如下:
- 你直接给
List_Compose_Form.list_mat赋值自定义的MatForm实例列表,每个MatForm的mat字段没有自动生成的序号前缀,所有下拉框的name属性都是mat,浏览器提交同名参数只会保留一个值,导致所有字段拿到同一个结果 - 模板存在HTML标签嵌套错误,
form标签提前关闭,可能导致部分字段未被正确纳入表单提交范围 - 手动给每个
MatForm传request.form的逻辑多余,反而会干扰WTForms的自动数据填充
修复方案
1. 调整路由逻辑,使用FieldList原生的动态添加条目方法
不要手动生成MatForm列表,改用append_entry()方法动态添加子表单,让WTForms自动处理字段前缀:
import re import pickle from flask import session, redirect, url_for, render_template, request @app.route("/compose",methods=['GET','POST']) @grade_required def compose(): the_grade = session['grade'] session['dic_compos'] = {} # 先加载配置数据 raw_name = r'interface_app\grades_raw\\' + str(the_grade) + '_clnd.raw' dic_compose, dic_choice = pickle.load(open(raw_name,'rb')) # 初始化父表单 form = List_Compose_Form(request.form) # 清空默认条目,保存所有材料标签后续提交用 form.list_mat.entries = [] mat_labels = [] for key, values in dic_compose.items(): mat_labels.append(key) # 调用FieldList原生方法添加子表单,自动生成前缀 sub_form = form.list_mat.append_entry() sub_form.mat.label = key # 设置下拉选项 if re.search('%', str(key)): choice = [(values, values)] choice += [(str(i/10), str(i/10)) for i in range(1, 200)] else: choice = [(values, values)] choice += [(dic_choice[key][i], dic_choice[key][i]) for i in range(1, len(dic_choice[key]))] sub_form.mat.choices = choice if form.submit.data and form.validate(): for idx, sub_form in enumerate(form.list_mat): session['dic_compos'][mat_labels[idx]] = sub_form.mat.data return redirect(url_for('test')) return render_template('compose.html', form=form)
原来的compose_form函数可以废弃,或者仅保留配置加载的逻辑抽成单独的工具函数即可。
2. 修复模板的HTML嵌套问题,补充隐藏字段
修正form标签的位置,添加hidden_tag()自动渲染csrf等隐藏字段:
<div class="table-responsive-sm"> <form action="" method="post" role="form"> <table id="data" class="table table-dark table-responsive overflow-auto" style="height:400px"> <thead > <tr> <th>Labels</th> <th>Selected</th> </tr> </thead> <tbody> {% for mat_form in form.list_mat %} <tr> <th>{{mat_form.mat.label}}</th> <th>{{mat_form.mat}}</th> </tr> {% endfor %} </tbody> </table> <div> {{ form.hidden_tag() }} {{ form.submit }} </div> </form> </div>
修复原理
WTForms的FieldList会自动给每个子表单的字段添加序号前缀,比如第一个子表单的mat字段name为list_mat-0-mat,第二个为list_mat-1-mat,确保所有提交字段名唯一,不会出现值覆盖的问题。
内容的提问来源于stack exchange,提问作者v_boubou
相关产品推荐
相关产品推荐

