Подтвердить что ты не робот

Как установить значение по умолчанию для WTForms SelectField?

При попытке установить значение по умолчанию для SelectField с помощью WTForms, я передаю значение параметру 'default', как это показано ниже.

class TestForm(Form):
  test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=2)

Я также пробовал следующее.

class TestForm(Form):
  test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=(2, "Def"))

Ни одно из полей по умолчанию не выбрано "Def.". Это работает для других видов полей, таких как TextField. Как установить значение по умолчанию для SelectField?

4b9b3361

Ответ 1

Первый способ, который вы опубликовали, является правильным, и он работает для меня. Единственное объяснение, почему это не работает, может заключаться в том, что вы используете более старую версию WTForms, она работала для меня на 1.0.1

Ответ 2

Я полагаю, что эта проблема вызвана атрибутом Field data, переопределяющим default тем, что WTForms не понимает (например, объект модели БД - он ожидает int). Это произойдет, если вы заполнили форму в конструкторе следующим образом:

form = PostForm(obj=post)

решение состоит в том, чтобы вручную установить атрибут data после заполнения формы:

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

Ответ 3

Есть несколько способов сделать это. Ваш первый фрагмент кода действительно прав.

Если вы хотите сделать это в представлении динамически, вы также можете:

form = TestForm()
form.test_field.default = some_default_id
form.process()

Ответ 4

Flask-WTF 0.14.2 пользователь здесь. Таким образом, этот ответ для всех, у кого есть аналогичная проблема со мной.

В принципе, ни одно из предыдущих решений не работает правильно с form.validate_on_submit().

Настройка form.test_field.data действительно изменит значение по умолчанию при загрузке страницы, но данные остаются неизменными после validate_on_submit (пользовательские изменения в браузере не влияют).

Настройка form.test_field.default, тогда вызов form.process() также изменит значение при загрузке страницы, но validate_on_submit завершится с ошибкой.

Вот новый способ сделать это:

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():
    ...

Ответ 5

Это choices с параметром SelectField, когда вы используете int, он работает следующим образом:

test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)

или

class TestForm(Form):
    test_select = SelectField("Test", coerce=int)

@app.route("/test")
def view_function():
    form = TestForm()
    form.test_select.choices = [(0, "test0"), (1, "test1")]
    form.test_select.default = 1
    form.process()

Ответ 6

В случае, если вы используете flask_wtf и хотите установить значение по умолчанию для различных SelectFields, вложенных в FieldList, как это

from flask_wtf import FlaskForm


class FormWithSelect(FlaskForm):
    my_select_field = SelectField(validators=[DataRequired()], coerce=int)


class FormWithMultipleSelects(FlaskForm):
    select_fields = FieldList(FormField(FormWithSelect), min_entries=1)
    submit = SubmitField(label="save all the select field values")

решение заключается в перезаписи data, а не по default как вы ожидаете.

def generate_my_form(my_data, overwrite_data=True):
    form = FormWithMultipleSelects(select_fields=[{
        "my_select_field": {
             "name": d["name"],
             # ...
        }
    } for d in my_data]))
    for n range(len(form.select_fields)):
        form.select_fields[n].my_select_field.choices = [(1,'foo'), (2,'bar')]
        # I wan't 'bar' to be the option selected by default
        # form.select_fields[n].my_select_field.default = 2  # has no effect!
        if overwrite_data:
            form.select_fields[n].my_select_field.data = 2 #  works

В основном это решение похоже на ответ Эллиота выше; Я просто хотел предложить решение для более сложного случая FieldList. Никит упомянул в комментарии, что есть побочный эффект, что form.validate_on_submit() не работает, если вы перезаписываете data. Вы можете создать простой обходной путь, где отключить перезапись data при вызове validate_on_submit().

 form_for_validation = generate_my_form(my_data, False)
 if form_for_validation.validate_on_submit():
      # do something with form_for_validation.data
 else:
     form_with_default_data = generate_my_form(my_data, True)
     render_template(..., form=form_with_default_data)

Это не супер элегантно, но это работает.

PS: Моя репутация слишком низкая, чтобы прямо комментировать правильный ответ Эллиота.