Chapitre 4.3 : Envoi de requêtes POST/PUT/DELETE
Temps d'étude : 1 heure
1. Commandes actives : Du lancement au déclassement
Jusqu'à présent, notre centre de contrôle (MCC) ne faisait que demander des informations (GET
). Nous allons maintenant apprendre à envoyer des commandes actives :
- POST : "Lancer un nouveau satellite en orbite !"
- PUT : "Effectuer une mise à niveau complète des systèmes de l'ISS !"
- DELETE : "Désorbiter l'ancien appareil
Debris-123
!"
Pour ce faire, nous utiliserons fetch
, mais avec des paramètres supplémentaires qui décrivent notre commande.
💡 Analogie spatiale :
Si
GET
est une écoute passive de la radio,POST
,PUT
etDELETE
sont une transmission active de commandes. Pour cela, il ne suffit pas d'indiquer la "fréquence" (URL), mais aussi le contenu de la commande (corps de la requête) et le protocole de communication (en-têtes).
2. Envoi d'une requête POST : Lancement d'un nouveau vaisseau
Pour créer une nouvelle ressource, nous envoyons une requête POST
. Le plus important ici est de transmettre le corps (body) de la requête avec les données du nouvel objet.
Étape 1 : Ajout du formulaire de création dans index.html
Plaçons-le après le bloc "Requête par ID".
<!-- index.html -->
<hr>
<h2>Lancer un nouvel appareil</h2>
<form id="create-ship-form">
<input type="text" id="create-name" placeholder="Nom" required><br>
<input type="text" id="create-type" placeholder="Type" required><br>
<input type="number" id="create-year" placeholder="Année de lancement" required><br>
<input type="text" id="create-status" placeholder="Statut" required><br>
<button type="submit">Lancer</button>
</form>
<div id="create-status-message"></div>
Étape 2 : Ajout de la logique dans app.js
// app.js, à la fin du fichier
const createShipForm = document.getElementById('create-ship-form');
const createStatusMessage = document.getElementById('create-status-message');
async function createShip(event) {
event.preventDefault();
// 1. Rassemble les données du formulaire dans un objet
const shipData = {
name: document.getElementById('create-name').value,
type: document.getElementById('create-type').value,
launch_year: parseInt(document.getElementById('create-year').value),
status: document.getElementById('create-status').value
};
try {
createStatusMessage.textContent = 'Envoi de la commande de lancement...';
// 2. Envoie la requête fetch avec les paramètres
const response = await fetch(`${API_BASE_URL}/spaceships`, {
method: 'POST', // Indique la méthode
headers: {
'Content-Type': 'application/json' // Indique au serveur que nous envoyons du JSON
},
body: JSON.stringify(shipData) // Convertit l'objet JavaScript en chaîne JSON
});
if (!response.ok) {
// Si le serveur a renvoyé une erreur, essaie de lire son corps
const errorData = await response.json();
throw new Error(errorData.detail || `Erreur serveur : ${response.status}`);
}
const newShip = await response.json();
createStatusMessage.textContent = `🚀 Lancement réussi ! L'appareil a l'ID : ${newShip.id}`;
createShipForm.reset(); // Efface le formulaire
fetchAndDisplayFleet(); // Met à jour la liste générale de la flotte
} catch (error) {
console.error('Erreur lors du lancement de l\'appareil :', error);
createStatusMessage.textContent = `🔴 Erreur : ${error.message}`;
}
}
createShipForm.addEventListener('submit', createShip);
fetch
pour POST :
method: 'POST'
: Il est impératif d'indiquer la méthode HTTP.headers: { 'Content-Type': 'application/json' }
: Cet en-tête est crucial. Il indique à notre serveur FastAPI que le corps de la requête contient du JSON et qu'il doit être analysé.body: JSON.stringify(shipData)
: Nous ne pouvons pas envoyer un objet JavaScript directement. Il doit être sérialisé (converti) en chaîne JSON.
3. Envoi d'une requête DELETE : Déclassement d'un appareil
La requête de suppression est plus simple : elle n'a généralement pas besoin de corps, seulement d'une URL avec l'ID de l'objet.
Étape 1 : Ajout du bouton "Supprimer" dans notre liste de vaisseaux
Modifions la fonction fetchAndDisplayFleet
dans app.js
pour qu'elle ajoute un bouton de suppression pour chaque élément.
// app.js, à l'intérieur de la fonction fetchAndDisplayFleet
// ...
ships.forEach(ship => {
const listItem = document.createElement('li');
// Ajoute un bouton avec un attribut data stockant l'ID
listItem.innerHTML = `
<strong>${ship.name} (ID: ${ship.id})</strong><br>
Type: ${ship.type} | Année: ${ship.launch_year} | Statut: ${ship.status}<br>
<button class="delete-btn" data-ship-id="${ship.id}">Déclasser l'appareil</button>
`;
fleetList.appendChild(listItem);
});
// ...
Étape 2 : Ajout d'un gestionnaire pour tous les boutons "Supprimer" Nous utilisons la délégation d'événements - un seul gestionnaire pour toute la liste.
// app.js, à la fin du fichier
async function deleteShip(shipId) {
if (!confirm(`Êtes-vous sûr de vouloir déclasser l'appareil avec l'ID ${shipId} ? Cette action est irréversible.`)) {
return;
}
try {
const response = await fetch(`${API_BASE_URL}/spaceships/${shipId}`, {
method: 'DELETE' // Indique la méthode
});
if (!response.ok) {
throw new Error(`Échec du déclassement de l'appareil. Statut : ${response.status}`);
}
alert(`L'appareil avec l'ID ${shipId} a été déclassé avec succès.`);
fetchAndDisplayFleet(); // Met à jour la liste
} catch (error) {
console.error('Erreur lors du déclassement :', error);
alert(`Erreur : ${error.message}`);
}
}
// Délégation d'événements : écoute les clics sur toute la liste
fleetList.addEventListener('click', (event) => {
// Vérifie si le clic a eu lieu sur un bouton avec la classe 'delete-btn'
if (event.target.classList.contains('delete-btn')) {
const shipId = event.target.dataset.shipId; // Récupère l'ID depuis l'attribut data
deleteShip(shipId);
}
});
Étape 3 : Ajout de l'id au modèle Spaceship
Ajoutez l'id aux modèles et à la base de données dans le fichier main.py
.
class Spaceship(BaseModel):
id: int
# Reste du code du modèle...
db_spaceships = {
1: {
"id": 1,
# Données de l'élément 1
},
2: {
"id": 2,
# Données de l'élément 2
},
3: {
"id": 3,
# Données de l'élément 3
}
}
method: 'DELETE'
: Indique la méthode. Le corps et les en-têtes ne sont pas nécessaires ici.confirm()
: Simple fenêtre de confirmation intégrée pour éviter de supprimer accidentellement quelque chose d'important.
4. Envoi d'une requête PUT (Tâche autonome)
L'implémentation d'une requête PUT
pour la mise à jour est très similaire à POST
.
Votre mission, si vous choisissez de l'accepter :
- Ajouter un bouton "Modifier" à côté du bouton "Supprimer" pour chaque vaisseau.
- Lorsque vous cliquez sur "Modifier", remplissez le formulaire (vous pouvez utiliser le même que pour la création) avec les données actuelles du vaisseau.
- Modifiez le texte du bouton "Lancer" en "Mettre à jour".
- Lors de la soumission du formulaire, envoyez une requête
PUT
à/spaceships/{id}
avec le corps complet de l'objet. - Après une mise à jour réussie, mettez à jour la liste de la flotte.
Indice : Vous aurez besoin de
fetch
avecmethod: 'PUT'
, les en-têtesContent-Type
etbody
avecJSON.stringify()
, exactement comme dans la requêtePOST
.
Quiz pour la consolidation
resultsHTML += </ul><p><b>Votre score : ${score} sur ${Object.keys(correctAnswers).length}</b></p>
;
resultsContainer.innerHTML = resultsHTML;
resultsContainer.style.display = 'block';
}
🚀 Résumé du chapitre :
Votre Centre de Contrôle de Mission (CCM) dispose maintenant d'un ensemble complet de commandes pour gérer la flotte !
- ✅ Vous avez appris à envoyer des requêtes
POST
avec un corps et des en-têtes pour créer de nouvelles ressources. - ✅ Vous avez implémenté des requêtes
DELETE
pour désactiver les appareils obsolètes. - ✅ Vous avez reçu la tâche d'implémenter une requête
PUT
, consolidant ainsi vos connaissances.
Le contrôle total est établi ! Mais que faire si la connexion est interrompue ou si le serveur signale une erreur ? Dans le prochain chapitre, nous allons créer un système centralisé de gestion des erreurs côté front-end.
📌 Vérification :
- Assurez-vous que le formulaire de création d'un nouveau vaisseau fonctionne et qu'après une création réussie, la liste sur la page est mise à jour.
- Vérifiez que le bouton "Désactiver l'appareil" fonctionne, demande confirmation et supprime le vaisseau de la liste.
- Essayez de créer un vaisseau avec des données non valides (par exemple, avec un nom très court) et observez l'erreur que votre serveur FastAPI renverra.
⚠️ En cas d'erreurs :
- Erreur
422
du serveur : Il est probable que les données que vous envoyez ne passent pas la validation Pydantic. Vérifiez la console du navigateur —errorData.detail
indiquera le champ problématique.- Erreur
415 Unsupported Media Type
: Vous avez oublié d'ajouter l'en-tête'Content-Type': 'application/json'
.- Les boutons de suppression ne fonctionnent pas : Vérifiez si la délégation d'événements fonctionne correctement et si vous récupérez correctement
shipId
à partir dedata-ship-id
.