Aperçu de la CGI avec Python

Formation

En Semi-présenciel Paris

Prix sur demande

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Description

  • Typologie

    Formation

  • Méthodologie

    En semi-présentiel

  • Lieu

    Paris

Grâce à cette formation vous pourrez acquérir les connaissances nécessaires qui vous permettrons d’ajouter des compétences à votre profil et obtenir de solides aptitude qui vous offriront de nombreuses opportunités professionnelles.

Les sites et dates disponibles

Lieu

Date de début

Paris ((75) Paris)
Voir plan
7 Cité Paradis, 75010

Date de début

Consulter

Questions / Réponses

Ajoutez votre question

Nos conseillers et autres utilisateurs pourront vous répondre

À qui souhaitez-vous addresser votre question?

Saisissez vos coordonnées pour recevoir une réponse

Nous ne publierons que votre nom et votre question

Les Avis

Les matières

  • CGI

Le programme

Introduction du cours

Vous aimeriez rendre votre site interactif, par exemple pour mettre en place un compteur de visites, un formulaire de contact, un petit jeu...
Pour ça, tout le monde utilise le PHP. Mais vous faites partie d'une élite éclairée et vous aimeriez le faire avec Python. C'est faisable !
Voici un aperçu de la CGI avec ce langage.

Juste une chose avant de commencer, si vous n'avez pas d'hébergeur qui vous permette d'utiliser Python sur vos pages web, regardez donc cette liste. Si vous hébergez votre site vous-même, alors sachez qu'il vous suffit d'installer Apache et Python.

Les exemples contenus dans ce cours fonctionnement avec la version 2 de Python. Si vous utilisez la version 3 ou supérieure, n'oubliez pas de remplacer les print ... par des print(...)

Préparation

Pour que vos scripts soient exploitables, il faut tout d'abord configurer Apache.
Créons un fichier .htaccess, que vous placerez à la racine du site (en effet, ce fichier fonctionne récursivement : tous les répertoires situés dans le répertoire contenant votre .htaccess seront assujettis aux règles que vous définirez dans celui-ci). Le voici :

AddHandler cgi-script .py Options +ExecCGI

Ces deux lignes indiquent que les fichiers .py doivent être interprétés avant d'être envoyés au client. Le comportement par défaut serait d'envoyer le fichier comme s'il s'agissait d'un fichier texte ordinaire.
Une bonne chose à faire est de configurer Apache pour considérer vos fichiers index.py comme les indexes de vos répertoires. Pour cela, vous pouvez ajouter la ligne suivante à votre .htaccess :

DirectoryIndex index.py

Néanmoins, il reste une chose très importante à faire : rendre votre script exécutable. Je dois reconnaître que je me suis souvent fait avoir par ce genre d'erreur. C'est assez pervers car vous ne savez pas pourquoi votre script échoue : vous vous retrouvez face à une erreur 500 fort peu explicite.
Pour ce faire, sous UNIX, il faut utiliser la commande suivante :

chmod +x fichier.py

Vous devez le faire sur chacun de vos scripts.

Maintenant, nous allons voir comment rédiger nos fichiers Python.

La rédaction des scripts

Lorsque vous utilisez Python pour votre site web, vous générez du HTML.
Il vous faut le préciser : vous pourriez très bien renvoyer une image, aussi faut-il informer le client de la nature du document renvoyé.
Pour ce faire, il faut tout simplement utiliser print :

#!/usr/bin/python print 'Content-type: text/html' print # Là commence votre code.

