Guide De Base pour l'Utilisation de Requêtes Ajax dans un Contexte d'API REST avec Flask

Publié le : 22/01/24
Modifié le : 04/06/24 à 10h58

emoji_objects

Documentation officielle de Flask : link Documentation officielle de jQuery : link Documentation officielle de Vue.js 3 : link

emoji_objects

On doit s'assurer de disposer des éléments suivants :
- Deux serveurs Flask fonctionnant correctement et en communication.
- Le package requests installé.
- jQuery opérationnel.

Requête Get Sans Paramètre


Nous allons débuter par la requête GET sans paramètre. Cette requête vise à obtenir des données de l'API REST.
Dans notre exemple, nous utilisons une méthode qui effectue une requête Ajax pour récupérer une ressource.
Commençons par examiner le code Ajax :

Code Ajax

                            
                                function requeteGetSansParametre() {    
                                    $.ajax({
                                        url: 'client/get/ressource', 
                                        method: 'GET',
                                        dataType: 'json',                           
                                        success: function(response) {
                                            if(response.status == 200) {
                                                console.log(response.data);
                                            }
                                        },
                                        error: function(xhr, textStatus, errorThrown) {
                                            var errorMessage = 'Erreur inconnue';

                                            // Vérifie si la réponse est du JSON
                                            if (xhr.status && xhr.responseJSON && xhr.responseJSON.error) {
                                                errorMessage = xhr.responseJSON.error;
                                            } else if (xhr.status) {
                                                // Si la réponse n'est pas du JSON, utilise le statut HTTP
                                                errorMessage = "Erreur HTTP " + xhr.status + ": " + (errorThrown ? errorThrown : "Erreur inconnue");
                                            } else if (textStatus !== 'error') {
                                                // Erreur avec un texte d'état fourni par jQuery
                                                errorMessage = textStatus;
                                            } else if (errorThrown) {
                                                // Message d'erreur par défaut fourni par le navigateur
                                                errorMessage = errorThrown;
                                            }

                                            console.log(errorMessage);
                                        },
                                        complete: function() {
                                            console.log('Requête complétée');
                                        }
                                    });
                                } 
                            
                            
emoji_objects

- Ce type de requête permet de récupérer une ressource stockée sur le serveur distant.
Dans cette requête, aucun paramètre n'est inclus, car nous savons ce que nous attendons et gérons cette ressource côté frontend, par exemple en l'affichant.
- La gestion des erreurs indiquée ici est exhaustive, on peut l'adapter selon les besoins.

Le serveur Flask reçoit ces requêtes AJAX et les transmet au serveur API final.
Examinons maintenant comment cela se déroule du côté de la route Flask :

Route Flask

                            
                            from flask import request, jsonify
                            import requests

                            @app.route('/client/get/ressource', methods=['GET'])
                            def get_sans_parametre():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'GET':
                                    api_url = f"{server_distant_url}/api/get/ressource"
                                    try:
                                        response = requests.get(api_url)
                                        response.raise_for_status()
                                        return response.json()
                                    except requests.exceptions.RequestException as e:
                                        error_message = f"Erreur de requête vers l'URL distante : {str(e)}"
                                        return jsonify({
                                            "status": 500, 
                                            "error": error_message
                                        }), 500
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            
emoji_objects

- methods=['GET'] : Cette ligne indique le type de requête que la route attend, et il est possible d'en spécifier plusieurs pour la même route.
- api_url : Il s'agit de l'URL du serveur distant API.
- requests.get(api_url) : Ce code effectue la requête vers le serveur API.
- response.raise_for_status() : Cette instruction génère une exception en cas d'erreur.
- return response.json() : Cette ligne renvoie la ressource récupérée au format JSON.

Nous avons donc examiné le code Ajax qui envoie une demande de requête HTTP au serveur Flask "local".
Nous avons également étudié la route Flask du serveur "local" qui envoie cette requête et renvoie la réponse reçue de l'API distante.
Maintenant, nous allons explorer comment l'API gère cette requête et comment elle renvoie la réponse.

Route API

                            
                            from flask import request, jsonify
                            import requests

                            @app.route('/api/get/ressource', methods=['GET'])
                            def get_sans_parametre():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'GET':
                                    data = "Réponse de la part du serveur."
                                    response = {
                                        "status": 200,
                                         "data": data
                                    }
                                    return jsonify(response), 200
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            
emoji_objects

