Fondamentaux de Flask : requêtes HTTP, authentification et gestion des routes

Introduction rapide à Flask

Flask est un framework web minimaliste basé sur le WSGI (Web Server Gateway Interface) via Werkzeug. Lorsqu'une requête utilisateur arrrive, la méthode app.__call__ est exécutée. Voici un exemple de base :

from flask import Flask

application = Flask(__name__)

@application.route("/connexion", endpoint="login_ep")
def acceder():
    print("Processus de connexion")
    return "Connecté"

@application.route("/accueil")
def page_accueil():
    return "Bienvenue sur la page d'accueil"

if __name__ == "__main__":
    application.run()

Le paramètre endpoint dans les routes définit un alias pour la fonction de vue. S'il n'est pas spécifié, il prend par défaut le nom de la fonction.

Exemple d'authentification utilisateur

Programme principle :

from flask import Flask, request, render_template, redirect, url_for

application = Flask(__name__)
donnees_utilisateur = {1: {"nom": "Alice", "age": 30}, 2: {"nom": "Bob", "age": 25}}

@application.route('/connexion', methods=['GET', 'POST'])
def connexion():
    if request.method == "GET":
        return render_template("connexion.html")
    identifiant = request.form['identifiant']
    mot_de_passe = request.form['mdp']
    if identifiant == "admin" and mot_de_passe == "secret":
        return redirect("/accueil")
    erreur = "Identifiants incorrects"
    return render_template("connexion.html", erreur=erreur)

@application.route('/accueil', endpoint="accueil_ep")
def afficher_accueil():
    return render_template("accueil.html", donnees=donnees_utilisateur)

@application.route('/modifier', methods=['GET', 'POST'])
def modifier_utilisateur():
    id_utilisateur = request.args.get("id")
    id_utilisateur = int(id_utilisateur)
    if request.method == "GET":
        info = donnees_utilisateur[id_utilisateur]
        return render_template("modification.html", info=info)
    nouveau_nom = request.form['nom']
    nouvel_age = request.form['age']
    donnees_utilisateur[id_utilisateur] = {"nom": nouveau_nom, "age": nouvel_age}
    return redirect("/accueil")

@application.route('/supprimer/<id_utilisateur>')
def supprimer_utilisateur(id_utilisateur):
    del donnees_utilisateur[id_utilisateur]
    return redirect(url_for("accueil_ep"))

if __name__ == '__main__':
    application.run()</id_utilisateur>

Fichiers de templates HTML :

connexion.html

<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Connexion</title>
</head>
<body>
    <h1>Se connecter</h1>
    <form method="post">
        <input type="text" name="identifiant" placeholder="Identifiant">
        <input type="password" name="mdp" placeholder="Mot de passe">
        <input type="submit" value="Connexion"><span style="color: red;">{{ erreur }}</span>
    </form>
</body>
</html>

accueil.html

<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Accueil</title>
</head>
<body>
    <table border="1" style="margin-top: 10px;">
        <thead>
            <tr>
                <th>ID</th>
                <th>Nom</th>
                <th>Age</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            {% for cle, valeur in donnees.items() %}
                <tr>
                    <td>{{ cle }}</td>
                    <td>{{ valeur.nom }}</td>
                    <td>{{ valeur.age }}</td>
                    <td>
                        <a href="/modifier?id={{ cle }}">Modifier</a>
                        <a href="/supprimer/{{ cle }}">Supprimer</a>
                    </td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
</body>
</html>

modification.html

<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Modification</title>
</head>
<body>
    <form method="post">
        <input type="text" name="nom" value="{{ info.nom }}">
        <input type="text" name="age" value="{{ info.age }}">
        <input type="submit" value="Mettre à jour">
    </form>
</body>
</html>

Requêtes et réponses HTTP

Requêtes GET et POST

Les requêtes GET transmettent des paramètres via l'URL, tandis que les requêtes POST utilisent le corps de la requête, qui peut être sous forme de données classiques ou JSON.

from flask import Flask, request, jsonify

application = Flask(__name__)

@application.route('/donnees', methods=['GET', 'POST'])
def gerer_donnees():
    # Paramètres GET via l'URL
    identifiant = request.args.get('id')
    secret = request.args.get('cle')
    print(identifiant, secret)
    
    # Paramètres POST dans le corps de la requête
    valeur1 = request.form.get("champ1")
    valeur2 = request.form.get("champ2")
    print(valeur1, valeur2)
    
    # Données JSON dans le corps de la requête
    print(request.json)
    return 'Succès'