La première ligne est importante : il s'agit du shebang. Il indique quel interpréteur Python utiliser.
La seconde (en réalité, la troisième car j'ai sauté une ligne) indique le type de document envoyé.
La dernière écrit une ligne vide. En effet, le client et le serveur communiquent par le protocole HTTP. Ce dernier est composé d'un en-tête, dans lequel des informations comme le nom et la version du client, ceux du serveur, le poids du fichier, l'état de la requête (vous savez, 200 OK, 404 Not Found, 500 Internal Server Error...), etc., et du corps de la requête, qui contient, dans le cas d'une requête du serveur vers le client, le fichier envoyé. Ces deux blocs (en-tête et corps) sont séparés par une ligne vide. Pour plus d'informations, regardez donc l'article sur Wikipedia.

Le type de fichier (que j'ai spécifié à la deuxième ligne avec 'Content-type: text/html'), fait partie de l'en-tête de la requête. Or, la page que vous souhaitez envoyer se trouve dans le corps. C'est pourquoi vous devez les séparer à l'aide de cette ligne vide.

Votre script est maintenant prêt. Vous pouvez désormais écrire votre code HTML, toujours à l'aide de print :

#!/usr/bin/python print 'Content-type: text/html' print print '<html><head><title>...'

Vous pouvez, plutôt que de vous esquinter à écrire ligne par ligne :

print '<html>' print '<head>' print '<title>Mon super site en Python qui powne tout XdXDxDXDXd</title>' print '</head>' print '<body>' # ... Je vous épargne la suite de cette horreur.

Utiliser la syntaxe suivante, qui n'est pas toujours connue :

print ''' <html> <head> <title>Mon super site en Python qui powne tout XdXDxDXDXd</title> </head> <body> <p>Vous êtes jaloux, hein ?</p> </body> </html> '''

Vous constatez qu'à l'intérieur des ''', vous pouvez utilisez l'indentation que vous voulez.
Il est bien entendu important de rendre son site conforme aux normes de la W3C.

Si vous avez eu l'occasion de faire une erreur dans votre code, vous avez sûrement pu admirer une erreur 500. Et, vous l'avez remarqué, c'est très gênant pour le dépistage d'erreurs. Le module cgitb va pouvoir vous aider.
Pour cela, il faut l'importer, puis l'activer :

import cgitb cgitb.enable()

C'est fait ! Maintenant, les erreurs s'afficheront sur la page. Ces deux lignes vous seront certainement utiles !

Mise en pratique : un compteur de visites

Maintenant que vous connaissez le strict minimum, pourquoi ne pas l'employer ? Nous allons réaliser un compteur de visites.
Il serait judicieux de tenter de le faire seul. Néanmoins, je vous donne ma méthode.
Tout d'abord, je tente d'ouvrir un fichier en mode lecture ('r' pour read). Je stocke son contenu dans la variable nbr_visiteurs, en le transformant en un nombre (car il s'agit pour l'instant d'une chaîne). Si cela ne marche pas (pour la bonne raison que mon fichier n'existe pas, ou que son contenu n'est pas un nombre), alors nbr_visiteurs = 0.
Cela donne :

try: # Pour essayer le code qui suit. Si ledit code ne fonctionne pas, alors except: est appelé. Autrement, on continue. fichier = open('compteur','r') # Lecture dans le fichier, appelé 'compteur'. nbr_visiteurs = int(fichier.read()) # int() transforme son argument (à savoir, le contenu du fichier retourné par fichier.read()) en un nombre. except Exception: nbr_visiteurs = 0 # Si le fichier est inexistant (= page jamais visitée) ou incorrect, on repart de 0.

Maintenant, nous allons ouvrir le fichier avec l'option 'w' pour write. S'il existe, il sera supprimé et recréé vide. Sinon, il sera tout simplement créé. Dans les deux cas, nous n'aurons plus qu'à écrire dedans la valeur nbr_visiteurs + 1 (car il faut compter le visiteur qui charge la page :-) ), en la transformant en une chaîne avec la fonction str().

fichier = open('compteur','w') fichier.write(str(nbr_visiteurs+1))

Finalement, on indique au visiteur le nombre de visites :

print nbr_visiteurs+1,'visites \o/'

Ce qui, avec le code minimal, donne :

#!/usr/bin/python print 'Content-type: text/html' print try: fichier = open('compteur','r') nbr_visiteurs = int(fichier.read()) except Exception: nbr_visiteurs = 0 fichier = open('compteur','w') fichier.write(str(nbr_visiteurs+1)) print nbr_visiteurs+1,'visites \o/' Traiter un formulaire

Un des points inévitables en CGI est le traitement de formulaires. En Python, c'est aussi faisable.

Nous travaillons maintenant avec des données envoyées par l'utilisateur. Nous allons notamment les afficher à l'écran. Or, si le visiteur décide de mettre du HTML dans les données qu'il envoie, cela peut présenter une faille.

Prenons un cas concret. Si le visiteur entre le code suivant :

<script type="text/javascript">alert('OLOL CMT G T PWNED');</script>

Une alerte s'affichera sur l'écran du visiteur ! Et rien ne l'empêche de se faire passer pour vous « Votre session va expirer. Entrez votre mot de passe à nouveau. », de le récupérer puis de se le faire envoyer par mail, le tout en JavaScript !
Pour pallier ce problème, nous allons utiliser une fonction fort pratique : cgi.escape(). C'est un peu l'équivalent de htmlspecialchars() en PHP : elle remplace les caractères < et > par &amp;lt; et &amp;gt;. De ce fait, le code JavaScript cité plus haut s'affichera tel quel, au lieu d'être exécuté. Notez que si vous utilisez une version de python supérieure à la 3.2 il vous faudra utiliser html.escape() à la place de cgi.escape(), car cette dernière est dépréciée.
Aussi, prenez l'habitude de sécuriser toutes les données envoyées par le visiteur à l'aide de cette fonction.

Pour traiter un formulaire, nous devons tout d'abord importer le module CGI. Vous savez comment faire :

import cgi

À partir de là, ça se corse. :-° On va créer une instance de la classe cgi.FieldStorage(), qui contiendra le formulaire envoyé. Puis, on pourra en extraire les informations avec instance.getvalue('nom'). Cela vous semble tordu ? En vérité, c'est très simple.

#!/usr/bin/python import cgi print 'Content-type: text/html' print formulaire = cgi.FieldStorage() if formulaire.getvalue('nom') == None: print ''' Veuillez remplir le formulaire : <form action="formulaire.py" method="post"> <input type="text" name="nom" /> <input type="submit"></form> ''' else: print 'Ainsi, vous vous appelez',cgi.escape(formulaire.getvalue('nom')),' ?' # N'oubliez pas de sécuriser le code !

Ce code, enregistré dans un fichier formulaire.py (autrement, il vous faudra le modifier, car le formulaire renvoie vers formulaire.py), créera une instance de cgi.FieldStorage() dans la variable formulaire.
Si formulaire.getvalue('nom') == None, alors le champ 'nom' était vide, voire non envoyé.
On présente donc le formulaire au client. Autrement, on récupère la valeur du champ 'nom' avec formulaire.getvalue('nom'), et on l'affiche tout en prenant soin de le sécuriser avec cgi.escape().
Si le champ s'était appelé 'prenom', vous comprenez bien que l'on aurait récupéré sa valeur avec formulaire.getvalue('prenom').

Vous voulez une bonne nouvelle ? Pour un formulaire envoyé avec GET (c'est-à-dire que les valeurs des champs se retrouvent dans l'URL, dans le style page.py?var=valeur&amp;var2=valeur2), c'est exactement pareil.
Ainsi, le script suivant enregistré sous essai.py et appelé avec essai.py?var=1&amp;var2=2 affichera 'Var = 1 et Var2 = 2'.

#!/usr/bin/python import cgi print 'Content-type: text/html' print form = cgi.FieldStorage() print 'Var = ',cgi.escape(form.getvalue('var')),' et Var2 = ',cgi.escape(form.getvalue('var2')) Mise en pratique : un livre d'or

Le livre d'or est une des fonctionnalités que l'on se plaît à implémenter sur son site. Grâce aux formulaires et à la manipulation de fichiers, c'est tout à fait faisable en Python.
Nous allons tout d'abord créer un formulaire tout simple, puis le traiter. Ensuite, nous verrons comment lire le fichier dans lequel seront enregistrés les messages.
Le formulaire ressemblera à ça :

<form action="enregistrement.py" method="post"> <p>Vous avez une remarque, un commentaire, un conseil ? Signez le livre d'or !</p> <p> Pseudonyme : <input type="text" name="pseudo" /><br /> Site web : <input type="text" name="site" /><br /> Message :<br /> <textarea name="message" cols="20" rows="2"></textarea><br /> <input type="submit" /> </p> </form>

À vous de le faire correspondre à vos besoins.
Pour la gestion du formulaire :

#!/usr/bin/python import cgi print 'Content-type: text/html' print print '<html><head><title>Mon super site</title></head><body>' formulaire = cgi.FieldStorage() if formulaire.getvalue('message') != None: print '<p>Merci d\'avoir particip&amp;eacute; au livre d\'or. Vous pouvez le visiter <a href="livreor.py">ici</a>.</p>' message = formulaire.getvalue('message') site = formulaire.getvalue('site') pseudo = formulaire.getvalue('pseudo') try: fichier = open('livreor','r') livreor = fichier.read() except IOError: livreor = '' message_poste = '<message><auteur>'+cgi.escape(pseudo)+'</auteur><site>'+cgi.escape(site)+'</site><contenu>'+cgi.escape(message)+'</contenu></message>\n' fichier = open('livreor','w') fichier.write(message_poste+livreor) else: print '''Erreur : vous n'avez pas rempli le formulaire.''' print '</body></html>'

C'est tout simple :

  • on charge le formulaire dans la variable formulaire avec cgi.FieldStorage ;

  • on teste si le formulaire a été rempli, en vérifiant qu'un message est présent. Vous pouvez bien sûr vérifier si tous les champs sont remplis ;

  • on charge les éléments du formulaire dans des variables ;

  • on essaie de lire le contenu du fichier livreor. Si cela rate (avec une IOError), c'est que le fichier n'existe pas, auquel cas le contenu de livreor sera une chaîne vide ;

  • on ouvre le fichier livreor en mode écriture. On écrit dedans le contenu du nouveau message.

L'écriture est terminée. Chaque message est écrit dans le format :

<message><auteur>Auteur</auteur><site>Site</site><contenu>Contenu</contenu></message>

Nous n'avons plus qu'à le lire !

#!/usr/bin/python def trouver(chaine,chaine1,chaine2): position_chaine1 = chaine.index(chaine1) + len(chaine1) position_chaine2 = chaine.index(chaine2,position_chaine1) return chaine[position_chaine1:position_chaine2] def isoler_message(chaine): dico = {} try: message = trouver(chaine,'<message>','</message>') dico['auteur'] = trouver(message,'<auteur>','</auteur>') dico['site'] = trouver(message,'<site>','</site>') dico['contenu'] = trouver(message,'<contenu>','</contenu>') return dico except Exception: return 0 def supprimer(chaine): return chaine.replace('<message>'+trouver(chaine,'<message>','</message>')+'</message>','') print 'Content-type: text/html' print print ''' <html> <head> <title>Le livre d'or</title> </head> <body> ''' try: fichier = open('livreor','r') contenu = fichier.read() continuer = True while continuer: message = isoler_message(contenu) if not message: continuer = False else: print '<p>De : <b><a href="',message['site'],'">',message['auteur'],'</a></b></p>' print '<p>',message['contenu'],'</p>' print '<br /><br />' contenu = supprimer(contenu) except Exception: print 'Il n\'y a aucun message dans le livre d\'or' print '</body></html>'

Ma première fonction, trouver(), retourne la première chaîne trouvée entre chaine1 et chaine2 dans chaine. Son fonctionnement est simple, lisez le code si vous souhaitez le comprendre.

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Aperçu de la CGI avec Python

Prix sur demande