Update later... I finally get my problem solved. I just wonder if there is a way doing this more elegant?
I'm at the very beginning of programing with Python3
, Flask
and Jquery
.
What I aim to do is that making one SelectField
change its value(s) based on another SelectField
's option. Just like, when I choose US as country, then automatically load states(say, New York/Washington, D.C./...) from database with ajax help.
Now I could get data using ajax call, which means I could see the response in debug mode of Browser. I just do not know how to fill the specific SelectField
with the response data. Below is the relevant code snippet. Thanks in advance for your time.
choose.html
<html>
<head>...</head>
<body>
...
<div class="row">
<form action="{{url_for('some_view_function')}}" method="post">
...
<div class="col-md-4 col-sm-4 col-xs-12">
{{ form.country(class="form-control select2_single") }}
</div>
<div class="col-md-4 col-sm-4 col-xs-12">
{{ form.state(class="form-control select2_single") }}
</div>
...
</form>
</div>
...
<script>
$(document).ready(function(){
$("#country").change(function(){
country_id=$("#country").val();
$.get("{{ url_for('get_states_by_country') }}",
{"country_id":country_id},
function(data, status){
if (status == 'success') {
// What should I do here with data?
}
});
});
});
</script>
</body>
</html>
view_function.py
@app.route('/obtain/states', methods={'GET', 'POST'})
def get_states_by_country():
country_id = request.args.get("country_id")
states = State.query.filter_by(
country_id=country_id
)
return jsonify(
{int(s.state_id): s.state_name
for s in states}
)
form.py
class LinkChooseForm(Form):
country = SelectField(label='Country')
state = SelectField(label='State')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.country.choices = [(c.id, c.name) for c in Country.query.all()]
self.state.choices = [] # I leave it empty when initiating
Update-1:
The data is json
format. Mock data below. The key
would be value
of <option>
, and value
would be text
of <option>
.
{
"bash", "desc_for_bash",
"csh", "desc_for_csh",
...
}
Update-2:
With @Deepak's help, I finally solved this problem. The issue I mentioned under @Deepak's answer(form doesn't accept select option) is post wrong. In fact, form
does accept the select option on my html
page. I debug that and find out I miss to reset state.choices
in my action function. You could notice that I leave the state.choices
empty when initiating form object. But flask-wtf
would validate that if your choice on page is one of state.choices
. Which is obviously not, since I leave it empty. So I must reset it with request.form.get('state')
to meet flask-wtf
's validation. Below is submit function.
@app.route('/test', methods={'GET', 'POST'})
def some_view_function():
form = LinkChooseForm(**request.view_args)
if request.method == 'POST':
# The most important part here.
form.state.choices = [(request.form.get('state'), "")]
if form.validate_on_submit():
action_entity = ActionEntity()
action_entity.do(form)
return redirect(url_for('.another_view_function'))
else:
# reset it as empty again
form.state.choices = []
return render_template(
'result.html',
form=form
)
SelectFields
with specific business meaning, notcountry
andstate
. - Light.G