Outils pour utilisateurs

Outils du site


Panneau latéral

Plan du Site:

python:flask:flask_wtf

Flask-WTF

Installation

pip install flask-wtf

Création du formulaire

forms.py
from flask_wtf import FlaskForm
from wtforms   import StringField
 
class RegisterForm(FlaskForm):
    name     = StringField('Nom', validators=[])
    password = PasswordField('Mot de passe', validators=[])
    submit   = SubmitField("S'inscrire")

Types de champs :

StringField Champ texte
EmailField
PasswordField
TextAreaField
FloatField (préférer DecimalField)
DateField Date avec calendrier
TimeField Heure
DecimalField Champ numérique décimal places=X
BooleanField
SelectField Liste dropdown choices=[ ('valeur', 'texte'), ('valeur2', 'texte2') ]
SubmitField

Utilisation du formulaire

app.py
from flask import Flask, render_template, redirect, url_for
from forms import RegisterForm;
 
app = Flask(__name__)
 
@app.route('/register', methods=['get', 'post'])
def register():
    form = RegisterForm()
 
    # Si le formulaire a été validé
    if form.validate_on_submit():
 
        # Afficher les nouvelles valeurs des champs
        print('Nom: ' + form.name.data)
        print('Mot de passe: ' + form.password.data)
 
        # Insert dans la DB
 
        # Flash message
 
        # Rediriger vers une autre page
        return redirect(url_for('index'))
 
    # Sinon, initialiser les valeurs des champs
    form.name.data     = 'Dupont'
    form.password.data = ''
 
    # Afficher le formulaire
    return render_template('register.html', form=form)

Intégration dans le template :

register.html
<form action="" method="post">
    {{ form.hidden_tag() }}
    <div class="form-group">
        {{ form.name.label(class="form-label") }}
        {{ form.name(class="form-input") }}
    </div>
    <div class="form-group">
        {{ form.password.label(class="form-label") }}
        {{ form.password(class="form-input") }}
    </div>
    {{ form.submit(class="btn btn-primary") }}
</form>

Ajout d'ID aux champs

Par défaut c'est le nom du champ, mais si on désire imposer un id on peut le passer au constructeur des champs :

forms.py
class MyForm(FlaskForm):
    nom  = StringField("Nom", id="edtNom")
    sexe = SelectField("Sexe", id="cmbSexe")

Validation

Ajout de contraintes de validation aux champs :

forms.py
from flask_wtf          import FlaskForm
from wtforms            import StringField
from wtforms.validators import DataRequired, Email, Length, ValidationError
 
class RegisterForm(FlaskForm):
    email    = StringField('Nom', validators=[DataRequired(), Email()])
    password = PasswordField('Mot de passe', validators=[DataRequired(), Length(min=4, max=12)])
    submit   = SubmitField("S'inscrire")
 
    # validation custom
    def validate_email(self, email):
        if email.data == "root@domain.com":
            raise ValidationError("Cet email est déjà enregistré")

Désactiver la validation par défaut du navigateur (ajouter novalidate) :

<form action="" method="post" novalidate>
 
    ...
 
</form>

Afficher les messages d'erreur de chaque champ :

register.html
<div class="form-group">
  {{ form.email.label(class="form-label") }}
  {{ form.email(class="form-input" }}
  {% for error in form.email.errors %}
    {{ error }}
  {% endfor %}
</div>
 
<div class="form-group">
  {{ form.password.label(class="form-label") }}
  {{ form.password(class="form-input" }}
  {% for error in form.password.errors %}
    {{ error }}
  {% endfor %}
</div>

Boutons Valider et Annuler

Classe formulaire :

...
 
class MyEditForm(FlaskForm):
 
    ...
 
    submit = SubmitField("Valider")
    cancel = SubmitField("Annuler")

Rendu dans le template (avec classes pour w3css :-) ) :

<form action="" method="post" class="...">
    ...
 
    <div class="w3-section">
        {{ form.submit(class="w3-button w3-round w3-blue") }}
        {{ form.cancel(class="w3-button w3-round w3-white w3-border") }}
    </div>
</form>

Traitement du formulaire dans le contrôleur :

form = MyEditForm()
 
...
 
if form.validate_on_submit():
 
    # Selon qu'on a validé ou annulé, les champs
    # "submit" et "cancel" valent True ou False
 
    # Donc on peut faire ceci :
    if form.submit.data:
        # On a cliqué sur le bouton "Valider"
        ...
    if form.cancel.data:
        # On a cliqué sur le bouton "Annuler"
        ...

Remplir un SelectField

Source: https://stackoverflow.com/questions/63209897/flask-wtforms-building-a-selectfield-from-a-table

EXEMPLE À TESTER :

from flask_wtf  import FlaskForm
from wtforms    import SelectField
from app.models import Categories
 
class MyForm(FlaskForm):
    # ...
    category = SelectField("Catégorie")
 
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.category.choices = Categories.query.all()

Remplissage via Javascript ⇒ désactiver la validation

Si la liste de choix est remplie via Javascript une fois le formulaire déjà créé, la validation échouera car la valeur sélectionnée ne fera jamais partie des choix possibles. Pour résoudre ce problème, il faut désactiver la validation pour ce champ :

class MyForm(FlaskForm):
    # ...
    category = SelectField("Catégorie", validate_choice=False)
python/flask/flask_wtf.txt · Dernière modification: 2023/01/08 08:13 par marclebrun