Dynamic choices WTForms Flask SelectField
I'm trying to pass userID variable to WTForms with FlaskForms. First I'll show code that works fine and then what I need to modify(that the part I don't know how). I'm adding new Name associated with some group.
FlaskForm model:
class AddName(FlaskForm):
name =StringField('Device name', validators=[InputRequired(),Length(min=4, max=30)])
groupID = SelectField('Payload Type', choices=[(1,"Group1"),(2,"Group2")], validators=[InputRequired])
View model:
@app.route('/dashboard/addname', methods=['GET', 'POST'])
def addname():
form=AddName()
if form.validate_on_submit():
name=Name(form.name.data,form.groupID.data)
db.session.add(name)
db.session.commit()
return "New name added"
Template:
<form method="POST" action="/dashboard/addname">
<h2>Add name</h2>
{{ form.hidden_tag() }}
{{ wtf.form_field(form.name) }}
{{ wtf.form_field(form.groupID) }}
<button type="submit">Add name</button>
</form>
I see correct list in dropdown, and on submit gives me correct numbers.
Task: I need to pass different list based on current_user.userID. I'm forming list using SQLAlchemy, by making query from table from DB, so My Flask view is:
@app.route('/dashboard/addname', methods=['GET', 'POST'])
def addname():
available_groups=db.session.query(Groups).filter(Groups.userID == currend_user.userID).all()
#Now forming the list of tuples, so it's ok for SelectField
groups_list=[(i.groupID, i.groupName) for i in available_groups]
form=AddName()
if form.validate_on_submit():
name=Name(form.name.data,form.groupID.data)
db.session.add(name)
db.session.commit()
return "New name added"
- How can i pass my groups_list to the form? I tried to implement forming procedure in the FlaskForm model, but it doesn't see current_user object
- Do I need to transform groupID to string and then back to int when I need to pass it to the SelectField like tuples?
Solution 1:
The main idea here is to assign the choices list to the field after instantiation. To do so you need to use argument coerce=int
. The coerce keyword arg to SelectField says that we use int() to coerce form data. The default coerce is unicode().
Correct FormModel:
class AddName(FlaskForm):
name =StringField('Device name', validators=[InputRequired(),Length(min=4, max=30)])
groupID = SelectField('Payload Type', coerce=int, validators=[InputRequired])
Correct View:
@app.route('/dashboard/addname', methods=['GET', 'POST'])
def addname():
available_groups=db.session.query(Groups).filter(Groups.userID == currend_user.userID).all()
#Now forming the list of tuples for SelectField
groups_list=[(i.groupID, i.groupName) for i in available_groups]
form=AddName()
#passing group_list to the form
form.groupID.choices = groups_list
if form.validate_on_submit():
name=Name(form.name.data,form.groupID.data)
db.session.add(name)
db.session.commit()
return "New name added"