Tu vas travailler sur un site web qui permet de :
- Lire et créer des articles
- Envoyer un message de contact
Ce site est découpé en deux grandes parties :
| Partie | Rôle | Fichiers concernés |
|---|---|---|
| Front-end | Ce que tu vois dans le navigateur | index.html, articles.html, contact.html, script.js |
| Back-end | Le cerveau invisible du site | main.py, models.py, database.py |
Ils communiquent via une API : quand tu cliques sur "Envoyer", le navigateur envoie les données au serveur Python, qui les traite et les sauvegarde.
Ouvre un terminal dans le dossier backend/ et tape :
pip install -r requirements.txt
uvicorn main:app --reloadPuis ouvre ton navigateur sur http://localhost:8000
💡 Le
--reloadredémarre automatiquement le serveur à chaque modification. Tu n'as pas besoin de relancer la commande après chaque changement !
Durée estimée : 25 min
Le formulaire de contact semble fonctionner : tu vois "Message envoyé avec succès". Mais les messages ne sont jamais vraiment sauvegardés.
Ouvre backend/main.py et trouve cette fonction :
@app.post("/api/contact")
async def send_message(name: str = Form(...), email: str = Form(...), content: str = Form(...), db: Session = Depends(get_db)):
# TODO :
return {"status": "Message envoyé avec succès"}Elle reçoit les données du formulaire… mais ne fait rien avec !
Juste au-dessus, tu peux voir une fonction qui fonctionne bien :
@app.post("/api/articles")
async def create_article(title: str = Form(...), content: str = Form(...), author: str = Form(...), db: Session = Depends(get_db)):
article = Article(title=title, content=content, author=author) # 1. Créer l'objet
db.add(article) # 2. Préparer la sauvegarde
db.commit() # 3. Sauvegarder pour de vrai
db.refresh(article) # 4. Mettre à jour l'objet
return articleRemplace le # TODO : dans send_message pour sauvegarder le message.
Indices :
- L'objet à créer s'appelle
Message(comme dansmodels.py) - Ses champs sont :
name,email,content - Inspire-toi exactement de
create_article!
- Va sur http://localhost:8000/contact
- Remplis le formulaire et envoie
- Recharge la page — si tu vois "Message envoyé" sans erreur dans le terminal, c'est bon !
💡 Bonus : Ouvre le fichier
database.dbavec un outil comme DB Browser for SQLite pour voir les messages enregistrés.
Durée estimée : 30 min
Ouvre frontend/index.html.
Exercice A — Changer le nom du site
Trouve la ligne :
<a class="navbar-brand" href="/">Mon Projet</a>Remplace Mon Projet par un nom de ton choix. Recharge la page !
Exercice B — Changer la couleur de la barre de navigation
Trouve :
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">Remplace bg-dark par l'une de ces classes Bootstrap :
| Classe | Couleur |
|---|---|
bg-dark |
Noir (défaut) |
bg-primary |
Bleu |
bg-success |
Vert |
bg-danger |
Rouge |
bg-warning navbar-light |
Jaune (change aussi navbar-dark en navbar-light) |
Exercice C — Enrichir la page d'accueil
Remplace le contenu de la <div class="container mt-5"> par quelque chose de plus sympa :
<div class="container mt-5">
<h1>🚀 Bienvenue sur [ton nom de site]</h1>
<p class="lead">Une plateforme créée pendant la Booster Class CESI.</p>
<a href="/articles" class="btn btn-primary me-2">Voir les articles</a>
<a href="/contact" class="btn btn-outline-secondary">Nous contacter</a>
</div>💡 Les classes
btn,btn-primary,lead,me-2viennent de Bootstrap — une bibliothèque qui fait le style à ta place !
Ouvre frontend/contact.html.
Exercice D — Ajouter un champ "Sujet"
Après le champ email, ajoute un nouveau champ :
<div class="mb-3">
<label for="subject" class="form-label">Sujet</label>
<input type="text" class="form-control" id="subject" placeholder="Ex: Question, Bug, Suggestion..." required>
</div>💡 Pour aller plus loin : tu pourrais aussi l'envoyer au back-end ! Il faudrait modifier
script.js,main.pyetmodels.py. C'est le Niveau 3 en miniature.
Exercice E — Changer le texte du bouton
Trouve :
<button type="submit" class="btn btn-primary">Envoyer</button>Essaie ces variantes :
btn-success→ bouton vertbtn-lg→ bouton plus grand- Remplace le texte par
📨 Envoyer le message
Ouvre frontend/static/style.css.
Il est presque vide ! Ajoute tes propres règles CSS :
/* Changer la couleur de fond de la page */
body {
background-color: #f8f9fa;
}
/* Ajouter une ombre aux cartes d'articles */
.card {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.2s;
}
/* Faire "lever" les cartes au survol */
.card:hover {
transform: translateY(-4px);
}
/* Style du titre principal */
h1 {
font-weight: 700;
color: #212529;
}Recharge la page et observe le résultat !
Durée estimée : 40 min
Actuellement, les articles peuvent être créés mais pas supprimés. Tu vas ajouter cette fonctionnalité de A à Z.
Ouvre backend/main.py.
Après la fonction create_article, ajoute cette nouvelle route :
@app.delete("/api/articles/{article_id}")
async def delete_article(article_id: int, db: Session = Depends(get_db)):
# 1. Chercher l'article dans la base de données
article = db.query(Article).filter(Article.id == article_id).first()
# 2. Si l'article n'existe pas, renvoyer une erreur
if article is None:
raise HTTPException(status_code=404, detail="Article non trouvé")
# 3. Supprimer l'article
db.delete(article)
db.commit()
# 4. Confirmer la suppression
return {"status": "Article supprimé"}Comprendre le code :
{article_id}dans l'URL : c'est une variable —/api/articles/3supprimera l'article n°3db.query(Article).filter(...): cherche dans la table articles.first(): prend le premier résultat (ouNonesi pas trouvé)HTTPException(status_code=404): renvoie une erreur "introuvable" standard
Ouvre http://localhost:8000/docs — FastAPI génère automatiquement une page de documentation interactive !
Tu peux tester ton endpoint DELETE /api/articles/{article_id} directement depuis cette page.
Ouvre frontend/articles.html.
Trouve le bloc qui affiche les articles :
<div class="card-body">
<h5 class="card-title">{{ article.title }}</h5>
<p class="card-text">{{ article.content[:100] }}...</p>
<p class="card-text"><small class="text-muted">Auteur: {{ article.author }}</small></p>
</div>Ajoute un bouton de suppression à l'intérieur du card-body, après les <p> :
<button
class="btn btn-danger btn-sm mt-2"
onclick="deleteArticle({{ article.id }})">
🗑️ Supprimer
</button>Ouvre frontend/static/script.js.
Ajoute cette fonction à la fin du fichier :
// Supprimer un article
async function deleteArticle(articleId) {
// Demander confirmation avant de supprimer
if (!confirm('Voulez-vous vraiment supprimer cet article ?')) {
return; // L'utilisateur a annulé
}
const response = await fetch('/api/articles/' + articleId, {
method: 'DELETE'
});
if (response.ok) {
alert('Article supprimé !');
// Recharger la page pour voir la liste mise à jour
location.reload();
} else {
alert('Erreur lors de la suppression.');
}
}- Va sur http://localhost:8000/create_article
- Crée un article de test
- Va sur http://localhost:8000/articles
- Clique sur "Supprimer" — l'article doit disparaître !
Si tu as terminé, essaie ces défis supplémentaires :
Défi A — Afficher les messages de contact
Ajoute une nouvelle page qui liste les messages reçus (comme articles.html mais pour les messages). Tu auras besoin de :
- Un nouvel endpoint
GET /api/messagesdansmain.py - Une nouvelle page
messages.htmldansfrontend/ - Un lien dans la navbar
Défi B — Compter les articles
Sur la page d'accueil (index.html), affiche le nombre total d'articles. Tu peux le faire en JavaScript avec fetch('/api/articles').
Défi C — Styliser les boutons de suppression
Au lieu d'un confirm(), crée une modale Bootstrap plus jolie. Cherche "Bootstrap modal" dans la documentation !
Il est temps de présenter ce que tu as fait au reste du groupe !
Prépare une présentation de 3 à 5 minutes qui répond à ces questions :
-
Qu'est-ce que tu as fait ?
- Quel(s) niveau(x) as-tu complété ?
- Quelle fonctionnalité as-tu ajoutée ou modifiée ?
-
Montre-le en live
- Lance ton application et démontre ce qui fonctionne
- N'aie pas peur si quelque chose ne marche pas — ça arrive à tous les devs !
-
Qu'est-ce que tu as appris ?
- Quel concept t'a surpris ?
- Quelle partie était la plus difficile ? La plus satisfaisante ?
-
Si tu avais plus de temps...
- Quelle fonctionnalité tu ajouterais en premier ?
💡 Conseil : Les développeurs font des démos tous les jours — c'est une compétence aussi importante que le code !
| Concept | Ce que c'est | Où tu l'as vu |
|---|---|---|
| HTML | Structure d'une page web | index.html, articles.html… |
| CSS | Style visuel | style.css + classes Bootstrap |
| JavaScript | Comportement interactif | script.js |
| Python/FastAPI | Serveur qui traite les requêtes | main.py |
| Base de données | Stockage persistant des données | database.db |
| API REST | Interface de communication front ↔ back | /api/articles, /api/contact |
| ORM | Parler à la BDD en Python (pas en SQL) | SQLAlchemy dans main.py |
| CRUD | Create / Read / Update / Delete | Les 4 opérations de base sur les données |
Journées Découverte Métiers — CESI École d'Ingénieurs — 2026 Célestin PRÉAULT — cpreault@cesi.fr