Action de forme de signe déraisonnable. Validation sur le terrain améliorée

  • Traduction
  • Tutoriel

Il s'agit du troisième article d'une série dans laquelle je décris mon expérience d'écriture d'une application Web en Python à l'aide du microframework Flask.

Le but de ce tutoriel est de développer une application de microblog assez fonctionnelle, ce pour quoi je suis absence totale pour l'originalité, j'ai décidé de l'appeler microblog.

Récapitulatif rapide Dans la partie précédente, nous avons défini un modèle simple pour la page d'accueil et utilisé des objets imaginaires comme prototypes pour des choses que nous n'avons pas encore. Par exemple, des utilisateurs ou des enregistrements.

Dans cet article, nous allons combler l'une des lacunes que nous avons dans notre application. Nous verrons comment travailler avec des formulaires.

Les formulaires sont l’un des éléments de base de toute application Web. L'utilisation de formulaires permettra aux utilisateurs de publier des entrées de blog et également de se connecter à l'application.

Pour suivre cette partie, votre application de microblogging doit être la même que celle que nous l'avons laissée à la fin de la précédente. Veuillez vous assurer que l'application est installée et fonctionne.

Configuration Pour traiter les formulaires, nous utiliserons l'extension Flask-WTF, qui est un wrapper pour WTForms et s'intègre parfaitement aux applications Flask.

De nombreuses extensions Flask nécessitent une certaine configuration, nous allons donc créer un fichier de configuration dans le dossier racine de notre microblog afin qu'il soit facile à modifier si nécessaire. Voici par quoi nous allons commencer (fichier config.py) :
CSRF_ENABLED = True SECRET_KEY = "vous ne devinerez jamais"

C'est simple, ce sont les deux paramètres dont notre extension Flask-WTF a besoin. CSRF_ENABLED Active la prévention contre la falsification de requêtes intersites. Dans la plupart des cas, vous souhaiterez activer cette option, ce qui rendra votre application plus sécurisée.

SECRET_KEY n'est nécessaire que lorsque CSRF est activé. Il est utilisé pour créer un jeton cryptographique utilisé lors de la validation du formulaire. Lorsque vous rédigez votre candidature, assurez-vous que votre clé privée est difficile à deviner.

Nous avons maintenant la configuration et nous devons dire à Flask de la lire et de l'utiliser. Nous pouvons le faire juste après la création de l'objet d'application Flask (fichier app/__init__.py) :
à partir de l'importation de flacon Flask app = Flask(__name__) app.config.from_object("config") à partir des vues d'importation d'application

Formulaire de connexion Dans Flask-WTF, les formulaires sont représentés comme des objets de sous-classe de la classe Form. La sous-classe des formulaires définit simplement les champs du formulaire en tant que variables de la classe.

Nous créerons un formulaire de connexion qui sera utilisé en conjonction avec le système d'identification. Le mécanisme de connexion que nous prendrons en charge dans notre application n'est pas le type de nom d'utilisateur/mot de passe standard - nous utiliserons OpenID comme connexion. L'avantage d'OpenID est que l'autorisation se fait auprès du fournisseur OpenID, nous n'avons donc pas besoin de vérifier les mots de passe, ce qui rendra notre site plus sécurisé pour nos utilisateurs.

La connexion OpenID ne nécessite qu'une seule ligne appelée OpenID. Nous ajouterons également une case à cocher « Se souvenir de moi » au formulaire afin que l'utilisateur puisse définir un cookie dans son navigateur qui mémorisera son identifiant à son retour.

Écrivons notre premier formulaire (fichier app/forms.py) :
depuis flask.ext.wtf import Form depuis wtforms import TextField, BooleanField depuis wtforms.validators import Classe requise LoginForm (Formulaire): openid = TextField("openid", validators = ) Remember_me = BooleanField("remember_me", par défaut = False)

Je suis sûr que la classe parle d'elle-même. Nous avons importé la classe Form et les deux classes de champs dont nous aurons besoin, TextField et BooleanField.

Le requis importé est un validateur, une fonction qui peut être attachée à un champ pour effectuer la validation des données soumises par l'utilisateur. Le validateur Required vérifie simplement que le champ n'a pas été envoyé vide. Il existe de nombreux validateurs dans Flask-WTF, nous en utiliserons plusieurs nouveaux à l'avenir.

