Outils pour utilisateurs

Outils du site


dev:python:flask:flask_formulaires_wtforms

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
dev:python:flask:flask_formulaires_wtforms [2025/03/08 14:09] yoanndev:python:flask:flask_formulaires_wtforms [2026/04/12 10:26] (Version actuelle) yoann
Ligne 1: Ligne 1:
-{{tag>dev python web formulaire}}+{{tag>dev python flask web formulaire}}
  
-:TODO:+:TODO_DOCUPDATE:
  
-====== Python Gestion des formulaires via Flask-WTF ======+====== Flask Créer des formulaires via Flask-WTF ======
  
 [[https://wtforms.readthedocs.io/en/3.2.x/|WTForms]] est une bibliothèque Python permettant de gérer des formulaires web via des Classes et objets en POO. [[https://wtforms.readthedocs.io/en/3.2.x/|WTForms]] est une bibliothèque Python permettant de gérer des formulaires web via des Classes et objets en POO.
Ligne 21: Ligne 21:
 python3 -m venv venv python3 -m venv venv
 source venv/bin/activate source venv/bin/activate
-pip install Flask Flask-WTF+pip install Flask Flask-WTF email_validator
  
 # Création de l'application Flask # Création de l'application Flask
Ligne 88: Ligne 88:
  
   * Pour créer un formulaire, on définit une classe héritant de **FlaskForm**.   * Pour créer un formulaire, on définit une classe héritant de **FlaskForm**.
-  * Chaque attribut est un champ de formulaire héritant de la classe de base ''wtforms.fields.Field'' ;+  * Chaque attribut de la notre classe représentant un champ de formulaire sera un objet héritant de la classe de base ''wtforms.fields.Field'' ; 
 +  * L'objet de type formulaire est instancié et traité par le contrôleur (la fonction associée à la route Flask) et transmis à la vue (le template).
  
-Le constructeur de la classe de base ''wtforms.fields.Field'' accepte notamment les paramètres :+ 
 +<code python> 
 +from flask_wtf import FlaskForm 
 +from wtforms import EmailField, SubmitField 
 +from wtforms.fields.simple import BooleanField 
 + 
 +class NewsLetterForm(FlaskForm): 
 + 
 +    email = EmailField(label='Email'
 +    news_letter = BooleanField(label="S'abonner à la news letter"
 +    submit_button = SubmitField(label='Valider'
 +</code> 
 + 
 +Comme illustré ci-dessus, le constructeur des objets héritant de la classe de base ''wtforms.fields.Field'' accepte notamment les paramètres :
   * ''label'' : le label associé au champ ;   * ''label'' : le label associé au champ ;
-  * ''default'' : valeur par défaut du champ, peut être un callable ;+  * ''default'' : valeur par défaut du champ, peut être un ''callable'' (un nom de fonction exécutable) ;
   * ''description'' : une description associée au champ, utilisée généralement par les help text ;   * ''description'' : une description associée au champ, utilisée généralement par les help text ;
-  * ''filters'' : tableau, séquence de callables (fonctions) exécutées pour traiter les données du champ ; +  * ''filters'' : tableau, séquence de ''callable'' exécutés pour traiter les données du champ ; 
-  * ''validators'' : tableau de validators appelés lors de l'exécution de  ''validate''.+  * ''validators'' : tableau de validators appelés lors de l'exécution de ''validate''.
  
  
 La liste exhaustive des paramètres est disponible dans la documentation [[https://wtforms.readthedocs.io/en/3.2.x/fields/#basic-fields]] La liste exhaustive des paramètres est disponible dans la documentation [[https://wtforms.readthedocs.io/en/3.2.x/fields/#basic-fields]]
  
-Les champs élémentaires disponibles : 
  
-^ BooleanField | Champ de type checkbox  |+Quelques objets représentant les champs de base des formulaires :
  
 +  * **StringField** : Champ type texte ;
 +  * **TextAreaField** :
 +  * **SelectField** : 
 +  * **BooleanField** : Champ de type checkbox ;
 +  * **PasswordField**  : Champ de saisie de mot de passe
 +  * **HiddenField** : Champ masqué ;
 +  * **SubmitField** : Bouton soumission du formulaire ;
 +
 +
 +Champs plus spécifiques :
 +  * **EmailField** ;
 +  * **TelField** ;
 +  * **URLField** ;
 +  * **TimeField** ;
 +  * **ColorField** ; 
 +  * **IntegerField** : Saisie d'un nombre entier;
 +  * **IntegerRangeField**
 +  * **FloatField** 
 +  * **DecimalRangeField** ;
 +  * **FileField**
 +
 +
 +
 +===== Les filtres =====
 +
 +Les filtres (filters) permettent de traiter, en amont de la validation, les valeurs saisies par l'utilisateur. On les utilise couramment pour :
 +
 +  * Retirer les espaces en début et fin de saisie ;
 +  * Passer la saisie en majuscule, en minuscule ;
 +  * Arrondir les valeurs décimales etc.
  
  
 <code python> <code python>
 +from flask_wtf import FlaskForm
 +from wtforms import StringField
 +
 +class RegisterForm(FlaskForm):
 +
 +    lastname = StringField(label='Nom', default="DOE",
 +                           filters=[str.strip, str.upper],
 +                           description="Champ de saisie de votre nom")
 +
 +</code>
 +
 +Ci-dessus, on utilise les filtres pour retirer les espaces autour de la saisie et la passer en majuscules.
 +
 +===== Les validateurs =====
 +
 +Les **validators** permettent de contrôler la saisie de l'utilisateur. On les importe depuis ''wtforms.validators''.
 +
 +
 +<code python>
 +from flask_wtf import FlaskForm
 +from wtforms import StringField
 +from wtforms.validators import InputRequired, Email
 +
 +class RegisterForm(FlaskForm):
 +
 +    email = StringField(label='Email', validators=[InputRequired(),Email()])
 +</code>
 +
 +Ici on instancie deux validators pour contraindre la saisie de l'utilisateur :
 +  * Le champs ne doit pas être vide,
 +  * La saisie doit respecter le formalisme d'un email.
 +
 +Dans ce cas, peut également utiliser la classe ''EmailField''
 +
 +<code python>
 +from flask_wtf import FlaskForm
 +from wtforms import EmailField
 +
 +
 +class RegisterForm(FlaskForm):
 +
 +    email = EmailField(label='Email')
 +</code>
 +
 +Il existe de nombreux validators citons par exemple **InputRequired**, **Length**, **Email**, **URL**, **NumberRange**, **IPAddress**, **MacAddress**, **Regexp**, etc. Il est possible de définir ses propres validators.
 +
 +  * Ici la [[https://wtforms.readthedocs.io/en/3.2.x/validators/|documentation exhaustive des validators WTForms]]
 +
 +
 +
 +===== Rendu du formulaire dans le template =====
 +
 +Du côté du template, on peut s'appuyer sur des macros Jinja2 pour factoriser le code en charge de produire le HTML du formulaire :
 +
 +<code html _helpers.html>
 +{#
 +Produire le code HTML d'un champ de formulaire.
 +#}
 +
 +{% macro render_field_with_div(field) %}
 +<div>
 +    {{ field.label }} {{ field(**kwargs)|safe }}
 +        {% if field.errors %}
 +            <ul class=errors>
 +            {% for error in field.errors %}
 +                <li>{{ error }}</li>
 +            {% endfor %}
 +            </ul>
 +    {% endif %}
 +</div>
 +{% endmacro %}
 +</code>
 +
 +Une fois la macro définie, on peut l'utiliser dans les différents modèles produisant des formulaires.
 +
 +<code html>
 +<div>
 +    {% from "_helpers.html" import render_field_with_div %}
 +    <form method="POST" action="{{ url_for('frontend.parse_contact_form') }}">
 +        {{ form.csrf_token }}
 +        {{ render_field_with_div(form.first_name) }}
 +        {{ render_field_with_div(form.last_name) }}
 +        {{ render_field_with_div(form.email) }}
 +        {{ render_field_with_div(form.subject) }}
 +        {{ render_field_with_div(form.message) }}
 +        {{ render_field_with_div(form.submit_button) }}
 +    </form>
 +</div>
 +</code>
 +
 +===== Validation =====
 +
 +C'est la fonction contrôleur de la vue qui se charge de valider le formulaire retourné en méthode POST.
 +
 +<code python [highlight_lines_extra="7"] >
 +@frontend_bp.post('/contact')
 +def parse_contact_form():
 +    """
 +    Analyse le formulaire de contact renseigné par l'utilisateur.
 +    """
 +    from app.services.forms import ContactForm
 +    form = ContactForm()
 +    if form.validate_on_submit():
 +        # Les valeurs saisies sont correctes
 +        return redirect(url_for('frontend.supply_home'))
 +    else:
 +        # Reafficher le formulaire pour permettre à l'utilisateur de corriger
 +        flash('Vérifier les valeurs saisies')
 +        return render_template('contact.html', form=form)
 +</code>
 +
 +<note>
 +L'exemple montre bien qu'il n'est pas nécessaire de passer l'objet ''request.form'' à l'instanciation du formulaire ContactForm (héritant de FlaskForm) : il sera automatiquement chargé.
 +</note>
 +
 +La méthode ''validate_on_submit()'' vérifie que la méthode POST est utilisée et que le la saisie est valide.
 +
 +
 +===== Débogages =====
 +
 +==== Échec systématique de la validation ====
 +
 +Lors du traitement du formulaire dans la vue, celui-ci est systématiquement considéré comme invalide.
 +
  
 +Lorsqu'un formulaire hérite de ''FlaskForm'', il contient systématiquement un **jeton CSRF** (processus de sécurité). Celui-ci doit être rendu dans le template. 
 + 
 +<code html>
 +<form method="POST" action="/">
 +    {{ form.csrf_token }}
 +    
 +    <!-- vos autres champs ici -->
 +     
 +    <input type="submit" value="Go">
 +</form>
 </code> </code>
  
 ===== Références ===== ===== Références =====
  
-  * [[https://flask-wtf.readthedocs.io/en/1.2.x/|Documentation Officielle Flask-WTF]]+  * [[https://flask-wtf.readthedocs.io/en/1.2.x/|Documentation Flask-WTF]] 
 +  * [[https://flask.palletsprojects.com/en/stable/patterns/wtforms/| Documentation Flask : validation des formulaires WTF (palletsprojects.com) (en)]]
   * [[https://wtforms.readthedocs.io/en/3.2.x/|Documentation Officielle WTForms]]   * [[https://wtforms.readthedocs.io/en/3.2.x/|Documentation Officielle WTForms]]
   * [[https://spectre-org.github.io/spectre-docs/docs/get-started/|Documentation Framework CSS Spectre]]   * [[https://spectre-org.github.io/spectre-docs/docs/get-started/|Documentation Framework CSS Spectre]]
Ligne 120: Ligne 298:
   * https://picturepan2.github.io/spectre/getting-started.html   * https://picturepan2.github.io/spectre/getting-started.html
   * https://spectre-org.github.io/spectre-docs/docs/layout/   * https://spectre-org.github.io/spectre-docs/docs/layout/
 +  * [[https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iii-web-forms| Les formulaires dans Flask (miguelgrinberg.com)]]
  
  
dev/python/flask/flask_formulaires_wtforms.1741442973.txt.gz · Dernière modification : 2025/03/08 14:09 de yoann