Ответ 1
Первый способ, который вы опубликовали, является правильным, и он работает для меня. Единственное объяснение, почему это не работает, может заключаться в том, что вы используете более старую версию WTForms, она работала для меня на 1.0.1
При попытке установить значение по умолчанию для 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?
Первый способ, который вы опубликовали, является правильным, и он работает для меня. Единственное объяснение, почему это не работает, может заключаться в том, что вы используете более старую версию WTForms, она работала для меня на 1.0.1
Я полагаю, что эта проблема вызвана атрибутом 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
Есть несколько способов сделать это. Ваш первый фрагмент кода действительно прав.
Если вы хотите сделать это в представлении динамически, вы также можете:
form = TestForm()
form.test_field.default = some_default_id
form.process()
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():
...
Это 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()
В случае, если вы используете 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: Моя репутация слишком низкая, чтобы прямо комментировать правильный ответ Эллиота.