Modèles de formulaire Nous avons également besoin d'un modèle HTML contenant le formulaire. La bonne nouvelle est que la classe LoginForm que nous venons de créer sait comment restituer les champs de formulaire en HTML, nous devons donc simplement nous concentrer sur la mise en page. Voici notre modèle de connexion : (fichier app/templates/login.html) :
Connectez-vous ((form.hidden_tag()))

Veuillez entrer votre OpenID :
((form.openid(size=80)))

(%bloc final%)

Notez que nous utilisons à nouveau le modèle base.html via l'opérateur d'héritage, en l'étendant. Nous ferons cela avec tous nos modèles, en garantissant une mise en page cohérente sur toutes les pages.

Il y en a plusieurs différences intéressantes entre un formulaire HTML classique et notre modèle. Le modèle attend une instance de la classe de formulaire que nous venons d'attribuer dans l'argument du modèle de formulaire. Nous nous occuperons de transmettre cet argument de modèle à l'avenir lorsque nous écrirons une fonction de vue qui transmet ce modèle.

Le paramètre de modèle form.hidden_tag() sera remplacé par le champ de prévention CSRF caché activé dans notre fichier de paramètres. Ce champ devrait figurer sur tous vos formulaires si CSRF est activé.

Nos champs de formulaire sont fournis par un objet formulaire, il vous suffit de passer l'argument ((form.field_name)) à l'emplacement du modèle où le champ doit être inséré. Certains champs peuvent accepter des arguments. Dans notre cas, nous demandons au formulaire de créer notre champ openid d'une largeur de 80 caractères.

Puisque nous n'avons pas défini de bouton de soumission dans la classe form, nous devons le définir comme un champ normal. Le champ de soumission ne contient aucune donnée, il n'est donc pas nécessaire de le définir dans la classe du formulaire.

Vues de formulaire La dernière étape avant de pouvoir voir notre formulaire consiste à écrire une fonction de vue qui renvoie le modèle.

C’est en fait assez simple, puisqu’il suffit de passer l’objet formulaire au modèle. voici le nôtre nouvelle fonctionnalité vues (fichier app/views.py) :
depuis flask import render_template, flash, redirection depuis l'application import app depuis les formulaires import LoginForm # fonction d'affichage de l'index omise par souci de concision @app.route("/login", méthodes = ["GET", "POST"]) def login() : form = LoginForm() return render_template("login.html", title = "Connexion", form = form) !}

Nous avons importé notre classe LoginForm, l'avons instanciée et l'avons envoyée au modèle. C'est tout ce dont vous avez besoin pour dessiner les champs du formulaire.

Ignorons le flash et redirigeons les importations. Nous les utiliserons un peu plus tard.

Une autre innovation concerne les arguments de méthode dans le décorateur d'itinéraire. Ici, nous disons à Flask que la fonction d'affichage accepte les requêtes GET et POST. Sans cela, la vue n'acceptera que les requêtes GET. Nous souhaitons recevoir des requêtes POST qui renverront un formulaire avec les données saisies par l'utilisateur.

À ce stade, vous pouvez lancer l'application et consulter votre formulaire dans le navigateur. Une fois lancé, ouvrez l'adresse que nous avons associée à la fonction d'affichage de connexion : http://localhost:5000/login

Nous n'avons pas encore programmé la partie qui reçoit les données, donc cliquer sur le bouton Soumettre n'aura aucun effet.

Récupération des données du formulaire
Un autre domaine dans lequel Flask-WTF facilite notre travail est le traitement des données soumises. Ce nouvelle version notre fonction de visualisation de connexion, qui valide et enregistre les données du formulaire (fichier app/views.py) :
@app.route("/login", méthodes = ["GET", "POST"]) def login() : form = LoginForm() if form.validate_on_submit() : flash("Connexion demandée pour OpenID="" + form.openid.data + "", Remember_me=" + str(form.remember_me.data)) return redirect("/index") return render_template("login.html", title = "Connexion", form = form) !}

