使用从前一个字段中选择的值填充WTForms选择字段 [英] populate WTForms select field using value selected from previous field

查看:810
本文介绍了使用从前一个字段中选择的值填充WTForms选择字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

新的这个,试着建立一个应用程序,遵循着名的Flask教程,使用Flask-bootstrap,Flask-wtforms,Jinja等。

2选择字段和一个按钮。

$ $ $ $ p $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b 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事件? (这是我所要做的,或者有没有办法从视图功能?)

在此先感谢。


在这个例子中,我将使用州和县的概念(我使用了大量的地理数据,所以这是我构建的一个常见实现)。
$
$ b $ p
$ b $ p
$ p
$ b $ p
$ b $ p


$ p $类的PickCounty(Form):
form_name = HiddenField('Form Name')
state = SelectField('State:',validators = [DataRequired()],id ='select_state')
县= SelectField('县:',验证员= [DataRequired()],ID ='select_county')
提交= SubmitField('选择县!')


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

  @ app.route('/ pick_county / ,method = ['GET','POST'])
def pick_county():$ b $ form = PickCounty(form_name ='PickCounty')
form.state.choices = [(row。 ())
form.county.choices = [(row.ID,row.Name))for row.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':
#代码处理表单
flash('state:%s,county:%s'%(form.state.data,form.county.data))
return重定向(url_for('pick_county'))

一个Flask视图响应县的XHR请求: / b>

  @ app.route('/ _ get_counties /')
def _get_counties():
state = request对于row.query.filter_by(state = state).all()中的行,.args.get('state','01',type = str)
counties = [(row.ID,row.Name) ]
返回jsonify(县)

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

 < ; script charset =utf-8type =text / javascript> 

$(function(){

// jQuery选择2个选择框
var dropdown = {
state:$('#select_state '),
county:$('#select_county')
};

//调用load时更新
updateCounties();

//函数调用XHR并更新县下拉菜单
函数updateCounties(){
var send = {
state:dropdown.state.val()
};
dropdown.county.attr('disabled','disabled');
dropdown.county.empty();
$ .getJSON({{url_for('_ get_counties')}} ,函数(data){
data.forEach(function(item){
dropdown.county.append(
$('< option>',{
value :item [0],
text:item [1]
})
);
});
dropdown.county.remov eAttr('disabled');
});


//事件监听器状态下拉变化
dropdown.state.on('change',function(){
updateCounties();
});

});

< / script>


New to this, trying to build an app following a well known Flask tutorial, using Flask-bootstrap, Flask-wtforms, Jinja etc

I have a form with 2 select fields and a button.

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

I want only the first field to be pre-populated, and the other to get populated (on the client side?) based on the previous field's selected value.

In the template I try something like

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

which works ok (provided that I return the tuples list to populate the next field, using the proper javascript and route) but I want something like the following

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

which doesn't work (Error: wtforms.widgets.core.HTMLString object' has no attribute 'flags')

So, I guess my question really is: how do I implement an onChange event on this wtf form field? (And is this what I have to do, or is there a way from the view function?)

Thanks in advance.

解决方案

Here is an example implementation of this logic to work with WTForms native functionality. The trick here, is if you want to use WTForms validation, you need to instantiate the form with every possible value, then modify the available options in Javascript to show the filtered values based on the other select.

For this example I'm going to use the concept of States and Counties (I work with a lot of geo data so this is a common implementation I build).

Here's my form, I've assigned unique IDs to the important elements to access them from 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!')

Now, the Flask view to instantiate and process the form:

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

A Flask view to respond to XHR requests for Counties:

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

And, finally, the Javascript to place at the bottom of your Jinja template. I'm assuming because you mentioned Bootstrap, that you are using jQuery. I'm also assuming this is in line javascript so I'm using Jinja to return the correct URL for the endpoint.

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

这篇关于使用从前一个字段中选择的值填充WTForms选择字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