我正在尝试使用Flask + WTForms + Select2(ajax调用)实现一个Web应用程序,但遗憾的是没有取得很大成功。主要问题是我的一个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)
当这段代码运行时,无论select的值是什么,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调用检索的数据集成?
答案 0 :(得分:0)
根据我对您的问题的了解,使用WTForm的ajax select2遇到了两个问题。
让我尝试解决以下问题:
对于第一个无效选择的问题,您可以告诉wtf表单不要在提交表单时对其进行验证,是的,解决方法!它也对我有用。
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>
这样,您的选择字段在查看或编辑它之前应该已经包含了先前选择的值:)
希望获得帮助!谢谢