Créez votre propre API en utilisant Flask (Partie 2 & fin)

Créez votre propre API en utilisant Flask (Partie 2 & fin)

Hello 👋🏿, c'est Yémalin🤓. Dans la première partie de notre série d'articles, nous avons jeté les bases de notre projet en mettant en place la structure du projet, en créant une interface pour gérer nos contacts, et en définissant les endpoints de notre API dans le fichier contact.py. Maintenant, dans cette deuxième partie, nous allons nous concentrer sur l'implémentation du contenu de ces fonctions pour les rendre pleinement fonctionnelles.

Chaque fonction dans notre fichier contact.py correspond à un endpoint spécifique de notre API. Par exemple, nous avons un endpoint pour récupérer tous les contacts, un autre pour créer un nouveau contact, un autre pour mettre à jour un contact existant, et ainsi de suite. Maintenant, notre tâche consiste à compléter le code de chaque fonction en y ajoutant la logique nécessaire pour effectuer les opérations CRUD sur notre collection de contacts.

Nous allons utiliser les méthodes de notre interface ContactInterface que nous avons créée précédemment pour interagir avec notre base de données. Par exemple, pour récupérer tous les contacts, nous utiliserons la méthode get_all_contacts() de notre interface. Pour créer un nouveau contact, nous utiliserons la méthode create_contact(), et ainsi de suite.

En implémentant le contenu de ces fonctions, nous donnerons vie à notre API en permettant aux clients de communiquer avec notre application et d'effectuer des actions sur notre collection de contacts. Restez avec nous dans cette deuxième partie de notre tutoriel pour découvrir comment concrétiser ces fonctionnalités et rendre notre API Flask pleinement opérationnelle.

Avant de commencer, j'ai créé un référentiel GitHub où vous pouvez trouver le code complet de l'API de gestion de carnet d'adresses que nous allons développer dans cet article. Vous pouvez accéder au référentiel en suivant ce lien : lien vers le référentiel GitHub. N'hésitez pas à y jeter un coup d'œil pour consulter le code source et suivre les étapes de développement en parallèle."

#Implémentation des fonctionnalités de l'API (CRUD)


Dans le fichier contact.py....

#Create

@contact_request.route('/create', methods=['POST'])
def create_contact():
    """
    Route pour créer un nouveau contact
    Méthode : POST
    """

Dans cette partie, nous définissons une route /contacts/create avec la méthode POST pour créer un nouveau contact. Lorsque cette route est appelée, les données du contact seront envoyées en tant que requête JSON.

Pour récupérer ces données, nous utilisons request.get_json(). Cela nous permet de transformer les données JSON de la requête en un objet Python que nous pouvons manipuler facilement.

    data = request.get_json()

Ensuite, nous utilisons l'interface ContactInterface pour créer un nouveau contact en utilisant les données que nous avons obtenues de la requête. L'interface fournit des méthodes pour effectuer les opérations CRUD (Create, Read, Update, Delete) sur notre collection de contacts.

Dans ce cas, nous appelons la méthode create_contact() de l'interface en lui passant les données du contact. Cette méthode est responsable de créer le nouveau contact dans notre collection de contacts.

    new_contact = ContactInterface().create_contact(data)

Enfin, nous renvoyons le nouveau contact créé en tant que réponse JSON. Pour cela, nous utilisons jsonify(), qui convertit l'objet Python en une représentation JSON. Cela nous permet de renvoyer les données du contact de manière structurée.

    return jsonify(new_contact), 201

La réponse est renvoyée avec le code de statut 201, ce qui indique que la création a été effectuée avec succès.

Le code de statut est un nombre à trois chiffres renvoyé par le serveur HTTP en réponse à une requête. Il indique l'état de la requête et de la réponse, permettant ainsi au client de comprendre si la requête a été traitée avec succès ou s'il y a eu des erreurs.

Voici trois exemples courants de codes de statut HTTP :

  1. Code de statut 200 - OK : Ce code indique que la requête a été traitée avec succès. Cela signifie que la requête a été comprise par le serveur et que la réponse renvoyée est conforme aux attentes. Par exemple, lorsqu'un client effectue une requête GET pour récupérer des données, si les données sont disponibles et renvoyées correctement, le serveur peut renvoyer le code de statut 200 - OK.

  2. Code de statut 404 - Not Found : Ce code indique que la ressource demandée n'a pas été trouvée sur le serveur. Cela se produit lorsque le serveur ne peut pas localiser la ressource correspondante à l'URL spécifiée dans la requête. Par exemple, si un client effectue une requête GET pour récupérer un contact spécifique par son ID, mais que cet ID n'existe pas dans la base de données, le serveur peut renvoyer le code de statut 404 - Not Found.

  3. Code de statut 500 - Internal Server Error : Ce code indique qu'une erreur interne s'est produite sur le serveur qui a empêché le traitement de la requête. Cela peut se produire en raison d'un bogue dans le code du serveur, d'un problème de configuration ou d'autres raisons techniques. Lorsqu'une telle erreur se produit, le serveur peut renvoyer le code de statut 500 - Internal Server Error pour indiquer qu'il y a eu un problème inattendu.