if __name__ == '__main__':
    application.run(host="0.0.0.0", port=5000, debug=True)

Requêtes POST avec JSON

Utilisation de jsonify pour sérialiser les réponses JSON.

import hashlib
from flask import Flask, request, jsonify

application = Flask(__name__)

def charger_utilisateurs():
    utilisateurs = {}
    with open('base.txt', 'r') as fichier:
        for ligne in fichier:
            ligne = ligne.strip()
            jeton, nom = ligne.split(',')
            utilisateurs[jeton] = nom
    return utilisateurs

@application.route('/signature', methods=['POST'])
def calculer_signature():
    # Données attendues en JSON : {"texte_a_signer":"...."}
    texte = request.json.get('texte_a_signer')
    if not texte:
        return jsonify({"statut": False, "erreur": "Paramètre invalide"})
    # Génération d'une signature numérique
    chiffrage = texte + "cle-secrete-123"
    signature = hashlib.md5(chiffrage.encode('utf-8')).hexdigest()
    return jsonify({"statut": True, "donnee": signature})

if __name__ == '__main__':
    application.run(host="0.0.0.0", port=5000, debug=True)

Gestion des sessions

Les sessions permettent de stocker des informations utilisateur entre les requêtes. Configuration nécessaire :

application.secret_key = "ma-cle-secrete-ultra-longue"
# ou via la configuration : application.config['SECRET_KEY'] = "ma-cle-secrete-ultra-longue"

Exemple d'utilisation :

# Après authentification réussie
if donnees_utilisateur:
    session['infos_utilisateur'] = donnees_utilisateur
    return redirect("/accueil")

# Dans une autre route
@application.route('/profil')
def afficher_profil():
    infos = session.get("infos_utilisateur")
    if not infos:
        return redirect("/connexion")
    return "Bienvenue dans votre profil"

Configuration des routes

Alias et utilisation de url_for()

L'alias d'une route est défini via le paramètre endpoint. La fonction url_for() génère l'URL correspondante.

@application.route('/tableau', endpoint="tableau_bord")
def tableau_de_bord():
    # ... logique ...
    return render_template("tableau.html")

# Génération d'URL
url_vers_tableau = url_for("tableau_bord")

Transmission de valeurs depuis les templates

Deux méthodes courantes :

  1. Via les paramètres de requête GET : <a href="/modifier?id={{ cle }}">
  2. Via les convertisseurs d'URL : <a href="/supprimer/{{ cle }}">

Exemple de route avec convertisseur :

@application.route('/supprimer/<id_element>')
def supprimer_element(id_element):
    # Traitement avec id_element
    return redirect(url_for("tableau_bord"))</id_element>

Récapitulatif des routes Flask

  • Définition de route : @application.route('/chemin', methods=['GET', 'POST'])
  • Paramètres additionnels : endpoint="alias_unique"
  • Routes dynamiques : /chemin/<type:parametre> (types : string, int, etc.)
  • Récupération de données : request.args pour GET, request.form pour POST
  • Réponses possibles : templates, JSON, redirection, texte simple
  • Syntaxe dans les templates : {{ variable }} et boucles {% for %}

Décorateurs et authentification

Utilisasion des décorateurs

Un décorateur peut vérifier l'authentification avant l'exécution d'une fonction de vue.

import functools
from flask import session, redirect, url_for

def verification_auth(fonction):
    @functools.wraps(fonction)
    def fonction_modifiee(*args, **kwargs):
        if not session.get('infos_utilisateur'):
            return redirect(url_for("connexion"))
        return fonction(*args, **kwargs)
    return fonction_modifiee

# Application du décorateur
@application.route('/supprimer/<id>')
@verification_auth
def supprimer_protege(id):
    # Suppression sécurisée
    return redirect(url_for("accueil_ep"))</id>

Intercepteurs (hooks de requête)

Les hooks before_request permettent d'intercepter toutes les requêtes pour une authentification globale.

from flask import Flask, redirect, session, request

def verifier_auth_globale():
    if request.path.startswith("/ressources_statiques"):
        return
    if request.path == '/connexion':
        return
    if session.get('infos_utilisateur'):
        return
    else:
        return redirect("/connexion")

def creer_application():
    app = Flask(__name__)
    app.secret_key = "cle-secrete-application"
    
    # Enregistrement des blueprints...
    app.before_request(verifier_auth_globale)
    return app

Les intercepteurs offrent une approche centralisée et pratique pour la gestion des accès.

Étiquettes: Flask Python Développement Web HTTP sessions

Publié le 14 juillet à 21h44