I am using the latest version of flask, wtforms and Flask-WTForms.
I have a page that displays a form and one is a select box with option option called "A".
When the app starts all is well. In a another form I add a record called "B".
Now, the form I want should have the select box wth options A and B bot only option A is available. I have to kill uWSGI and restart to get wtforms to refresh the data.
So, what am I missing? How to I get wtforms to refresh data?
Here s how I create the form where getAgencyList returns a list of options to add to the select box. In another dialogue I add an agency and the agency list should be updated without having to restart the app:
class createUser(Form):
"""
Users are given a default password
"""
first_name = TextField()
last_name = TextField()
email = TextField('Email', [validators.Length(min=6, max=120), validators.Email()])
user_role = SelectField(u'User Role', choices=[('1', 'User'), ('2', 'Admin')])
org_role = SelectField(u'User Role', choices=[('1', 'Agency'), ('2', 'Advertiser'),('3', 'Admin')])
agency = SelectField(u'Agency', choices=getAgencyList())
The problem is that getAgencyList()
is called upon definition of the class. So whatever that function returns at that time will be it's data. In order to update the list information you have to somehow run getAgencyList
during instantiation. In order to do this you can use a not very obvious fact about wtforms that allows you to add choices to a particular field. The documentation is here just look for the subsection that is titled "Select fields with dynamic choice values". Here's a sample of code that should work.
class CreateUserForm(Form):
first_name = TextField()
last_name = TextField()
email = TextField('Email',
[validators.Length(min=6, max=120), validators.Email()])
user_role = SelectField(u'User Role',
choices=[('1', 'User'), ('2', 'Admin')])
org_role = SelectField(u'User Role',
choices=[('1', 'Agency'), ('2', 'Advertiser'),('3', 'Admin')])
agency = SelectField(u'Agency')
@classmethod
def new(cls):
# Instantiate the form
form = cls()
# Update the choices for the agency field
form.agency.choices = getAgencyList()
return form
# So in order to use you do this ...
@app.route('/someendpoint')
def some_flask_endpoint():
# ... some code ...
form = CreateUserForm.new()
# That should give you a working CreateUserForm with updated values.
# ... some more code to validate form probably...
A simple solution would be to fetch the options to be displayed from the database and then overwrite the Form Class with those:
eg:
def get_agencies():
agency_list = []
# get the Agencies from the database - syntax here would be SQLAlchemy
agencies = Agency.query.all()
for a in agencies:
# generate a new list of tuples
agency_list.append((a.id,a.name))
return agency_list
@app.route('/somewhere',methods=['POST'])
def somewhere():
form = createUser()
# overwrite the choices of the Form Class
form.agency.choices = get_agencies()
# here goes the rest of code - like form.validate_on_submit()
...
return render_template('create_user.html', form=form)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With