Il existe de nombreux autres codes de statut HTTP qui fournissent des informations supplémentaires sur l'état de la requête et de la réponse. Ces codes aident les clients et les serveurs à communiquer de manière précise lorsqu'ils interagissent via le protocole HTTP.

Pour plus d'informations sur les différents codes de statut HTTP et leur signification, vous pouvez consulter la documentation officielle de la spécification HTTP. Elle fournit une liste complète des codes de statut, ainsi que des explications détaillées sur leur utilisation et leur interprétation.

Du coup, notre fonction de création ressemble à ça:

@contact_request.route('/create', methods=['POST'])
def create_contact():
    """
    Route pour créer un nouveau contact
    Méthode : POST
    """
    # Obtenir les données du contact à partir de la requête
    data = request.get_json()

    # Utilisation de l'interface pour créer un nouveau contact
    new_contact = ContactInterface().create_contact(data)

    # Renvoyer le nouveau contact créé sous forme de réponse JSON
    return jsonify(new_contact), 201

#Update

@contact_request.route('/update', methods=['PUT'])
def update_contact():
    """
    Route pour mettre à jour un contact existant
    Méthode : PUT
    """
    # Implémentation pour mettre à jour un contact existant

Dans cette fonction, nous utilisons la méthode request.get_json() pour récupérer les données du contact à mettre à jour à partir de la requête HTTP. Nous vérifions également si les données sont présentes et si l'ID du contact est fourni.

    data = request.get_json()

    if not data:
        return jsonify(message="Données de contact manquantes"), 400
    contact_id = data.get('id')

    if not contact_id:
        return jsonify(message="ID de contact manquant"), 400

Ensuite, nous construisons un dictionnaire update_contact avec les informations mises à jour du contact. Nous vérifions également les champs spécifiés pour nous assurer qu'ils sont présent avant de les ajouter au dictionnaire.

updated_contact = {}

if 'fullname' in data:
    updated_contact['fullname'] = data.get('fullname')

if 'email' in data:
    updated_contact['email'] = data.get('email')

if 'phone' in data:
    updated_contact['phone'] = data.get('phone')

Nous utilisons ensuite la méthode update_contact() de notre interface ContactInterface pour effectuer la mise à jour du contact dans la collection. Si le contact est introuvable, nous renvoyons une réponse JSON avec un message indiquant que le contact n'a pas été trouvé et un code de statut HTTP 404 (Non trouvé). Sinon, nous renvoyons une réponse JSON avec un message de succès et un code de statut HTTP 200 (OK) pour indiquer que la mise à jour a été effectuée avec succès.

     filter = {'_id': ObjectId(contact_id)}
     result = ContactInterface().update_contact(filter, updated_contact)

    if not result:
        return jsonify(message="Contact non trouvé"), 404

    return jsonify(message="Contact mis à jour avec succès"), 200

Voici à quoi ressemble le code de notre fonction:

@contact_request.route('/update', methods=['PUT'])
def update_contact():
    """
    Route pour mettre à jour un contact existant
    Méthode : PUT
    """
    data = request.get_json()

    if not data:
        return jsonify(message="Données de contact manquantes"), 400

    contact_id = data.get('id')

    if not contact_id:
        return jsonify(message="ID de contact manquant"), 400

    updated_contact = {}

    if 'fullname' in data:
        updated_contact['fullname'] = data.get('fullname')

    if 'email' in data:
        updated_contact['email'] = data.get('email')

    if 'phone' in data:
        updated_contact['phone'] = data.get('phone')
    filter = {'_id': ObjectId(contact_id)}
    result = ContactInterface().update_contact(filter, updated_contact)

    if not result:
        return jsonify(message="Contact non trouvé"), 404

    return jsonify(message="Contact mis à jour avec succès"), 200

#Delete

@contact_request.route('/delete', methods=['DELETE'])
def delete_contact():
    """
    Route pour supprimer un contact
    Méthode : DELETE
    """
    # Implémentation pour supprimer un contact

Comme d'habitude, pour récupérer les données du contact à supprimer, nous utilisons la méthode request.get_json(). Nous vérifions également si les données sont présentes et si l'ID du contact est fourni.

data = request.get_json()

    if not data:
        return jsonify(message="Données de contact manquantes"), 400

    contact_id = data.get('id')

    if not contact_id:
        return jsonify(message="ID de contact manquant"), 400

