How do you set a default value for a WTForms SelectField?

I believe this problem is caused by the Field's data attribute overriding the default with something that WTForms doesn't understand (e.g. a DB model object -- it expects an int). This would happen if you have populated your form in the constructor like so:

form = PostForm(obj=post)

the solution is to manually set the data attribute after the form has been populated:

form = PostForm(obj=post)
form.category.data = (post.category.id
                      if page.category
                      else 0) # I make 0 my default

Flask-WTF 0.14.2 user here. So this answer is for anyone who have similar problem with me.

Basically, none of the previous solutions function properly with form.validate_on_submit().

Setting form.test_field.data will indeed change the default value when the page is loaded, but the data stays the same after validate_on_submit (user changes in browser has no effect).

Setting form.test_field.default then call form.process() also changes the value when the page is loaded, but validate_on_submit will fail.

Here is the new way to do it:

class TestForm(Form):
    test_field = SelectField("Test", choices=[(0, "test0"), (1, "test1")])

@app.route("/test")
def view_function():
    form = TestForm(test_field=1)
    if form.validate_on_submit():
        ...

The first way you posted is correct, and it works for me. The only explanation for it not working can be that you are running an older version of WTForms, it worked for me on 1.0.1