Вопрос

Here's the code I've got, and this works. MyForm is a form class, which defines only a RadioField. The RadioFieldhas no default specified here, because we don't know what items it will contain yet. my_form takes a list of items and creates a MyForm with the items added to the RadioField, and (crucially) picks the first item in the list to be the default.

from wtforms.fields.core import RadioField
from wtforms.validators import Required
from flask_wtf.form import Form

class MyForm(Form):
    """
    User chooses an item.
    """
    itemid = RadioField(validators=[Required()])

def my_form(items):
    """
    Returns a MyForm object populated with appropriate items.
    """
    form = MyForm()
    form.itemid.choices = [(item.id, item.name)
        for item in sorted(items, key=lambda i: i.order)]
    if items and form.itemid.data == u'None':
        # None ensures we don't overwrite submitted data
        form.itemid.data = items[0].id
    return form

The check and form.itemid.data == u'None' just smells really bad. The reason for this is that without that check, we overwrite submitted data. I.e. when we use the form like this...

@APP.route('/page_one', methods=['GET', 'POST'])
def page_one():
    form = my_form(dynamic_items())
    if form.validate_on_submit():
        itemid = form.itemid.data
        return redirect(url_for('page_two', itemid=itemid))
    else:
        return render_template('page_one.html', form=form)

... if we don't have that smelly check, we set the form data so as to set the default, but in the case that form.validate_on_submit() will pass because the user has submitted the form, by setting the default we've clobbered the actual data submitted by the user.

Of course, the obvious answer seems to be that my_form should just set the default, so the smelly check should just become:

if items:
    form.itemid.default = items[0].id

But that doesn't work, seemingly because form.itemid.data has no data, and that's what's actually used to construct the HTML.

So the question is: what is the right way to do this?

Это было полезно?

Решение

It looks like you are using my_form() for both form creation and form validation. Do you need to call:

form = my_form(create_items())

or can you simply use:

form = MyForm()
if form.validate_on_submit():
    ...

Then my_form() is only for form creation.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top