【问题标题】:How to populate a WTForms SelectField with an ajax call (i.e. Select2)?如何使用 ajax 调用(即 Select2)填充 WTForms SelectField?
【发布时间】:2017-02-11 22:53:55
【问题描述】:

我正在尝试使用 Flask + WTForms + Select2(ajax 调用)实现一个网络应用程序,但不幸的是没有取得很大成功。主要问题与我的 WTForms 类之一中的属性“选择”有关,因为我无法理解如何使用 ajax 调用填充选择菜单并让 WTForms 类管理这些数据。 这是我的解决方法:

class insertData(FlaskForm):
    ...
    feature_tag = SelectMultipleField(
        u'Features',
        choices=[(0, "")],
        coerce=int,
        render_kw={"multiple": "multiple"},
        id="feature_tag_sel2")
    ...

这是在模板中调用的:

<div class="col-sm-4">
    {{form.feature_tag}}
</div>

由 Select2 管理:

$("#feature_tag_sel2").select2({
    minimumInputLength: 2,
    ajax: {
      url: "/select/api/feature",
      dataType: 'json',
      data: function (params) {
          return { q: params.term };
      },
      processResults: function (data) {
          return {results: data};
      },
      cache: false
    }
});

最后,ajax 调用引用了这段代码:

@app.route('/select/api/feature')
def suggestion_feature():
    param = request.args.get('q', '')
    q = db.session.query(Feature).filter(Feature.nome_f.startswith(param)).all()
    value = [dict(id=i.id, text=i.nome_f) for i in q]
    return json.dumps(value)

当此代码运行时,无论选择的值是什么,validate_on_submit 都会出现错误:我可以从 Select2 菜单中选择许多值,但当然任何与 0 不同的值都不是有效的选择。然后我试图通过实现一个新的字段定义来阻止这个错误的传播:

class Select2MultipleField(SelectMultipleField):
    def pre_validate(self, form):
        # Prevent "not a valid choice" error
        pass

此代码有效,但无论如何它是一种解决方法。例如,当validate_on_submit 在表单中发现另一个错误并重新加载页面时,所有选定的值都会丢失。当我需要编辑数据时也会发生同样的情况。总而言之,这种解决方法让我失去了 WTForms 的许多优点。

因此问题是:是否有任何方法可以将 WTForms SelectField 与通过 ajax 调用检索到的数据集成?

2021 年 10 月 8 日编辑

对于仍然对此事感兴趣的任何人,我找到了以下解决方案:Flask-Select2。它很好地集成到代码中,几乎不需要修改。唯一的缺陷是它仅适用于 Select2 版本。 3(对于Select2当前版本的更新,有几点需要重写)

【问题讨论】:

  • 你找到解决办法了吗?

标签: ajax flask jquery-select2 flask-wtforms wtforms


【解决方案1】:

根据我对您的问题的理解,您的 ajax select2 与 WTForm 有两个问题。

  • 提交表单时选择无效
  • 和选定的值丢失和表单重新加载或错误

让我尝试如下解决它们:

提交表单时选择无效

对于第一个无效选择的问题,您可以告诉 wtf form 在提交表单时不要验证它,是的,您的解决方法!它也适用于我。

class Select2MultipleField(SelectMultipleField):
    def pre_validate(self, form):
        # Prevent "not a valid choice" error
        pass

选择的值丢失和表单重新加载或错误

引用您的问题

当 validate_on_submit 在表单和页面中发现另一个错误时 重新加载,所有选定的值都将丢失。当我发生同样的事情时 需要编辑数据。

是的,这确实按预期工作。首先,选择字段不包含任何选项,因为您的选择字段中的所有数据都是从远程 ajax 调用中获取的,这意味着当您使用 WTForm 创建时,选择字段没有提供任何数据选择在这里调用你的代码

class insertData(FlaskForm):
    ...
    feature_tag = SelectMultipleField(
        u'Features',
        choices=[(0, "")],
        coerce=int,
        render_kw={"multiple": "multiple"},
        id="feature_tag_sel2")
    ...

确实,您不必提供参数 choices,因为您的数据是从远程 ajax 调用中调用的,并且您已经解决了问题 Not a valid choice

要回答您的问题并解决第二个问题,您可以检查数据值是否附加到您的选择字段中,如下所示,并将其创建为您的选择字段的选项,如下所示:

<div class="col-sm-4">
    {{form.feature_tag}}
</div>

<script>
$(document).ready(function(){
$("#feature_tag_sel2").select2({
    minimumInputLength: 2,
    ajax: {
      url: "/select/api/feature",
      dataType: 'json',
      data: function (params) {
          return { q: params.term };
      },
      processResults: function (data) {
          return {results: data};
      },
      cache: false
    }
});

{# check if select field come with data previously selected #}
{% if form.feature_tag.data %}
{# trigger an ajax call to url with parameter of this value #}

        $.ajax("/select/api/feature?q={{form.feature_tag.data}}", {
                dataType: "json"
        }).done(
                function(data) { 
                    text = data.items[0].text // text returned from your url
                    id = data.items[0].id. // id returned from your url
                    
                    // created an option for the select field
                    var newOption = new Option(text, id, false, false)

                    $('#{{form.feature_tag.id}}').append(newOption).trigger('change')

                    $('#{{form.feature_tag.id}}').val(id).trigger('change')
    
                }
        );

{% endif %}


});

</script>

这样,您的选择字段在您查看或编辑它之前应该已经包含您之前选择的值:)

希望对您有所帮助!谢谢

【讨论】:

    猜你喜欢
    • 2021-01-30
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    相关资源
    最近更新 更多