使用从前一个字段中选择的值填充WTForms选择字段

时间:2016-12-19 22:36:03

标签: flask flask-wtforms flask-bootstrap

新手,尝试按照着名的Flask教程构建应用程序,使用Flask-bootstrap,Flask-wtforms,Jinja等

我有一个包含2个选择字段和一个按钮的表单。

class Form(FlaskForm): 
    school_year = SelectField('School year', choices=some_tuples_list)
    category = SelectField('Category', choices=[]) 
    submit = SubmitField('submit')

我想只预先填充第一个字段,并根据前一个字段的选定值填充另一个字段(在客户端?)。

在模板中我尝试了类似

的内容
{{ form.school_year(**{"onchange":"getCategories()"}) }}

哪个工作正常(假设我返回元组列表以填充下一个字段,使用正确的javascript和路由)但我想要类似下面的内容

{{ wtf.form_field(form.school_year(**{"onchange":"getCategories()"})) }}

哪个不起作用(错误:wtforms.widgets.core.HTMLString对象'没有属性'标志')

所以,我想我的问题是:如何在这个wtf表单字段上实现onChange事件? (这是我必须做的,或者是否有一种来自视图功能的方法?)

提前致谢。

3 个答案:

答案 0 :(得分:22)

以下是使用WTForms本机功能的此逻辑的示例实现。这里的技巧是,如果你想使用WTForms验证,你需要使用每个可能的值来实例化表单,然后修改Javascript中的可用选项以显示基于其他选择的过滤值。

对于这个例子,我将使用States和Counties的概念(我使用了大量的地理数据,因此这是我构建的常见实现)。

这是我的表单,我已经为从Javascript访问它们的重要元素分配了唯一的ID:

int main()

现在,Flask视图实例化并处理表单:

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!')

用于响应县的XHR请求的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'))

最后,将Javascript放在Jinja模板的底部。我假设是因为你提到了Bootstrap,你正在使用jQuery。我也假设这是在线javascript,所以我使用Jinja返回端点的正确URL。

@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)

答案 1 :(得分:0)

PJ Santoro的答案很棒。调用了load的更新,但事件监听器最初并不适用于我。原来我没有换掉'state'作为我自己的字段ID,因为我认为这是一个关键字,指的是该字段的状态! D'哦!因此,在寻找其他选项时,我发现这也有用,这可能对那里的人有用:

    // event listener to state dropdown change
$('#state').change(function() {
    updateCounties();
});

答案 2 :(得分:0)

abigperson的回答对我很有帮助。...最终。

要添加的唯一内容是,它们网站上当前的Bootstrap代码段使用了精简版的JQuery,这可以使我节省很多时间在屏幕上尖叫。苗条的版本不包含abigperson在其代码中使用的某些功能。

立即滑动完整版jQuery即可解决问题。

进一步阅读表明,Bootstrap在完整版的jQu​​ery上仍然可以正常运行。