动态选择字段不是WTForms的有效选项

55

我目前正在使用WTFORMS创建动态选择字段,但它从未提交,并在验证时出现以下错误。

Not a valid choice

我的领域是这样创建的:

area = SelectField()

在我的视图中,我正在从数据库中获取选项,代码如下:

form = MytestForm()
form.area.choices = [(a.id, a.name) for a in Area.objects.all()]

如果我创建静态选项,它就能正常工作。


这个问题已经有人提出过了,可以参考 https://github.com/wtforms/wtforms/issues/434 ,但还有其他类似的问题。这让人感到困惑。 - Wolfgang Fahl
4个回答

117

我猜测 Area.id 是一个 int - 当数据从客户端返回时,如果没有向 coerce 关键字参数传递可调用对象,WTForms 会将其视为 字符串,这是由 wtforms.fields.SelectField 构造函数处理的:

area = SelectField(coerce=int)

或者,如果你正在使用SQLAlchemy,你可以使用wtforms.ext.sqlalchemy.fields.QuerySelectField(如果你正在使用WTForms 3+,则使用wtforms_sqlalchemy):

area = QuerySelectField(query_factory=Area.objects.all,
                            get_pk=lambda a: a.id,
                            get_label=lambda a: a.name)

4
谢谢,这是强制问题,WTFORMS 默认转换为 unicode,但实际对象是 MongoDB 的 Object ID 类型。所以我将强制转换更改为创建一个 ObjectID 实例,现在已经验证成功。 - ismail
2
coerce=int 对我很有帮助。具体来说,我的问题是我的选择值恰好是整数0和1。我猜wtforms将其解释为False和True。然而,我的模型需要一个int。类Abc(基础): foo = Column(Integer)类AbcView(ModelView): form_overrides = { 'foo':SelectField, } form_args = { 'foo':{ 'choices':[(0,'unknown'),(1,'defcon 1')], 'coerce':int } } - coderfi
3
亲爱的 @SeanVieira,非常感谢您提供 wtforms.ext.sqlalchemy.fields.QuerySelectField。它让我省下了一辈子的时间 :) - Max
2
coerce=int - 对我来说有效,但对其他情况可能不适用。谢谢! - Worker
1
这是因为最新版本(3.0)从主包中移除了扩展并将其作为单独的包。https://github.com/wtforms/wtforms-sqlalchemy - Sean Vieira
显示剩余3条评论

7

以下是不需要使用QuerySelectField解决该问题的方法。

以下是我所采用的方法:

years = [(str(y), y) for y in reversed(range(1950, 2013))]
years.insert(0, ('','year'))
year = wt.SelectField(choices=years)

6

3.01版本的Pullrequest添加必要的参数:

 validate_choice=True

如果这个功能存在缺陷,并且已经有33k次阅读和2022年1月的52个赞,您可以关闭它。

 SelectField(coerce=int, validate_choice=False) 

使我感到非常高兴。

0

记得在设置表单类时同时加入可用选项。

class MyForm(FlaskForm):
    sel = SelectField(coerce=int, label="MyLabel", choices=my_choices)
    ....

选择可以是这样的:

my_choices = [x.id for x in get_products()]

当调用validate_on_submit()函数时,在脚本/wtforms/fields/core.py中的pre_validate函数中出现了异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接