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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 13:54:01