- if request.method == 'GET': Nous commençons par vérifier que l'utilisateur utilise la méthode appropriée pour interagir avec cette route.
- Nous construisons la réponse dans un bloc try, puis nous la renvoyons.
- jsonify(response), 200 : La fonction jsonify permet de renvoyer la réponse au format JSON, et le code "200" correspond au statut de réussite de la requête HTTP.

Voici un exemple d'utilisation très élémentaire :

Code FrontEnd

                            
                            <div class="test">
                                <button onclick="requeteGetSansParametre()" class="btn btn-primary">Bouton de teste</button>
                                <p id="print-result" class="mt-4"></p>
                            </div>
                            
                            

Requête Get Avec Paramètre(s)


Nous allons maintenant explorer une requête GET avec un paramètre. Cette requête vise à obtenir une donnée de l'API REST en spécifiant un paramètre.
Commençons par examiner le code Ajax :

Code Ajax

                            
                                function requeteGetAvecParametres() {    
                                    $.ajax({
                                        url: 'client/get/ressource/parametres',
                                        type: 'GET',
                                        data: {
                                            param1: 'une requête',
                                            param2: 'avec paramètres'
                                        },
                                        dataType: 'json',
                                        success: function(response) {
                                            if(response.status == 200) {
                                                console.log(response.data);
                                                $("#print-result").html(response.data);
                                            }
                                        },
                                        error: function(xhr, textStatus, errorThrown) {
                                            var errorMessage = 'Erreur inconnue';

                                            // Vérifie si la réponse est du JSON
                                            if (xhr.status && xhr.responseJSON && xhr.responseJSON.error) {
                                                errorMessage = xhr.responseJSON.error;
                                            } else if (xhr.status) {
                                                // Si la réponse n'est pas du JSON, utilise le statut HTTP
                                                errorMessage = "Erreur HTTP " + xhr.status + ": " + (errorThrown ? errorThrown : "Erreur inconnue");
                                            } else if (textStatus !== 'error') {
                                                // Erreur avec un texte d'état fourni par jQuery
                                                errorMessage = textStatus;
                                            } else if (errorThrown) {
                                                // Message d'erreur par défaut fourni par le navigateur
                                                errorMessage = errorThrown;
                                            }

                                            console.log(errorMessage);
                                        },
                                        complete: function() {
                                            console.log('Requête complétée');
                                        }
                                    });
                                } 
                            
                            
emoji_objects

- Dans ce code, data contient les paramètres que nous souhaitons envoyer. jQuery les convertira automatiquement en une chaîne de requête et les attachera à l'URL.
- Pour les requêtes GET, il n'est ni courant ni recommandé d'envoyer des données au format JSON dans le corps de la requête. Les requêtes GET sont conçues pour récupérer des données du serveur et utilisent généralement les paramètres de l'URL.

Passons maintenant à la route Flask du serveur "local" qui récupérera les données envoyées par la requête Ajax.

Route Flask

                            
                            @app.route('/client/get/ressource/parametres', methods=['GET'])
                            def get_avec_parametre():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'GET':
                                    param1 = request.args.get('param1', default=None, type=str)
                                    param2 = request.args.get('param2', default=None, type=str)

                                    # Préparer l'URL avec les paramètres pour la requête au serveur final
                                    api_url = f"{server_back_end_url}/api/get/ressource/parametres"
                                    params = {'param1': param1, 'param2': param2}

                                    try:
                                        # Inclure les paramètres dans la requête
                                        response = requests.get(api_url, params=params)
                                        response.raise_for_status()
                                        return response.json()
                                    except requests.exceptions.RequestException as e:
                                        error_message = f"Erreur de requête vers l'URL distante : {str(e)}"
                                        return jsonify({
                                            "status": 500, 
                                            "error": error_message
                                        }), 500

                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            

La route Flask récupère les deux paramètres transmis par Ajax et effectue la requête vers le serveur distant.
Passons maintenant à la gestion de cette requête sur le serveur distant.

Code API

                            
                            @app.route('/api/get/ressource/parametres', methods=['GET'])
                            def get_avec_parametre():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'GET':
                                    # Récupérer les paramètres de la requête
                                    param1 = request.args.get('param1', default=None, type=str)
                                    param2 = request.args.get('param2', default=None, type=str)
                                    
                                    # Créer une réponse
                                    response = {
                                        'status': 200,
                                        'data': f'Paramètres reçus avec succès : {param1}, {param2}'
                                    }
                                    return jsonify(response), 200
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            
emoji_objects

- Nous n'utilisons pas de bloc try: pour les opérations request.args.get, car ces opérations sont généralement fiables et peu susceptibles de générer des exceptions.
- Robustesse de request.args.get : La méthode get de request.args est conçue pour être robuste et gérer les situations où les paramètres ne sont pas présents.

