使用前一个字段的值 select 填充 WTForms select 字段
populate WTForms select field using value selected from previous field
新手,尝试按照著名的 Flask 教程构建应用程序,使用 Flask-bootstrap、Flask-wtforms、Jinja 等
我有一个包含 2 个 select 字段和一个按钮的表单。
class Form(FlaskForm):
school_year = SelectField('School year', choices=some_tuples_list)
category = SelectField('Category', choices=[])
submit = SubmitField('submit')
我只想预填充第一个字段,并根据前一个字段的 selected 值填充另一个字段(在客户端?)。
在模板中我尝试了
{{ form.school_year(**{"onchange":"getCategories()"}) }}
工作正常(前提是我 return 元组列表使用正确的 javascript 和路由填充下一个字段)但我想要类似下面的东西
{{ wtf.form_field(form.school_year(**{"onchange":"getCategories()"})) }}
这不起作用(错误:wtforms.widgets.core.HTMLString 对象'没有属性 'flags')
所以,我想我的问题确实是:如何在这个 wtf 表单字段上实现 onChange 事件? (这是我必须做的,还是从视图函数有办法?)
提前致谢。
这里是一个使用 WTForms 本机功能的逻辑实现示例。这里的技巧是,如果你想使用 WTForms 验证,你需要用每个可能的值实例化表单,然后修改 Javascript 中的可用选项以显示基于其他 select 的过滤值。
对于这个例子,我将使用州和县的概念(我处理大量地理数据,所以这是我构建的常见实现)。
这是我的表单,我已经为重要元素分配了唯一 ID,以便从 Javascript:
访问它们
class PickCounty(Form):
form_name = HiddenField('Form Name')
state = SelectField('State:', validators=[DataRequired()], id='select_state')
county = SelectField('County:', validators=[DataRequired()], id='select_county')
submit = SubmitField('Select County!')
现在,实例化和处理表单的 Flask 视图:
@app.route('/pick_county/', methods=['GET', 'POST'])
def pick_county():
form = PickCounty(form_name='PickCounty')
form.state.choices = [(row.ID, row.Name) for row in State.query.all()]
form.county.choices = [(row.ID, row.Name) for row in County.query.all()]
if request.method == 'GET':
return render_template('pick_county.html', form=form)
if form.validate_on_submit() and request.form['form_name'] == 'PickCounty':
# code to process form
flash('state: %s, county: %s' % (form.state.data, form.county.data))
return redirect(url_for('pick_county'))
响应县的 XHR 请求的 Flask 视图:
@app.route('/_get_counties/')
def _get_counties():
state = request.args.get('state', '01', type=str)
counties = [(row.ID, row.Name) for row in County.query.filter_by(state=state).all()]
return jsonify(counties)
最后,Javascript 放在 Jinja 模板的底部。我假设因为您提到了 Bootstrap,所以您正在使用 jQuery。我还假设这是 javascript 行,所以我使用 Jinja return 端点的正确 URL。
<script charset="utf-8" type="text/javascript">
$(function() {
// jQuery selection for the 2 select boxes
var dropdown = {
state: $('#select_state'),
county: $('#select_county')
};
// call to update on load
updateCounties();
// function to call XHR and update county dropdown
function updateCounties() {
var send = {
state: dropdown.state.val()
};
dropdown.county.attr('disabled', 'disabled');
dropdown.county.empty();
$.getJSON("{{ url_for('_get_counties') }}", send, function(data) {
data.forEach(function(item) {
dropdown.county.append(
$('<option>', {
value: item[0],
text: item[1]
})
);
});
dropdown.county.removeAttr('disabled');
});
}
// event listener to state dropdown change
dropdown.state.on('change', function() {
updateCounties();
});
});
</script>
PJ Santoro 的回答很棒。调用了加载更新,但事件侦听器起初对我不起作用。原来我没有将 'state' 换成我自己的字段 ID,因为我认为这是一个引用字段状态的关键字!哦!所以在寻找其他选择时,我发现这也有效,可能对那里的人有用:
// event listener to state dropdown change
$('#state').change(function() {
updateCounties();
});
新手,尝试按照著名的 Flask 教程构建应用程序,使用 Flask-bootstrap、Flask-wtforms、Jinja 等
我有一个包含 2 个 select 字段和一个按钮的表单。
class Form(FlaskForm):
school_year = SelectField('School year', choices=some_tuples_list)
category = SelectField('Category', choices=[])
submit = SubmitField('submit')
我只想预填充第一个字段,并根据前一个字段的 selected 值填充另一个字段(在客户端?)。
在模板中我尝试了
{{ form.school_year(**{"onchange":"getCategories()"}) }}
工作正常(前提是我 return 元组列表使用正确的 javascript 和路由填充下一个字段)但我想要类似下面的东西
{{ wtf.form_field(form.school_year(**{"onchange":"getCategories()"})) }}
这不起作用(错误:wtforms.widgets.core.HTMLString 对象'没有属性 'flags')
所以,我想我的问题确实是:如何在这个 wtf 表单字段上实现 onChange 事件? (这是我必须做的,还是从视图函数有办法?)
提前致谢。
这里是一个使用 WTForms 本机功能的逻辑实现示例。这里的技巧是,如果你想使用 WTForms 验证,你需要用每个可能的值实例化表单,然后修改 Javascript 中的可用选项以显示基于其他 select 的过滤值。
对于这个例子,我将使用州和县的概念(我处理大量地理数据,所以这是我构建的常见实现)。
这是我的表单,我已经为重要元素分配了唯一 ID,以便从 Javascript:
访问它们class PickCounty(Form):
form_name = HiddenField('Form Name')
state = SelectField('State:', validators=[DataRequired()], id='select_state')
county = SelectField('County:', validators=[DataRequired()], id='select_county')
submit = SubmitField('Select County!')
现在,实例化和处理表单的 Flask 视图:
@app.route('/pick_county/', methods=['GET', 'POST'])
def pick_county():
form = PickCounty(form_name='PickCounty')
form.state.choices = [(row.ID, row.Name) for row in State.query.all()]
form.county.choices = [(row.ID, row.Name) for row in County.query.all()]
if request.method == 'GET':
return render_template('pick_county.html', form=form)
if form.validate_on_submit() and request.form['form_name'] == 'PickCounty':
# code to process form
flash('state: %s, county: %s' % (form.state.data, form.county.data))
return redirect(url_for('pick_county'))
响应县的 XHR 请求的 Flask 视图:
@app.route('/_get_counties/')
def _get_counties():
state = request.args.get('state', '01', type=str)
counties = [(row.ID, row.Name) for row in County.query.filter_by(state=state).all()]
return jsonify(counties)
最后,Javascript 放在 Jinja 模板的底部。我假设因为您提到了 Bootstrap,所以您正在使用 jQuery。我还假设这是 javascript 行,所以我使用 Jinja return 端点的正确 URL。
<script charset="utf-8" type="text/javascript">
$(function() {
// jQuery selection for the 2 select boxes
var dropdown = {
state: $('#select_state'),
county: $('#select_county')
};
// call to update on load
updateCounties();
// function to call XHR and update county dropdown
function updateCounties() {
var send = {
state: dropdown.state.val()
};
dropdown.county.attr('disabled', 'disabled');
dropdown.county.empty();
$.getJSON("{{ url_for('_get_counties') }}", send, function(data) {
data.forEach(function(item) {
dropdown.county.append(
$('<option>', {
value: item[0],
text: item[1]
})
);
});
dropdown.county.removeAttr('disabled');
});
}
// event listener to state dropdown change
dropdown.state.on('change', function() {
updateCounties();
});
});
</script>
PJ Santoro 的回答很棒。调用了加载更新,但事件侦听器起初对我不起作用。原来我没有将 'state' 换成我自己的字段 ID,因为我认为这是一个引用字段状态的关键字!哦!所以在寻找其他选择时,我发现这也有效,可能对那里的人有用:
// event listener to state dropdown change
$('#state').change(function() {
updateCounties();
});