La méthode validate_on_submit effectue tout le traitement. Si vous avez appelé la méthode lorsque le formulaire est présenté à l'utilisateur (c'est-à-dire avant que l'utilisateur n'ait la possibilité de saisir des données), elle renverra False , alors vous savez que vous devez restituer le modèle.

Si validate_on_submit est appelé dans le cadre d'une demande de soumission de formulaire, il collectera toutes les données, exécutera tous les validateurs attachés aux champs et, si tout va bien, retournera True , indiquant que les données sont valides. Cela signifie que les données peuvent être incluses en toute sécurité dans l'application.

Si au moins un champ échoue à la validation, la fonction renverra False, ce qui entraînera à nouveau le rendu du formulaire devant l'utilisateur, donnant ainsi la possibilité de corriger les erreurs. Plus tard, nous apprendrons comment afficher des messages d'erreur lorsque la validation échoue.

Lorsque validate_on_submit renvoie True, notre fonction de soumission appelle deux nouvelles fonctions importées de Flask. La fonction Flash est moyen rapide afficher un message sur la page suivante présentée à l'utilisateur. DANS dans ce cas Nous l'utiliserons pour le débogage tant que nous ne disposons pas de l'infrastructure nécessaire à la journalisation. Nous imprimerons simplement un message qui affichera les données envoyées. Flash est également extrêmement utile sur un serveur de production pour fournir retour avec l'utilisateur.

Les messages Flash n'apparaîtront pas automatiquement sur notre page ; nos modèles doivent afficher les messages d'une manière adaptée à la mise en page de notre site. Nous ajouterons des messages au modèle de base afin que tous nos modèles héritent de cette fonctionnalité. Voici le modèle de base mis à jour (fichier app/templates/base.html) :
(% si titre %) ((titre)) - microblog (% else %) microblog (% endif %) Microblog : Accueil (% avec messages = get_flashed_messages() %) (% si messages %)

    (% pour message dans messages %)
  • ((message))
  • (%fin pour%)
(% endif %) (% endwith %) (% contenu du bloc %) (% endblock %)

J'espère que la façon dont les messages sont affichés est explicite.

Une autre nouvelle fonctionnalité que nous avons utilisée dans notre vue de connexion est la redirection. Cette fonction redirige le navigateur web du client vers une page autre que celle demandée. Dans notre fonction d'affichage, nous avons utilisé une redirection vers page d'accueil, développé dans les parties précédentes. Gardez à l'esprit que les messages flash seront affichés même si la fonction se termine par une redirection.

C'est le moment idéal pour exécuter l'application et vérifier le fonctionnement des formulaires. Essayez de soumettre le formulaire avec un champ openid vide pour voir comment le validateur requis arrête le processus de soumission.

Validation de champ améliorée Avec l'application dedans état actuel Les formulaires soumis avec des données incorrectes ne seront pas acceptés. Au lieu de cela, le formulaire sera renvoyé à l'utilisateur pour correction. C'est exactement ce dont nous avons besoin.

Ce que nous avons manqué, c'est d'informer l'utilisateur de ce qui ne va pas exactement avec le formulaire. Heureusement, Flask-WTF facilite également cette tâche.

Lorsqu'un champ échoue à la validation, Flask-WTF ajoute un message d'erreur visuel à l'objet de formulaire. Ces messages sont disponibles dans le modèle, il suffit donc d'ajouter une logique pour les afficher.

Voici notre modèle de connexion avec les messages de validation des champs (fichier app/templates/login.html) :
(% étend "base.html" %) (% de contenu du bloc %) Connexion ((form.hidden_tag()))

