web-dev-qa-db-fra.com

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? '

34
jan

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

24
sp.

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
31
Elliott C

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()
13
getup8

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

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()
5
Liu Yue

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.

0
konstantin