Connecter une API à une Base de Données sous Python

-
4
 m de lecture
-

Dans un premier article, nous avons vu quelques principes de construction des API REST et un premier exemple d’implémentation de celles-ci sous Python avec Flask.

Dans cet exemple, les données étaient intégrées au code sous la forme d’une liste de dictionnaires.

Nous avons également un article sur comment programmer et documenter une API avec python, flask, swagger et connexion.

Dans l’exemple qui va suivre, on va voir comment connecter une API à une base de données relationnelle externe et autoriser le filtrage des items par différentes conditions :

1. Bases de données relationnelles

Les bases de données relationnelles permettent de stocker et de récupérer des données, ces dernières étant mises sous la forme de tables.

Les tables sont semblables à des feuilles de calcul : elles ont des lignes et des colonnes, les colonnes indiquant ce à quoi correspondent les données, par exemple à un titre ou à une date. Les lignes représentent des données individuelles, qui peuvent correspondre à des utilisateurs, des transactions ou tout autre type d’entité.

2. SQLite

Le moteur de base de données utilisé dans la suite est SQLite, un moteur de base de données très léger et disponible sous Python par défaut.

L’extension standard des fichiers SQLite est .db.

La base de données utilisée est la base Chinook (disponible via le lien suivant), composée de 11 tables. Dans la suite, on s’intéressera particulièrement à la table employees : celle-ci contient des données sur les employés de l’entreprise Chinook, telles que l’identifiant, le nom, le prénom, etc. 

3. Connecter une API à la base Chinook

On commence par recopier la base chinook.db dans notre répertoire api.

Notre API requêtera cette base de données afin de renvoyer les résultats voulus aux utilisateurs.

Le code correspondant est le suivant :

On le sauvegarde dans le répertoire api sous le nom de api4.py.

Afin de l’exécuter, on lance une fenêtre ligne de commande à partir du répertoire api et on saisit les commandes suivantes :

$ export FLASK_APP = api4.py

$ export FLASK_ENV = development

$ flask run

(pour arrêter l’exécution, faire Ctrl-C).

On obtient, entre autres messages :

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Une fois le programme exécuté, on peut soumettre au navigateur utilisé des requêtes du type :

La table employees de la base de données Chinook compte 8 enregistrements, un pour chaque employé de la société Chinook.

Les données comprennent, entre autres, l’identifiant, le nom, le prénom, la ville de résidence, la date de naissance, la date de recrutement.

Notre API permet de filtrer selon trois champs : EmployeeId (identifiant), LastName (nom de famille) et City (ville de résidence).

La nouvelle API répond aux requêtes des utilisateurs en extrayant l’information de la base de données à l’aide de requêtes SQL.

Elle permet également de filtrer selon plus d’un champ.

4. Comprendre la nouvelle API

La table employees de la base de données Chinook est composée de huit colonnes : EmployeeId, LastName, FirstName, Title, ReportsTo, BirthDate, HireDate et Address. 

Chaque ligne représente un employé de la société Chinook.

Plutôt que de spécifier les données dans le code, notre fonction api_all les extrait de la base de données Chinook :

On commence par se connecter à la base de données en utilisant la bibliothèque sqlite3.

Un objet représentant la connexion à la base de données est lié à la variable conn.

L’instruction conn.row_factory = dict_factory dit à l’objet correspondant à la connexion d’utiliser la fonction dict_factory, qui renvoie les résultats sous forme de dictionnaires plutôt que de listes – ce qui se convertit mieux au format JSON.

On crée ensuite un objet curseur (cur = conn.cursor( )), qui parcourt la base de données pour extraire les données.

Finalement, on exécute une requête SQL à l’aide de la méthode cur.execute pour extraire toutes les données disponibles ( * ) de la table employees de notre base de données.

À la fin de notre fonction, les données récupérées sont converties au format JSON : jsonify(all_employees).

L’autre fonction renvoyant des données, api_filter, utilise la même approche pour extraire des données spécifiques de la base.

Le but de la fonction page_not_found est de créer une page d’erreur affichée à l’utilisateur s’il spécifie une route qui n’est pas prise en charge par l’API :

Dans les résultats HTML, le code 200 signifie « OK » (données transférées) alors que le code 404 signifie « not found » (pas de ressources disponibles à l’adresse spécifiée).

La fonction page_not_found permet de renvoyer 404 si quelque chose se passe mal.

La fonction api_filter permet de filtrer selon trois champs : EmployeeId, LastName et City.

Elle commence par identifier tous les paramètres de requête fournis dans l’URL, à l’aide de l’instruction :

query_parameters = request.args

Elle récupère ensuite les valeurs des paramètres et les lie à des variables :

employeeid = query_parameters.get(‘EmployeeId’)

lastname = query_parameters.get(‘LastName’)

city = query_parameters.get(‘City’)

La portion de code suivante permet de construire une requête SQL qui est utilisée pour extraire l’information recherchée de la base de données.

Les requêtes SQL les plus simples sont la forme :

SELECT <columns> FROM <table> WHERE <column=match> AND <column=match>;

Afin d’obtenir les données recherchées, on doit construire à la fois une requête SQL du type précédent et une liste avec les filtres (valeurs) spécifiés.

On commence par définir la requête et la liste de filtres :

Alors, si EmployeeId, LastName et City ont été passés en paramètres de requête, on les rajoute à la requête et à la liste de filtres :

Si l’utilisateur n’a spécifié aucun de ces paramètres de requête, on renvoie la page d’erreur 404 :

Afin de parfaire notre requête SQL, on supprime le dernier AND et on complète la requête par le point-virgule requis par SQL :

Ensuite, on se connecte à la base de données, puis on exécute la requête SQL construite à l’aide de notre liste de filtres :

Finalement, on renvoie les résultats au format JSON à l’utilisateur:

return jsonify(results)

5. Utiliser la nouvelle API

Notre nouvelle API autorise des requêtes plus sophistiquées de la part des utilisateurs.

De plus, dès que de nouvelles données sont rajoutées à la base, elles deviennent immédiatement disponibles pour les projets construits à l’aide de l’API.

Ainsi, dans bien des cas, il est pertinent de commencer par créer une interface de type API pour les données d’un projet avant de construire une visualisation, une application ou un site web basé sur les données.

Dans le prochain article, nous développerons les techniques présentées précédemment pour voir comment programmer une API REST professionnelle sous Python en utilisant Flask, OpenAPI (anciennement Swagger) et Connexion.

6. Références bibliographiques

Facebook
Twitter
LinkedIn

DataScientest News

Inscrivez-vous à notre Newsletter pour recevoir nos guides, tutoriels, et les dernières actualités data directement dans votre boîte mail.

Vous souhaitez être alerté des nouveaux contenus en data science et intelligence artificielle ?

Laissez-nous votre e-mail, pour que nous puissions vous envoyer vos nouveaux articles au moment de leur publication !

Newsletter icone
icon newsletter

DataNews

Vous souhaitez recevoir notre
newsletter Data hebdomadaire ?