Flask表单报错:'UnboundField' object is not callable 求解
Flask表单报错:'UnboundField' object is not callable 解决方法
错误原因
你在AdditionResultsForm里直接用列表存储BooleanField和IntegerField,这种写法不符合FlaskForm的字段绑定机制——FlaskForm会通过元类处理类属性定义的字段,将其绑定到表单实例,但列表中的字段不会被元类处理,始终是未绑定的UnboundField对象,调用它自然会报错。
解决方法
方法1:使用FieldList(推荐)
FieldList是WTForms专门用来管理同类型字段集合的工具,能正确完成字段绑定:
修改表单类:
from flask_wtf import FlaskForm from wtforms import BooleanField, IntegerField, SubmitField, FieldList class AdditionResultsForm(FlaskForm): # 定义40个BooleanField,min_entries和max_entries确保数量固定 checkboxes_fields = FieldList(BooleanField(), min_entries=40, max_entries=40) # 定义50个IntegerField,默认值0 numb_fields = FieldList(IntegerField(default=0), min_entries=50, max_entries=50) submit = SubmitField('Отправить результат')
对应模板修改:
注意FieldList的索引从0开始,和enumerate(tasks)的i对应,同时修正else分支的语法错误:
<div> <form method="POST"> {{ form.csrf_token }} <fieldset> <legend>{{subject.capitalize()}}</legend> <div class="grid"> {% for i, task in enumerate(tasks)%} {% if task == 1 %} <div> <label for="{{ form.checkboxes_fields[i].id }}">№{{i + 1}}</label> {{ form.checkboxes_fields[i]() }} </div> {% else %} <div> <label for="{{ form.numb_fields[i].id }}">№{{i + 1}}</label> {{ form.numb_fields[i]() }} </div> {% endif %} {% endfor %} </div> {{ form.submit(class="btn btn-primary") }} </fieldset> </form> </div>
方法2:动态添加字段
在表单的__init__方法里动态给实例绑定字段:
修改表单类:
from flask_wtf import FlaskForm from wtforms import BooleanField, IntegerField, SubmitField class AdditionResultsForm(FlaskForm): submit = SubmitField('Отправить результат') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 动态添加40个BooleanField for idx in range(40): field_name = f"checkbox_{idx}" setattr(self, field_name, BooleanField(f"{idx+1}")) # 动态添加50个IntegerField for idx in range(50): field_name = f"number_{idx}" setattr(self, field_name, IntegerField(f"{idx+1}", default=0))
对应模板修改:
通过字段名获取对应字段:
<div> <form method="POST"> {{ form.csrf_token }} <fieldset> <legend>{{subject.capitalize()}}</legend> <div class="grid"> {% for i, task in enumerate(tasks)%} {% if task == 1 %} <div> <label for="checkbox_{{i}}">№{{i + 1}}</label> {{ form['checkbox_{}'.format(i)]() }} </div> {% else %} <div> <label for="number_{{i}}">№{{i + 1}}</label> {{ form['number_{}'.format(i)]() }} </div> {% endif %} {% endfor %} </div> {{ form.submit(class="btn btn-primary") }} </fieldset> </form> </div>
额外注意
你模板的else分支原本写的{{ for number in form.checkboxes_fields }}是语法错误,已在上述修正中替换为对应IntegerField的渲染代码。
内容的提问来源于stack exchange,提问作者EugeneSuper Bichkov
相关产品推荐
相关产品推荐

