Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask and WTForms - how to get wtforms to refresh select data

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())
like image 446
Tampa Avatar asked Aug 29 '12 04:08

Tampa


2 Answers

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...
like image 70
ravenac95 Avatar answered Nov 18 '22 12:11

ravenac95


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)
like image 1
Thomas Krickl Avatar answered Nov 18 '22 12:11

Thomas Krickl