Flask FieldList无法接收前端修改数据及validate_on_submit报错问题
错误原因
- 手动修改字段名不符合WTForms FieldList的命名规则,提交的表单数据无法被正确解析,只能拿到初始化时的默认值,布尔字段匹配不到提交值就会始终返回False。
- 直接将自定义的表单列表赋值给
entry_form_list属性,覆盖了原有的FieldList实例,导致调用校验方法时缺少内部所需的copy等方法,抛出AttributeError。
修复方案
1. 调整表单类
将id字段改为隐藏字段,符合业务逻辑不需要前端显式输入:
class Beneficiary_Migration_Entry_Form(FlaskForm): id = HiddenField('') name = StringField('') school = SelectField('', validate_choice=False) student_class = SelectField('', validate_choice=False) migrate = BooleanField('') class Beneficiary_Migration_Form(FlaskForm): entry_form_list = FieldList(FormField(Beneficiary_Migration_Entry_Form)) submit = SubmitField('Submit')
2. 重写路由逻辑
不要手动修改字段名、不要直接覆盖FieldList属性,用WTForms内置的append_entry方法填充动态条目,区分GET/POST请求的表单初始化逻辑:
@app.route('/migration/student/<school_year_id>', methods=['GET', 'POST']) @login_required def student_migration_page(school_year_id): school_year_id = int(school_year_id) school_year = School_Year.query.filter(School_Year.id==school_year_id).first() school_choices = get_school_list() entries = Student.query.filter(Student.user_id==current_user.id).all() school_map = Database_Manager.get_schools_map(current_user) # 初始化表单,POST请求会自动加载提交的数据 migration_form = Beneficiary_Migration_Form() if migration_form.validate_on_submit(): # 直接遍历即可拿到修改后的所有数据 for form_entry in migration_form.entry_form_list: print(form_entry.id.data, form_entry.migrate.data) return redirect(url_for('migration_page', school_year_id=school_year_id)) # GET请求才用数据库数据填充表单 for entry in entries: migration_form.entry_form_list.append_entry( data={ "id": entry.id, "name": entry.name } ) # 给当前条目的选择字段设置选项 entry_form = migration_form.entry_form_list[-1] entry_form.school.choices = school_choices entry_form.student_class.choices = [('','')] return render_template('migration-elev.html', school_map=school_map,school_year=school_year, migration_form=migration_form)
3. 调整前端代码
去掉每个条目的重复hidden_tag(),避免CSRF token冲突:
<form action="" method="post"> {{ migration_form.hidden_tag() }} <table class="table table-striped table-dark" style="text-align: center;"> <thead class="thead-dark"> <tr> <th scope="col">ID</th> <th scope="col">Nume</th> <th scope="col">Scoala</th> <th scope="col">Clasa/ Grupa</th> <th scope="col">Transfer</th> </tr> </thead> <tbody> {% for form in migration_form.entry_form_list %} <tr> <td>{{form.id.data}}</td> <td>{{form.name}}</td> <td>{{form.school}}</td> <td>{{form.student_class}}</td> <td>{{form.migrate}}</td> </tr> {% endfor %} </tbody> </table> <p>{{ migration_form.submit(class_="btn btn-primary") }}</p> </form>
内容的提问来源于stack exchange,提问作者Robert-Nicolae Solca
相关产品推荐
相关产品推荐

