Aller au contenu

Premier formulaire POST

Objectif : envoyer une valeur depuis un formulaire HTML et la lire côté contrôleur.

Ce que vous allez apprendre : afficher un formulaire HTML protégé par un jeton CSRF, le soumettre en POST, et lire la valeur reçue dans le corps de la requête avec request.form("name", ...) (et non dans l'URL).

Palier 8 de la progression officielle des starters, après Le jeton CSRF.

Prérequis : comprendre le jeton CSRF (palier 7).

Ce que ce starter montre

  • une route GET /form-post
  • une route POST /form-post
  • une vue HTML avec un formulaire minimal
  • une méthode de contrôleur qui lit la valeur envoyée
  • une réponse texte avec Response.text(...)

Aucune base de données. Aucune validation serveur avancée. Aucun CRUD.

Classes Forge utilisées

Classe Rôle dans ce starter Référence
Request Lire les champs envoyés avec request.form(...). Request
Response Construire la réponse texte avec Response.text(...). Response
BaseController Fournit render(...) pour la vue et csrf_token(...) pour le jeton CSRF. BaseController

Tester

Depuis le projet Forge déjà créé avec ce starter :

forge run

Ouvrez :

https://localhost:8000/form-post

Saisissez Roger, envoyez le formulaire.

Résultat attendu :

Bonjour Roger

Les routes

# mvc/routes.py
from mvc.controllers.form_post_controller import FormPostController

with router.group("", public=True) as pub:
    pub.add("GET",  "/form-post", FormPostController.index,  name="form_post_index")
    pub.add("POST", "/form-post", FormPostController.submit, name="form_post_submit")

Le contrôleur

# mvc/controllers/form_post_controller.py
from core.http.request import Request
from core.http.response import Response
from core.mvc.controller.base_controller import BaseController


class FormPostController(BaseController):

    @staticmethod
    def index(request: Request) -> Response:
        return BaseController.render(
            "form_post/index.html",
            request=request,
            context={"csrf_token": BaseController.csrf_token(request)},
        )

    @staticmethod
    def submit(request: Request) -> Response:
        name = request.form("name", default="Forge")
        return Response.text(f"Bonjour {name}")

Comprendre ce code

  • Deux méthodes pour un même chemin /form-post, mais des verbes HTTP différents : GET affiche le formulaire, POST reçoit la soumission.
  • BaseController.csrf_token(request) génère le jeton CSRF à injecter dans la vue. Sans ce jeton, Forge refuse le POST (protection contre les soumissions cross-site).
  • Côté submit, request.form("name", default="Forge") lit la valeur envoyée dans le corps du formulaire — pas dans l'URL.
  • Une fois la donnée traitée, le contrôleur retourne une réponse. Ici un simple Response.text(...) ; dans une vraie application on redirigerait généralement vers une page de confirmation.

La vue

<!-- mvc/views/form_post/index.html -->
<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <title>Premier formulaire POST — Forge</title>
</head>
<body>
  <h1>Premier formulaire POST</h1>

  <form method="post" action="/form-post">
    <input type="hidden" name="csrf_token" value="{{ csrf_token }}">

    <label for="name">Prénom</label>
    <input id="name" name="name" type="text" value="Forge">

    <button type="submit">Envoyer</button>
  </form>
</body>
</html>

Comprendre ce code

  • method="post" indique au navigateur d'envoyer les données dans le corps de la requête, pas dans l'URL.
  • Le champ caché csrf_token transporte le jeton généré par le contrôleur. Le middleware CSRF de Forge vérifie sa correspondance avant d'appeler submit.
  • name="name" est la clé lue côté serveur par request.form("name").

À retenir

  • GET /form-post affiche le formulaire.
  • POST /form-post reçoit les données.
  • Le contrôleur lit la valeur envoyée avec request.form("name", ...).
  • Le champ caché csrf_token est exigé par Forge sur toute requête POST (protection contre les soumissions cross-site). Il est généré par BaseController.csrf_token(request) et vérifié automatiquement par le middleware.
  • La validation serveur complète viendra au palier suivant (palier 9).

Après ce starter

Passez au palier suivant : Validation serveur.

Vous y apprendrez à refuser une valeur vide avec un statut HTTP explicite :

return Response.text("Le prénom est obligatoire", status=422)

Continuer avec Validation serveur