Veuillez entrer votre OpenID :
((form.openid(size=80)))
(% pour l'erreur dans form.errors.openid %) [((erreur))] (% fin pour %)

((form.remember_me)) Se souvenir de moi

(%bloc final%)

Le seul changement que nous avons apporté a été d'ajouter une boucle qui dessine tous les messages d'erreur ajoutés par le validateur à droite du champ openid. En règle générale, tous les champs auxquels sont attachés des validateurs auront des erreurs ajoutées sous le nom form.errors.field_name. Dans notre cas, nous utilisons form.errors.openid . Nous affichons ces messages en rouge pour attirer l'attention de l'utilisateur sur eux.

Interaction avec OpenID En fait, nous constaterons que beaucoup de gens ne savent même pas qu'ils possèdent déjà quelques OpenID. On sait peu de choses qu'un certain nombre de grands fournisseurs de services Internet prennent en charge l'authentification OpenID pour leurs utilisateurs. Par exemple, si vous avez un compte Google, vous disposez également d'OpenID. Tout comme Yahoo, AOL, Flickr et bien d'autres services.

Pour permettre à un utilisateur de se connecter plus facilement à notre site avec l'un des OpenID couramment utilisés, nous ajouterons des liens vers certains d'entre eux afin que l'utilisateur n'ait pas à saisir manuellement l'OpenID.

Commençons par définir une liste de fournisseurs OpenID que nous souhaitons représenter. Nous pouvons le faire dans notre fichier de configuration (fichier config.py) :
OPENID_PROVIDERS = [ ( "nom": "Google", "url": "https://www.google.com/accounts/o8/id" ), ( "nom": "Yahoo", "url": "https //me.yahoo.com" ), ( "nom": "AOL", "url": "http://openid.aol.com/" ), ( "nom": "Flickr", "url" : "http://www.flickr.com/", ( "nom": "MonOpenID", "url": "https://www.myopenid.com" )]

Voyons maintenant comment nous utilisons cette liste dans notre fonction d'affichage de connexion :
@app.route("/login", méthodes = ["GET", "POST"]) def login() : form = LoginForm() if form.validate_on_submit() : flash("Connexion demandée pour OpenID="" + form.openid.data + "", Remember_me=" + str(form.remember_me.data)) return redirect("/index") return render_template("login.html", title = "Connexion", form = form, providers = app.config["OPENID_PROVIDERS"]) !}

Ici, nous obtenons les paramètres en les recherchant à l'aide de la clé dans app.config . Ensuite, la liste est ajoutée à l'appel render_template en tant qu'argument de modèle.

Comme vous l’avez peut-être deviné, nous devons franchir une étape supplémentaire pour mettre fin à cette situation. Nous devons maintenant préciser comment nous souhaitons afficher les liens vers ces fournisseurs dans notre modèle de connexion (fichier app/templates/login.html) :
(% extends "base.html" %) (% contenu du bloc %) function set_openid(openid, pr) ( u = openid.search("") if (u != -1) ( // openid nécessite un nom d'utilisateur user = prompt ("Entrez votre nom d'utilisateur " + pr + " :") openid = openid.substr(0, u) + user ) form = document.forms["login"]; Connectez-vous ((form.hidden_tag()))

Veuillez saisir votre OpenID ou sélectionner l'un des fournisseurs ci-dessous :
((form.openid(size=80))) (% pour l'erreur dans form.errors.openid %) [((error))] (% endfor %)
|(% pour pr dans les fournisseurs %) ((pr.name))|

((form.remember_me)) Se souvenir de moi

(%bloc final%)

(%fin pour%)

Le modèle s'est avéré un peu long à cause de tous ces changements. Certains OpenID incluent des noms d'utilisateur, pour ceux-là, nous devons avoir un peu de magie javascript qui demande le nom d'utilisateur puis crée un OpenID. Lorsqu'un utilisateur clique sur le lien OpenID d'un fournisseur et saisit (éventuellement) un nom d'utilisateur, l'OpenID de ce fournisseur est inséré dans le champ de texte.

capture d'écran de notre page de connexion après avoir cliqué sur le lien Google OpenID

Derniers mots Bien que nous ayons fait beaucoup de progrès avec nos formulaires de connexion, nous n'avons pas vraiment fait grand-chose pour attirer les utilisateurs dans notre système. Tout ce que nous faisions concernait l'interface graphique du processus de connexion. En effet, avant de pouvoir effectuer de véritables connexions, nous devons disposer d’une base de données dans laquelle nous pouvons enregistrer nos utilisateurs.

Dans la prochaine partie, nous rendrons notre base de données opérationnelle, un peu plus tard, nous compléterons notre système de connexion, alors restez à l'écoute pour les prochains articles.

Les formulaires peuvent être trouvés sur presque tous les sites Web sur Internet. Par exemple, lorsque vous saisissez votre identifiant et votre mot de passe sur un site Web, les données sont renseignées via des formulaires et envoyées au serveur. Diverses enquêtes sont également un exemple de formulaire.

Syntaxe des balises

...

La balise a un attribut d'action très important, auquel est attribuée l'adresse (URL) du script auquel les informations reçues du formulaire sont envoyées pour traitement. Nous n'entrerons pas dans les détails de ce qui se passe après l'envoi des données, car ces problèmes sont déjà résolus non pas par HTML, mais par les méthodes GET et POST en PHP.

Exemple 1. Formulaire HTML avec des boutons Ce seront des boutons :
Bouton un
Bouton deux
Bouton trois






Après avoir cliqué sur OK, la page sera simplement actualisée, car... nous n'avons pas spécifié le paramètre d'action

Convertit ce qui suit sur la page :

Ce seront les boutons :
Bouton un
Bouton deux
Bouton trois
Et ce sera un champ de texte. Par exemple, vous pouvez saisir votre identifiant ici

Et ce sera un grand champ de texte. Par exemple, vous pouvez saisir ici des informations vous concernant

Après tout ce qui précède, il y aura un bouton OK

Après avoir cliqué sur OK, la page sera simplement actualisée, car... nous n'avons pas spécifié le paramètre d'action

Explications par exemple

  • action="" - indique que le traitement des données aura lieu sur la même page.
  • - l'attribut type="radio" indique qu'il faut afficher le texte après ce code comme bouton de sélection. Les attributs name et value de cette balise jouent désormais un petit rôle pour nous, car Nous n'étudions pas le php pour le moment (voir les leçons de php).
  • - l'attribut type="text" indique qu'il s'agira d'un champ texte. Il y a également deux attributs importants ici : name (pour php) et value (valeur par défaut).
  • - l'attribut type="textarea" indique qu'il s'agira d'un grand champ de texte. La seule différence avec le cas précédent est qu'il permet d'enregistrer une grande quantité de texte.
  • - l'attribut type="submit" indique qu'il s'agit d'un bouton. L'attribut value contient ce qui sera écrit sur le bouton.

Vous pouvez en savoir plus sur tous ces éléments dans la leçon 15 : éléments de balise, où les boutons radio, les listes, les cases à cocher, les champs de texte et les boutons sont abordés.

Examinons maintenant en détail tous les attributs de la balise.

Attributs et propriétés des balises

1. L'attribut accept-charset="Encoding" - détermine le codage dans lequel le serveur peut accepter et traiter les données du formulaire. Peut prendre différentes significations, par exemple, CP1251, UTF-8, etc.

2. L'attribut action="URL" est l'adresse du script qui traite les données transmises depuis le formulaire. Si vous laissez cette valeur vide, les données seront traitées dans le même document où se trouve le formulaire.

3. Attribut autocomplete="on/off" - définit ou désactive la saisie semi-automatique du formulaire. Peut prendre deux valeurs :

  • on - activer la saisie automatique ;
  • off - désactiver la saisie automatique ;

4. Attribut enctype="parameter" - spécifie la méthode de codage des données. Peut prendre les valeurs suivantes :

  • application/x-www-form-urlencoded - les espaces sont remplacés par +, les caractères comme les lettres russes sont codés avec leurs valeurs hexadécimales
  • multipart/form-data - les données ne sont pas codées
  • text/plain - les espaces sont remplacés par un signe +, les lettres et autres caractères ne sont pas codés.

5. Attribut Method="POST/GET" - spécifie la méthode d'envoi. Peut prendre deux valeurs :

  • GET - transmission de données dans la barre d'adresse (il existe une limitation sur le volume de données envoyées)
  • POST - envoie des données au serveur dans une requête du navigateur (peut envoyer grand nombre données, parce que aucune limitation de volume)

6. Attribut name="name" - définit le nom du formulaire. Le plus souvent utilisé lorsqu'il existe plusieurs formulaires afin que vous puissiez accéder à un formulaire spécifique via un script.

7. L'attribut novalidate - annule la vérification intégrée des données du formulaire pour l'exactitude de la saisie.

8. L'attribut target="parameter" est le nom de la fenêtre ou du cadre dans lequel le gestionnaire chargera le résultat renvoyé. Peut prendre les valeurs suivantes :

  • _blank - charge la page dans une nouvelle fenêtre de navigateur
  • _self - charge la page dans fenêtre actuelle
  • _parent - charge la page dans le cadre parent
  • _top - annule tous les cadres et charge la page dans la fenêtre complète du navigateur

Cher lecteur, vous en savez maintenant beaucoup plus sur la balise de formulaire HTML. Maintenant, je vous conseille de passer à la leçon suivante.

Spécifie le gestionnaire auquel les données du formulaire sont accessibles lorsqu'elles sont soumises au serveur. Le gestionnaire peut être un programme serveur ou un document HTML incluant des scripts serveur (par exemple, Parser). Une fois que le gestionnaire a effectué des actions sur les données du formulaire, il renvoie un nouveau document HTML.

Si l'attribut action est manquant, la page actuelle est rechargée, ramenant tous les éléments du formulaire à leurs valeurs par défaut.

Syntaxe

...

Valeurs

La valeur est le chemin complet ou relatif du fichier serveur.

Valeur par défautExemple

FORMULAIRE, attribut d'action

Vous pouvez spécifier une adresse en tant que gestionnaire e-mail, à partir de mot-clé mail à : . Lors de la soumission du formulaire, le programme de messagerie par défaut sera lancé. Pour des raisons de sécurité, le navigateur a été paramétré pour rendre impossible l'envoi discret par mail des informations saisies dans le formulaire. Pour interpréter correctement les données, utilisez l'attribut enctype="text/plain" dans l'élément.

FORMULAIRE, attribut d'action

Navigateurs

Les notations suivantes sont utilisées dans la table du navigateur.

  • - l'élément est entièrement pris en charge par le navigateur ;
  • - l'élément n'est pas perçu par le navigateur et est ignoré ;
  • - pendant le fonctionnement, diverses erreurs peuvent apparaître, ou l'élément est pris en charge avec des réserves.

Le numéro indique la version du navigateur à partir de laquelle l'élément est pris en charge.

Cet article détaille l'utilisation de la variable PHP _SELF.

Qu'est-ce que la variable PHP _SELF ?

La variable PHP _SELF renvoie le nom et le chemin du fichier courant (par rapport à la racine du document). Vous pouvez utiliser cette variable dans l'attribut action du formulaire. Il y a aussi certaines nuances que vous devez connaître. Bien entendu, nous ne pouvons ignorer ces nuances.

Regardons quelques exemples.

Écho $_SERVER["PHP_SELF"];

1) Supposons que votre fichier php se trouve à l'adresse suivante :

Http://www.yourserver.com/form-action.php

Dans ce cas, la variable PHP _SELF contiendra :

"/form-action.php"

2) Supposons que votre fichier php se trouve à cette adresse :

Http://www.yourserver.com/dir1/form-action.php

PHP_SELF sera :

"/rép1/form-action.php"

PHP _SELF dans l'attribut action du formulaire. Pourquoi était-elle nécessaire là-bas ?

Généralement, la variable PHP _SELF est utilisée dans attribut d'action balise de formulaire. L'attribut action précise l'adresse à laquelle le contenu du formulaire sera envoyé après confirmation (l'utilisateur clique sur le bouton avec type="submit"). En règle générale, il s'agit de la même page à partir de laquelle le formulaire est parti.

Cependant, si vous renommez le fichier référencé par le formulaire, vous devrez renommer le nom du fichier dans l'attribut action, sinon le formulaire ne fonctionnera pas.

La variable PHP _SELF vous évitera des corrections inutiles, puisque l'adresse de la page sera générée automatiquement en fonction du nom du fichier.

Supposons que vous ayez un fichier de formulaire appelé form-action.php et que vous souhaitiez que le formulaire soit soumis au même fichier après confirmation. Habituellement, ils écrivent comme ceci :

Mais vous pouvez utiliser la variable PHP _SELF au lieu de form-action.php. Dans ce cas, le code ressemblera à :



Avez-vous aimé l'article? Partagez avec vos amis !