0
votes

I'm having difficulty setting a default value in a WTForms SelectField based on a configuration value in my Flask app.

I have a forms.py file, which includes, in part:

class MySearchForm(FlaskForm):
    title = StringField('Title')
    page_size = SelectField('Entries/page', choices=[(10, "10"), (25, "25"), (50, "50"), (100, "100")], default=25)
    # other stuff

Even though it would seem to be the right place for this, I can't make the default a variable by passing the app config to the this file, because I get a "Working outside of application context" error. So I figure I have to do it with a dynamic default at runtime in my Flask view.

I've looked at a number of other StackOverflow questions about this—the main one seems to be How do you set a default value for a WTForms SelectField?—but I can't get any of them to work.

My routes.py for the search view is more or less like this:

form = MySearchForm(request.args)
if request.args: # if not, I display the search form
    if form.title.data:
        # construct relevant part of database query
    page_size = int(form.page_size.data)
    # other stuff: construct and execute DB query; render the view_results page

If, before the if request.args statement, I try form.page_size.default = current_app.config['PAGE_SIZE'] and then form.process(), as suggested, this wipes out anything else in the search form, so title won't go through. If I try form.page_size.data = current_app.config['PAGE_SIZE'], it doesn't set the config value as a default in the form, just in the result.

I have also tried the technique discussed in the Setting default value after initialization in SelectField flask-WTForms question, changing my form call to form = MySearchForm(request.args, page_size=current_app.config['PAGE_SIZE']). This also doesn't work correctly: On the initial call, the form has nothing selected (and in this specific case, thus shows the value of "10"); the configured value is correctly used for the search itself, but the form value of page_size remains at "10". Furthermore, actually selecting a value in the form has no effect; the configured value is used regardless of what the user selects in the form. (Similarly, manually changing page_size in the URL has the same behavior.)

How am I meant to do this?

1
Have you tried dabling with the coerce attribute for this SelectField? Also, check what is the type of app.config['PAGE_SIZE'], if it s either an int or an str and it matches the type of form.page_size.defaultor form.page_size.data, depending which solution you choose to set this form field value. - CloC
Ah, that was it! Yes, the value was an int, and all it took was coercing the str to it in the SelectField declaration. Thank you! I'm coming from Perl where these issues don't come up; this has bitten me a few times already. For the record: the second solution above, from the "Setting default value" question, worked. - user1235777

1 Answers

2
votes

You need to check the consistence of the types of the variables you want to set.

For that, in your SelectField, use the parameter coerce.

If the variable app.config['PAGE_SIZE'] is an int, you want to declare your form field like so :

page_size = SelectField('Entries/page',
    choices=[(10, "10"), (25, "25"), (50, "50"), (100, "100")],
    default=25,
    coerce=int)