Requête POST


Après avoir examiné les deux requêtes GET, passons maintenant à la requête POST.
Dans le contexte HTTP, la requête POST est utilisée pour créer une nouvelle ressource sur le serveur distant.
Commençons par explorer le code Ajax :

Code Ajax

                            
                            function requetePOST() {    
                                // Données à envoyer dans la requête POST
                                var donnees = {
                                    nom: 'ILLOURMANE',
                                    prenom: 'Mahmoud',
                                    age: 25
                                };
                                    
                                // Envoi de la requête AJAX avec les données préparées
                                $.ajax({
                                    url: 'client/post',
                                    type: 'POST',
                                    contentType: 'application/json',
                                    data: JSON.stringify(donnees),
                                    dataType: 'json',
                                    success: function(response) {
                                        if(response.status == 200) {
                                            console.log(response.data);
                                            $("#print-result").html(response.data);
                                        }
                                    },
                                    error: function(xhr, textStatus, errorThrown) {
                                        var errorMessage = 'Erreur inconnue';

                                        // Vérifie si la réponse est du JSON
                                        if (xhr.status && xhr.responseJSON && xhr.responseJSON.error) {
                                            errorMessage = xhr.responseJSON.error;
                                        } else if (xhr.status) {
                                            // Si la réponse n'est pas du JSON, utilise le statut HTTP
                                            errorMessage = "Erreur HTTP " + xhr.status + ": " + (errorThrown ? errorThrown : "Erreur inconnue");
                                        } else if (textStatus !== 'error') {
                                            // Erreur avec un texte d'état fourni par jQuery
                                            errorMessage = textStatus;
                                        } else if (errorThrown) {
                                            // Message d'erreur par défaut fourni par le navigateur
                                            errorMessage = errorThrown;
                                        }

                                        console.log(errorMessage);
                                    },
                                    complete: function() {
                                        console.log('Requête complétée');
                                    }
                                });
                            }
                            
                            
emoji_objects

- JSON.stringify : Cette fonction transforme la donnée en une chaîne JSON.

La requête Ajax est effectuée, passons maintenant à la route Flask.

Route Flask

                            
                            @app.route('/client/post', methods=['POST'])
                            def post_data():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'POST':
                                    # Récupérer les données envoyées en JSON
                                    data = request.get_json()
                            
                                    # Traitement des données, exemple : log, validation, etc.
                            
                                    api_url = f"{server_back_end_url}/api/post"
                                    try:
                                        response = requests.post(api_url, json=data)
                                        response.raise_for_status()
                                        return response.json()
                                    except requests.exceptions.RequestException as e:
                                        error_message = f"Erreur de requête vers l'URL distante : {str(e)}"
                                        return jsonify({
                                            "status": 500, 
                                            "error": error_message
                                        }), 500
                                        
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            

Les données ont été transmises à la route de l'API. À présent, explorons comment elles sont traitées sur le serveur distant.

Code API

                            
                            @app.route('/api/post', methods=['POST'])
                            def receive_data():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'POST':
                                    try:
                                        # Récupérer les données POST envoyées par le serveur intermédiaire
                                        data = request.get_json()
                                
                                        # Effectuer des opérations avec ces données

                                        # Renvoyer une réponse
                                        response = {
                                            'status': 200,
                                            'data': f'Paramètres reçus avec succès : {data['nom']}, {data['prenom']}, {data['age']}'
                                        }
                                        return jsonify(response), 200
                                    except Exception as e:
                                        return jsonify({
                                            "status": 500, 
                                            "error": str(e)
                                        }), 500
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            

Requête DELETE


Passons maintenant à la requête DELETE.
Dans le contexte HTTP, la requête DELETE est utilisée pour supprimer une ressource sur le serveur distant.
Commençons par explorer le code Ajax :

