Comment définir une valeur par défaut pour un WTForms SelectField?
Lorsque j'essaie de définir la valeur par défaut d'un SelectField avec WTForms, je passe de la valeur au paramètre 'default' comme suit.
class TestForm(Form):
test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=2)
J'ai aussi essayé le suivant.
class TestForm(Form):
test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=(2, "Def"))
Ni définir le champ sélectionné par défaut à "Def". Cela fonctionne pour d'autres types de champs tels que TextField. Comment définissez-vous la valeur par défaut pour un SelectField? '
La première façon dont vous avez posté est correcte, et cela fonctionne pour moi. La seule explication pour que cela ne fonctionne pas peut être que vous utilisez une version plus ancienne de WTForms, cela a fonctionné pour moi sur 1.0.1
Je pense que ce problème est causé par l'attribut Field
de data
et qu'il remplace default
par quelque chose que WTForms ne comprend pas (par exemple, un objet de modèle de base de données - il attend une int
). Cela se produirait si vous aviez renseigné votre formulaire dans le constructeur de la manière suivante:
form = PostForm(obj=post)
la solution consiste à définir manuellement l'attribut data
une fois le formulaire rempli:
form = PostForm(obj=post)
form.category.data = (post.category.id
if page.category
else 0) # I make 0 my default
Il y a quelques façons de le faire. Votre premier extrait de code est en effet correct.
Si vous souhaitez le faire dans une vue de manière dynamique, vous pouvez également effectuer les opérations suivantes:
form = TestForm()
form.test_field.default = some_default_id
form.process()
Flask-WTF 0.14.2
utilisateur ici. Donc, cette réponse est pour quiconque a le même problème avec moi.
En gros, aucune des solutions précédentes ne fonctionne correctement avec form.validate_on_submit()
.
Le paramétrage de form.test_field.data
modifiera la valeur par défaut lors du chargement de la page, mais les données resteront identiques après validate_on_submit
(les modifications apportées au navigateur n'auront aucun effet).
Définir form.test_field.default
puis appeler form.process()
change également la valeur lorsque la page est chargée, mais validate_on_submit
échouera.
Voici la nouvelle façon de le faire:
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():
...
Ceci est un choices
paramètres avec SelectField
lorsque vous utilisez un int
, cela fonctionne comme suit:
test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
ou:
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()
Si vous utilisez flask_wtf et souhaitez définir une valeur par défaut pour différents SelectFields imbriqués dans une liste de champs comme celle-ci
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")
la solution consiste à écraser data
et non pas default
comme prévu.
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
Cette solution est fondamentalement similaire à Elliots answer above; Je voulais juste fournir une solution au cas plus complexe d'une FieldList. nikitz mentionné dans un commentaire, qu'il existe un effet secondaire: form.validate_on_submit()
ne fonctionne pas si vous écrasez data
! Vous pouvez créer une solution de contournement simple permettant de désactiver le remplacement de data
lors de l'appel de 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)
Ce n'est pas très élégant, mais ça marche.
PS: Ma réputation est trop basse pour pouvoir commenter directement la bonne réponse d'Elliot.