Lorsque vous souhaitez récupérer des informations à partir d'un dictionnaire en utilisant la méthode get(), vous pouvez spécifier une valeur par défaut à renvoyer si la clé n'est pas présente dans le dictionnaire. Par exemple :

data = {
    "name": "John",
    "age": 30
}

name = data.get("name", "N/A")
print(name)  # Affiche "John"

city = data.get("city", "N/A")
print(city)  # Affiche "N/A" car "city" n'est pas une clé présente dans le dictionnaire

Alors, où en étions-nous ? 🤔 Ah, voilà delete....
Nous utilisons la méthode delete_contact() de notre interface ContactInterface pour supprimer le contact de la collection. Si le contact est introuvable, nous renvoyons une réponse JSON avec un message indiquant que le contact n'a pas été trouvé et un code de statut HTTP 404 (Non trouvé). Sinon, nous renvoyons une réponse JSON avec un message de succès et un code de statut HTTP 200 (OK) pour indiquer que la suppression a été effectuée avec succès.

filter = {'_id': ObjectId(contact_id)}
result = ContactInterface().delete_contact(filter)

    if not result:
        return jsonify(message="Contact non trouvé"), 404

    return jsonify(message="Contact supprimé avec succès"), 200

Voici à quoi ressemble le code de notre fonction:

@contact_request.route('/delete', methods=['DELETE'])
def delete_contact():
    """
    Route pour supprimer un contact
    Méthode : DELETE
    """
    data = request.get_json()

    if not data:
        return jsonify(message="Données de contact manquantes"), 400

    contact_id = data.get('id')

    if not contact_id:
        return jsonify(message="ID de contact manquant"), 400

    filter = {'_id': ObjectId(contact_id)}
    result = ContactInterface().delete_contact(filter)

    if not result:
        return jsonify(message="Contact non trouvé"), 404

    return jsonify(message="Contact supprimé avec succès"), 200

#Read all

@contact_request.route('/', methods=['GET'])
def get_all_contacts():
    """
    Route pour récupérer tous les contacts
    Méthode : GET
    """
    # Implémentation pour renvoyer tous les contacts

La route "/contacts" avec la méthode GET est utilisée pour récupérer tous les contacts de notre collection. Dans cette fonction, nous utilisons la méthode get_all_contacts() de notre interface ContactInterface pour obtenir tous les contacts.

    contacts = ContactInterface().get_all_contacts()

Ensuite, nous vérifions si la liste de contacts est vide. Si elle est vide, cela signifie qu'il n'y a aucun contact enregistré. Dans ce cas, nous renvoyons une réponse JSON avec un message d'erreur approprié et un code de statut HTTP correspondant (404 😌).

if not contacts:
        return jsonify(message="Aucun contact trouvé"), 404

Si la liste de contacts n'est pas vide, nous renvoyons une réponse JSON contenant la liste des contacts avec un code de statut HTTP 200 (OK) pour indiquer que la requête a réussi.

    return jsonify(contacts), 200

Voici à quoi ressemble le code de notre fonction:

@contact_request.route('/', methods=['GET'])
def get_all_contacts():
    """
    Route pour récupérer tous les contacts
    Méthode : GET
    """
    contacts = ContactInterface().get_all_contacts()

    if not contacts:
        return jsonify(message="Aucun contact trouvé"), 404

    return jsonify(contacts), 200

#Read by id

@contact_request.route('/<id>', methods=['GET'])
def get_contact_by_id(id):
    """
    Route pour récupérer un contact par son ID
    Méthode : GET
    """
    # Implémentation pour renvoyer un contact spécifique en fonction de son ID
    filter = {'_id': ObjectId(id)}
    contact = ContactInterface().get_contact_by_id(filter)
    if contact:
        return jsonify(contact), 200
    else:
        return jsonify({"message": "Contact not found"}), 404

Dans cette fonction, nous utilisons l'interface ContactInterface pour récupérer le contact correspondant à l'ID spécifié. Si le contact est trouvé, nous le renvoyons avec un code de statut 200 (OK). Sinon, nous renvoyons un message d'erreur avec un code de statut 404 (Non trouvé). Cela permet à l'utilisateur de récupérer les informations d'un contact spécifique en utilisant son ID dans l'URL de la requête GET.


Maintenant que nous avons implémenté toutes les fonctionnalités de notre API de gestion de contacts, nous avons parcouru un long chemin depuis la création de notre interface jusqu'à l'implémentation de nos endpoints.

Si vous avez suivi le tout premier article, vous vous souvenez que nous avons créé un fichier app.py pour notre application Flask. Ce fichier est le point d'entrée de notre application et contient la configuration et la création de l'instance de l'application Flask.