Code Ajax

                            
                            function requeteDELETE() { 
                                // Dans l'url
                                var idASupprimer = 123; 
                    
                                $.ajax({
                                    url: 'client/delete/' + idASupprimer,
                                    type: 'DELETE',
                                    success: function(response) {
                                        if(response.status == 200) {
                                            $("#print-result").html(response.data);
                                        }
                                    },
                                    error: function(xhr, textStatus, errorThrown) {
                                        var errorMessage = 'Erreur inconnue';

                                        // Vérifie si la réponse est du JSON
                                        if (xhr.status && xhr.responseJSON && xhr.responseJSON.error) {
                                            errorMessage = xhr.responseJSON.error;
                                        } else if (xhr.status) {
                                            // Si la réponse n'est pas du JSON, utilise le statut HTTP
                                            errorMessage = "Erreur HTTP " + xhr.status + ": " + (errorThrown ? errorThrown : "Erreur inconnue");
                                        } else if (textStatus !== 'error') {
                                            // Erreur avec un texte d'état fourni par jQuery
                                            errorMessage = textStatus;
                                        } else if (errorThrown) {
                                            // Message d'erreur par défaut fourni par le navigateur
                                            errorMessage = errorThrown;
                                        }

                                        console.log(errorMessage);
                                    },
                                    complete: function() {
                                        console.log('Requête complétée');
                                    }
                                });
                            }
                            
                            
emoji_objects

- L'identifiant (ID) est transmis dans l'URL.

La requête Ajax a été effectuée, passons maintenant à la route Flask.

Route Flask

                            
                            @app.route('/client/delete/', methods=['DELETE'])
                            def delete_data(id):
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'DELETE':
                                    api_url = f"{server_back_end_url}/api/delete/{id}"
                                    try:
                                        response = requests.delete(api_url)
                                        response.raise_for_status()
                                        return response.json()
                                    except requests.exceptions.RequestException as e:
                                        error_message = f"Erreur de requête vers l'URL distante : {str(e)}"
                                        return jsonify({
                                            "status": 500, 
                                            "error": error_message
                                        }), 500
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            

L'identifiant (ID) a été transmis à la route de l'API. À présent, explorons comment il est géré sur le serveur distant.

Code API

                            
                            @app.route('/api/delete/', methods=['DELETE'])
                            def delete_data(id):
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'DELETE':
                                    # Traiter la demande de suppression ici
                                    
                                    # Renvoyer une confirmation de suppression
                                    response = {
                                        'status': 200,
                                        'data': f'Élément avec l\'ID {id} supprimé.'
                                    }
                                    return jsonify(response), 200
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            

Requête DELETE avec plusieurs IDs


Après avoir examiné la requête Ajax qui permet de transmettre l'ID de la ressource à supprimer dans l'URL, nous allons maintenant voir un exemple où plusieurs IDs sont transmis à supprimer sous forme JSON.
Commençons par explorer le code Ajax :

Code Ajax

                            
                            function requeteDELETE() { 
                                var idsASupprimer = [123, 456, 789]; // Remplace ceci par les IDs réels à supprimer

                                $.ajax({
                                    url: 'client/deletes/',
                                    type: 'DELETE',
                                    contentType: 'application/json',
                                    data: JSON.stringify({ ids: idsASupprimer }),
                                    success: function(response) {
                                        if(response.status == 200) {
                                            $("#print-result").html(response.data);
                                        }
                                    },
                                    error: function(xhr, textStatus, errorThrown) {
                                        var errorMessage = 'Erreur inconnue';

                                        // Vérifie si la réponse est du JSON
                                        if (xhr.status && xhr.responseJSON && xhr.responseJSON.error) {
                                            errorMessage = xhr.responseJSON.error;
                                        } else if (xhr.status) {
                                            // Si la réponse n'est pas du JSON, utilise le statut HTTP
                                            errorMessage = "Erreur HTTP " + xhr.status + ": " + (errorThrown ? errorThrown : "Erreur inconnue");
                                        } else if (textStatus !== 'error') {
                                            // Erreur avec un texte d'état fourni par jQuery
                                            errorMessage = textStatus;
                                        } else if (errorThrown) {
                                            // Message d'erreur par défaut fourni par le navigateur
                                            errorMessage = errorThrown;
                                        }

                                        console.log(errorMessage);
                                    },
                                    complete: function() {
                                        console.log('Requête complétée');
                                    }
                                });
                            }
                            
                            

La requête Ajax a été effectuée, passons maintenant à la route Flask.

Route Flask

                            
                            @app.route('/client/deletes', methods=['DELETE'])
                            def delete_data_ids():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'DELETE':
                                    api_url = f"{server_back_end_url}/api/deletes"
                                    try:
                                        data = request.get_json()
                                        ids = data.get('ids')
                                            
                                        # Envoi de la requête DELETE au serveur final avec les IDs en JSON
                                        response = requests.delete(api_url, json={'ids': ids})
                                        response.raise_for_status()
                                        return response.json()
                                    except requests.exceptions.RequestException as e:
                                        error_message = f"Erreur de requête vers l'URL distante : {str(e)}"
                                        return jsonify({
                                            "status": 500, 
                                            "error": error_message
                                        }), 500
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405    
                            
                            

