【问题标题】:SelectField in wtforms and added <option> via javascriptwtforms 中的 SelectField 并通过 javascript 添加了 <option>
【发布时间】:2013-12-31 11:47:25
【问题描述】:

我目前正在金字塔中的某个项目上工作,并且遇到了 wtforms SelectField 的问题。

我有 3 个 SelectField 字段:

  • car_make(例如,“audi”)
  • car_model(例如,“audi 80”)
  • car_version(例如,“AUDI 80 B4”)。

我可以在视图中加载的 car_make 选择。其余SelectFields的选择(CAR_MODEL,CAR_VERSION)我将通过Ajax/javaScript加载客户端(选择CAR_MAKE时,我可以选择CAR_MODEL等)。

>>>>

问题是,当我提交表单时,car_model 和 car_version 引发“无效选择”,因为(在 SelectField.pre_validation 第 431 行中)self.choices 为空。

我该如何解决这个问题?

【问题讨论】:

    标签: python pyramid wtforms


    【解决方案1】:

    您要求做的是让 WTForms 处理“级联选择”(让一个选择的有效字段由另一个字段的值确定)。确实没有使用内置字段的好方法。

    WTForms 中的 SelectField 没有为您提供“不验证提供的选择是否有效”的选项。您必须提供选择才能使该字段验证选择。

    作为shown in the docs,虽然您通常可以使用静态选项列表填充选项字段...

    class PastebinEntry(Form):
        language = SelectField(u'Programming Language', choices=[('cpp', 'C++'), ('py', 'Python'), ('text', 'Plain Text')])
    

    ...但是,由于您是动态提出选项,因此您需要在实例化表单后设置choices 属性。

    def edit_user(request, id):
        user = User.query.get(id)
        form = UserDetails(request.POST, obj=user)
        form.group_id.choices = [(g.id, g.name) for g in Group.query.order_by('name')]
    

    在上面的示例中,“group_id”的选项会动态填充到您的 Pyramid 视图中。所以,这就是你需要做的:你需要在你的视图中填写选项。这就是你如何解决car_make 的问题(尽管我认为在你的问题中你说car_make 没问题)。

    但是,您遇到的问题是无法确定 car_model 的有效选择,因为它们取决于 car_make 已经被解析和验证。 WTForms 并不能很好地处理这个问题(至少对于 SelectFields 而言),因为它假定所有字段都应该一次验证。换句话说,为了生成car_model 的有效选择列表,您首先需要验证car_make 的值,鉴于 SelectField 的工作原理,这并不容易。

    我认为这样做的最佳方法是创建一个扩展 SelectField 类型的新字段类型,但删除了验证:

    class NonValidatingSelectField(SelectField):
        def pre_validate(self, form):
            pass
    

    这种新类型会覆盖 pre_validate,它通常会进行检查以确定选择是否有效。

    如果您将它用于car_model,您将不再有错误。但是,这现在意味着您的字段实际上并没有被验证!要解决此问题,您可以在表单上添加 in-line validator...

    class MyForm(Form):
        car_make = SelectField(u'Make', choices=[...])
        car_model = NonValidatingSelectField(u'Model', choices=[])
    
        def validate_car_model(self, field):
            choices = query_for_valid_models(self.car_make.data)
            # check that field.data is in choices...
    

    你可能需要稍微调整一下才能让它完全按照你想要的方式工作,我还没有实际测试过它是否有效。

    【讨论】:

    • 我知道这是一个非常古老的话题。 NonValidatingSelectField 帮助了我很多。但是它缺少 len() 方法。如何验证jinja2格式的这个字段的长度?
    猜你喜欢
    • 2013-08-24
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    相关资源
    最近更新 更多