Voici un exemple de ce que peut contenir le fichier app.py :


import os
from flask import Flask
from modules.contacts.contact import contact_request

app = Flask(__name__)

app.register_blueprint(contact_request, url_prefix='/api/contacts')


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

Dans la configuration de l'application Flask, nous enregistrons le Blueprint en utilisant app.register_blueprint(contact_request, url_prefix='/api/contacts'). Cette ligne de code lie notre Blueprint contact_request à l'application Flask principale et spécifie le préfixe d'URL /contacts pour toutes les routes définies dans le Blueprint. Cela signifie que toutes les routes de notre API de contacts commenceront par /api/contacts.

Avant de tester notre API avec Postman, assurez-vous de ne pas oublier de définir le fichier .env et d'y ajouter la variable DATABASE_URL avec la valeur appropriée. Cette variable contient l'URL de connexion à votre base de données.

Le fichier .env est un fichier de configuration où vous pouvez stocker des variables d'environnement spécifiques à votre application. Il est important de définir correctement la variable DATABASE_URL pour que notre application puisse se connecter à la base de données et fonctionner correctement.

Assurez-vous d'ajouter le fichier .env à la racine de votre projet et d'y ajouter la ligne suivante :

DATABASE_URL=<votre_url_de_base_de_données>

Remplacez <votre_url_de_base_de_données> par l'URL de connexion appropriée pour votre base de données. Assurez-vous également de respecter le format et les informations de connexion requis par votre base de données spécifique.

En définissant correctement la variable DATABASE_URL dans le fichier .env, notre application Flask sera en mesure de récupérer cette valeur lors de son exécution et d'établir la connexion appropriée à la base de données.


Une fois que vous avez implémenté vos endpoints et lancé l'API (python3 app.py), il est essentiel de les tester pour vous assurer qu'ils fonctionnent correctement. L'un des outils populaires pour tester les API est Postman. Postman vous permet d'envoyer des requêtes HTTP à vos endpoints et d'inspecter les réponses pour vérifier leur conformité.

Pour tester votre API Flask avec Postman, vous pouvez suivre les étapes suivantes :

  1. Ouvrez Postman et créez une nouvelle requête.

  2. Spécifiez l'URL de votre endpoint API Flask dans la barre d'adresse. Par exemple, si votre endpoint est /contacts, l'URL sera http://localhost:5000/api/contacts.

  3. Sélectionnez la méthode appropriée dans le menu déroulant de la requête. Par exemple, pour récupérer tous les contacts, utilisez la méthode GET.

  4. Cliquez sur le bouton "Send" pour envoyer la requête à votre API Flask.

  5. Dans la section de la réponse de Postman, vous pourrez voir le statut de la requête (code de statut HTTP) ainsi que le contenu de la réponse renvoyée par votre API. Vérifiez si les données retournées correspondent à ce que vous attendiez.

  6. Répétez les étapes ci-dessus pour tester vos autres endpoints avec différentes méthodes et paramètres.

Ex:


En conclusion, nous avons parcouru les principales étapes de création d'une API de gestion de carnet d'adresses en utilisant Flask. Nous avons commencé par mettre en place l'architecture du projet, en créant les dossiers nécessaires et en mettant à jour les dépendances.

Ensuite, nous avons créé une interface pour gérer notre collection de contacts, en implémentant les méthodes CRUD (Create, Read, Update, Delete). Cette interface nous permet de centraliser les opérations sur les contacts et de les réutiliser facilement dans nos endpoints.

En implémentant les endpoints de notre API, nous avons utilisé le concept de blueprint de Flask pour organiser notre code de manière modulaire. Chaque endpoint correspond à une route spécifique et est associé à une fonction qui gère la logique de cette route.

Nous avons expliqué en détail chaque fonctionnalité de l'API, de la création d'un nouveau contact à la récupération de tous les contacts, en passant par la mise à jour et la suppression d'un contact existant. Nous avons utilisé l'interface que nous avons créée pour interagir avec notre collection de contacts dans ces fonctions.

Enfin, nous avons souligné l'importance de tester notre API à l'aide d'outils tels que Postman. Tester nos endpoints nous permet de vérifier leur bon fonctionnement et de s'assurer qu'ils renvoient les réponses attendues.

Il est important de continuer à explorer les fonctionnalités de Flask et à approfondir nos connaissances en matière de développement d'API. Flask offre de nombreuses possibilités pour développer des applications web puissantes et flexibles.

C'est tout pour cet article ! Continuez à apprendre et à explorer Flask pour créer des applications Web et des API puissantes ✊🏿. À bientôt !

Le lien github: https://github.com/Pikatchu99/yemalin.tech-contact

C'était Yémalin👉🏿👈🏿, à la prochaine 🚀 !