0

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?

user1235777
  • 609
  • 7
  • 24
  • 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.default`or `form.page_size.data`, depending which solution you choose to set this form field value. – SivolcC Sep 18 '18 at 08:02
  • 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 Sep 18 '18 at 16:40

1 Answers1

2

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)
SivolcC
  • 3,258
  • 2
  • 14
  • 32