L'identifiant (ID) a été transmis à la route de l'API. À présent, explorons comment il est géré sur le serveur distant.

Code API

                            
                            @app.route('/api/deletes', methods=['DELETE'])
                            def delete_data_ids():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'DELETE':
                                    try:
                                        data = request.get_json()
                                        ids = data.get('ids')
                            
                                        # Traiter les demandes de suppressions ici
                            
                                        # Renvoyer une confirmation de suppression
                                        response = {
                                            'status': 200,
                                            'data': f'Éléments supprimés : {ids}.'
                                        }
                                        return jsonify(response), 200
                                    except Exception as e:
                                        return jsonify({
                                            "status": 500, 
                                            "error": str(e)
                                        }), 500
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            

Requête PUT


Passons maintenant à la requête PUT.
Dans le contexte HTTP, la requête PUT est utilisée pour mettre à jour une ressource existante sur le serveur distant.
Commençons par explorer le code Ajax :

Code Ajax

                            
                            function requetePUT() { 
                                var dataAModifier = {
                                    id: 123, // L'ID de l'élément à modifier
                                    nouvellesDonnees: { 
                                        attribut1: 'nouvelleValeur1',
                                        attribut2: 'nouvelleValeur2'
                                        // Ajoute ici d'autres attributs à modifier
                                    }
                                };
                                
                                $.ajax({
                                    url: 'http://monserveurflask.com/api/put',
                                    type: 'PUT',
                                    contentType: 'application/json',
                                    data: JSON.stringify(dataAModifier),
                                    success: function(response) {
                                        console.log('Succès : ', response);
                                    },
                                    error: function(xhr, textStatus, errorThrown) {
                                        var errorMessage = 'Erreur inconnue';

                                        // Vérifie si la réponse est du JSON
                                        if (xhr.status && xhr.responseJSON && xhr.responseJSON.error) {
                                            errorMessage = xhr.responseJSON.error;
                                        } else if (xhr.status) {
                                            // Si la réponse n'est pas du JSON, utilise le statut HTTP
                                            errorMessage = "Erreur HTTP " + xhr.status + ": " + (errorThrown ? errorThrown : "Erreur inconnue");
                                        } else if (textStatus !== 'error') {
                                            // Erreur avec un texte d'état fourni par jQuery
                                            errorMessage = textStatus;
                                        } else if (errorThrown) {
                                            // Message d'erreur par défaut fourni par le navigateur
                                            errorMessage = errorThrown;
                                        }

                                        console.log(errorMessage);
                                    },
                                    complete: function() {
                                        console.log('Requête complétée');
                                    }
                                });
                            }
                            
                            

La requête Ajax a été effectuée, passons maintenant à la route Flask.

Route Flask

                            
                            @app.route('/client/put', methods=['PUT'])
                            def update_data():
                                """
                                    DOCUMENTATION.
                                """
                                if request.method == 'PUT':
                                    try:
                                        data = request.get_json()
                                        id = data.get('id')
                                        nouvellesDonnees = data.get('nouvellesDonnees')
                            
                                        api_url = f"{server_back_end_url}/api/put/{id}"
                                        # Envoyer la requête PUT au serveur final avec l'ID et les nouvelles données
                                        response = requests.put(api_url, json=nouvellesDonnees)
                                        return jsonify(response.json())
                                    except requests.exceptions.RequestException as e:
                                        error_message = f"Erreur de requête vers l'URL distante : {str(e)}"
                                        return jsonify({
                                            "status": 500, 
                                            "error": error_message
                                        }), 500
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405
                            
                            

L'identifiant (ID) et les données à mettre à jour ont été transmis à la route de l'API. À présent, explorons comment ils sont gérés sur le serveur distant.

Code API

                            
                            @app.route('/api/put/', methods=['PUT'])
                            def update_item(id):
                                if request.method == 'PUT':
                                    try:
                                        nouvellesDonnees = request.get_json()
                                    
                                        # Traiter la mise à jour ici pour l'élément avec l'ID fourni
                                
                                        response = {
                                            'status': 200,
                                            'data': f'Éléments modifiés : id: {id}, valeurs : {nouvellesDonnees}'
                                        }
                                        return jsonify(response)
                                    except Exception as e:
                                        return jsonify({
                                            "status": 500, 
                                            "error": str(e)
                                        }), 500
                                return jsonify({
                                    "status": 405, 
                                    "error": "Method Not Allowed"
                                }), 405