{"id":140363,"date":"2023-03-07T11:20:01","date_gmt":"2023-03-07T10:20:01","guid":{"rendered":"https:\/\/liora.io\/?p=140363"},"modified":"2026-02-25T18:40:36","modified_gmt":"2026-02-25T17:40:36","slug":"programmation-dapi-web-sous-python-avec-flask","status":"publish","type":"post","link":"https:\/\/liora.io\/programmation-dapi-web-sous-python-avec-flask","title":{"rendered":"Programmation d\u2019API Web sous Python avec Flask"},"content":{"rendered":"\n<p><strong>L\u2019article va traiter de la programmation d\u2019API (Application Programming Interfaces) Web sous Python. Celles-ci sont des outils permettant de rendre accessibles de l\u2019information et des fonctionnalit\u00e9s via internet. Vous pouvez \u00e9galement d\u00e9couvrir comment connecter une API \u00e0 une base de donn\u00e9es sous python et comment programmer et documenter une API avec python, flask, swagger et connexion. Dans cet article, on verra :<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-1-qu-est-ce-qu-une-api\">1. Qu&rsquo;est-ce qu&rsquo;une API ?<\/h2>\n\n\n\n<p>Une API Web permet \u00e0 de l\u2019information et \u00e0 des fonctionnalit\u00e9s d\u2019\u00eatre manipul\u00e9es par des programmes informatiques via internet.<\/p>\n\n\n\n<p>Par exemple, avec l\u2019API Web Twitter, on peut \u00e9crire un programme dans un langage comme Python ou Javascript qui collecte des m\u00e9tadonn\u00e9es sur les tweets.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>Plus g\u00e9n\u00e9ralement, en programmation, le terme API (abr\u00e9viation d&rsquo;Application Programming Interface) r\u00e9f\u00e8re \u00e0 une partie d\u2019un programme informatique con\u00e7ue pour \u00eatre utilis\u00e9e ou manipul\u00e9e par un autre programme, contrairement aux interfaces qui sont con\u00e7ues pour \u00eatre utilis\u00e9es ou manipul\u00e9es par des humains.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Les programmes informatiques ont souvent besoin de communiquer entre eux ou avec le syst\u00e8me d\u2019exploitation sous-jacent et les API sont une fa\u00e7on de le faire.<\/p>\n\n\n\n<p>Dans la suite, toutefois, on se limitera aux API Web.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-2-quand-utiliser-une-api\">2. Quand utiliser une API ?<\/h2>\n\n\n\n<p>Si on dispose de donn\u00e9es qu\u2019on souhaite partager avec le monde entier, cr\u00e9er une API Web est une fa\u00e7on de le faire.<\/p>\n\n\n\n<p>Toutefois, les API ne sont pas toujours la meilleure mani\u00e8re de partager des donn\u00e9es avec des utilisateurs.<\/p>\n\n\n\n<p>Si le volume des donn\u00e9es qu\u2019on souhaite partager est relativement faible, il vaut mieux proposer un \u00ab data dump \u00bb sous la forme d\u2019un fichier <strong>JSON, XML, CSV ou Sqlite<\/strong>. Selon les ressources dont on dispose, cette approche peut \u00eatre viable jusqu\u2019\u00e0 un volume de quelques Gigaoctets.<\/p>\n\n\n\n<p>En g\u00e9n\u00e9ral, on utilise une API Web quand :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Notre <strong>jeu de donn\u00e9es est important<\/strong>, ce qui rend le t\u00e9l\u00e9chargement par FTP lourd ou consommateur de ressources importantes.<\/li>\n\n\n\n<li>Les utilisateurs ont besoin d\u2019<strong>acc\u00e9der aux donn\u00e9es en temps r\u00e9el<\/strong>, par exemple pour une visualisation sur un site web ou comme une partie d\u2019une application.<\/li>\n\n\n\n<li>Nos donn\u00e9es sont modifi\u00e9es ou mises \u00e0 jour fr\u00e9quemment.<\/li>\n\n\n\n<li>Les utilisateurs n\u2019ont besoin d\u2019acc\u00e9der qu\u2019\u00e0 <strong>une partie des donn\u00e9es \u00e0 la fois<\/strong>.<\/li>\n\n\n\n<li>Les utilisateurs ont \u00e0 effectuer d\u2019autres actions que simplement consulter les donn\u00e9es, par exemple <strong>contribuer<\/strong>, <strong>mettre \u00e0 jour ou supprimer<\/strong>.<\/li>\n<\/ul>\n\n\n\n<p>Notons qu\u2019on peut fournir \u00e0 la fois un data dump et une API ; \u00e0 charge des utilisateurs de choisir ce qui leur convient le mieux.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-3-la-terminologie-associee-aux-api\">3. La terminologie associ\u00e9e aux API<\/h2>\n\n\n\n<p><strong>HTTP (HyperText Transfert Protocol)<\/strong> : c\u2019est le principal moyen de communiquer de l\u2019information sur Internet. HTTP impl\u00e9mente un certain nombre de \u00ab m\u00e9thodes \u00bb qui disent dans quelle direction les donn\u00e9es doivent se d\u00e9placer et ce qui doit en \u00eatre fait. Les deux plus fr\u00e9quentes sont GET, qui r\u00e9cup\u00e8re les donn\u00e9es \u00e0 partir d\u2019un serveur, et POST, qui envoie de nouvelles donn\u00e9es vers un serveur.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/2022\/02\/illu_schema_http_1-85.png\" alt=\"\" class=\"wp-image-141956\" style=\"object-fit:contain\" \/><\/figure>\n\n\n\n<p><strong>URL (Uniform Ressource Locator)<\/strong> : Adresse d\u2019une ressource sur le web, comme <strong>http:\/\/www-facultesciences.univ-ubs.fr\/fr<\/strong>. Une URL consiste en un protocole (<strong>http:\/\/<\/strong>), un domaine (<strong>www-facultesciences.univ-ubs.fr<\/strong>), un chemin optionnel (<strong>\/fr<\/strong>).&nbsp;<\/p>\n\n\n\n<p>Elle d\u00e9crit l\u2019emplacement d\u2019une ressource sp\u00e9cifique, comme une page Web. Dans le domaine des API, les termes URL, request, URI, endpoint d\u00e9signent des id\u00e9es similaires. Dans la suite, on utilisera uniquement les termes URL et request (requ\u00eate), pour \u00eatre plus clair.&nbsp;<\/p>\n\n\n\n<p>Pour effectuer une requ\u00eate GET ou suivre un lien, il suffit de disposer d\u2019un navigateur Web.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/2022\/02\/illu_schema_http_2-86.png\" alt=\"\" class=\"wp-image-141955\" style=\"object-fit:contain\" \/><\/figure>\n\n\n\n<p><strong>JSON (JavaScript Object Notation)<\/strong>&nbsp;: c\u2019est un format texte de stockage des donn\u00e9es con\u00e7u pour \u00eatre lisible \u00e0 la fois par les \u00eatres humains et les machines.&nbsp;<strong>JSON est le format le plus usuel des donn\u00e9es r\u00e9cup\u00e9r\u00e9es par API<\/strong>, le deuxi\u00e8me plus usuel \u00e9tant XML.<\/p>\n\n\n\n<p><strong>REST (REpresentational State Transfer)<\/strong>&nbsp;: c\u2019est une m\u00e9thodologie qui regroupe les meilleures pratiques en termes de conception et d\u2019impl\u00e9mentation d\u2019APIs. Les API con\u00e7ues selon les principes de la m\u00e9thodologie REST sont appel\u00e9es des&nbsp;<strong>API REST&nbsp;(REST APIs)<\/strong>. Il y a toutefois de nombreuses pol\u00e9miques autour de la signification exacte du terme. Dans la suite, on parlera plus simplement d\u2019API Web ou d\u2019API HTTP.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-4-un-premier-exemple\">4. Un premier exemple<\/h2>\n\n\n\n<p>Dans la suite, on va voir comment cr\u00e9er une API en utilisant Python et le cadre de travail Flask. Notre exemple d\u2019API portera sur un annuaire des employ\u00e9s d\u2019une entreprise qui fournira leur nom, pr\u00e9nom, fonction et anciennet\u00e9. On commencera par utiliser <a href=\"http:\/\/flask.pocoo.org\">Flask<\/a>&nbsp;pour cr\u00e9er une page web pour notre site. Cela nous permettra de voir comment Flask fonctionne. Une fois qu\u2019on aura une petite application Flask fonctionnelle sous la forme d\u2019une page Web, on transformera le site en une API.<\/p>\n\n\n\n<p>Pourquoi Flask ? En effet, <a href=\"https:\/\/liora.io\/formation-langage-python\">Python<\/a> dispose de plusieurs cadres de d\u00e9veloppement (frameworks) permettant de produire des pages Web et des API. Le plus connu est Django, qui est tr\u00e8s riche mais qui peut toutefois \u00eatre \u00e9crasant pour les utilisateurs non exp\u00e9riment\u00e9s. Les applications Flask sont construites \u00e0 partir de canevas tr\u00e8s simples et sont donc plus adapt\u00e9es au prototypage d\u2019APIs.<\/p>\n\n\n\n<p>On commence par cr\u00e9er un nouveau r\u00e9pertoire sur l\u2019ordinateur, qui servira de r\u00e9pertoire de projet et qu\u2019on nommera <strong>projects<\/strong>. Les fichiers de notre projet seront stock\u00e9s dans un sous-<strong>r\u00e9pertoire de projects<\/strong>, nomm\u00e9 <strong>api<\/strong>. On lance ensuite Spyder 3 ou tout autre EDI et on saisit le code suivant :<\/p>\n\n\n\n<pre class=\"wp-block-code has-xsmall-font-size\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><code>import flask\n\napp = flask.Flask(__name__)\napp.config&#091;\"DEBUG\"] = True\n\n\n@app.route('\/', methods=&#091;'GET'])\ndef home():\n   return \"&lt;h1&gt;Annuaire Internet&lt;\/h1&gt;&lt;p&gt;Ce site est le prototype d\u2019une API mettant \u00e0 disposition des donn\u00e9es sur les employ\u00e9s d\u2019une entreprise.&lt;\/p&gt;\"\n\napp.run()<\/code><\/pre>\n\n\n\n<p>On sauvegarde ensuite le programme sous le nom api.py dans le r\u00e9pertoire api pr\u00e9c\u00e9demment cr\u00e9\u00e9.<\/p>\n\n\n\n<p>Afin de l\u2019ex\u00e9cuter, on lance une fen\u00eatre ligne de commande \u00e0 partir de ce r\u00e9pertoire et on saisit les commandes suivantes :<\/p>\n\n\n\n<p><strong>$ export FLASK_APP = api.py<\/strong><\/p>\n\n\n\n<p><strong>$ export FLASK_ENV = development<\/strong><\/p>\n\n\n\n<p><strong>$ flask run<\/strong><\/p>\n\n\n\n<p>Alternativement, on peut ex\u00e9cuter le programme sous Spyder ou tout autre EDI utilis\u00e9.<\/p>\n\n\n\n<p>On obtient dans le console l\u2019affichage suivant (entre autres sorties) :<\/p>\n\n\n\n<p><strong>* Running on http:\/\/127.0.0.1:5000\/ (Press CTRL+C to quit)<\/strong><\/p>\n\n\n\n<p>Il suffit de saisir le lien pr\u00e9c\u00e9dent dans un navigateur Web pour acc\u00e9der \u00e0 l\u2019application.<\/p>\n\n\n\n<p>On a ainsi cr\u00e9\u00e9 une application Web fonctionnelle.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/2022\/02\/API-1.png\" alt=\"\" class=\"wp-image-143760\" style=\"object-fit:contain;width:1000px;height:auto\" \/><\/figure>\n\n\n\n<p>Examinons \u00e0 pr\u00e9sent la fa\u00e7on dont Flask fonctionne.<\/p>\n\n\n\n<p>Flask envoie des requ\u00eates HTTP \u00e0 des fonctions Python. Dans notre cas, nous avons appliqu\u00e9 un chemin d\u2019URL (\u2018\/\u2018) sur une fonction : <strong>home<\/strong>.<\/p>\n\n\n\n<p>Flask ex\u00e9cute le code de la fonction et affiche le r\u00e9sultat dans le navigateur. Dans notre exemple, le r\u00e9sultat est un code HTML de bienvenue sur le site h\u00e9bergeant notre API.<\/p>\n\n\n\n<p>Le processus consistant \u00e0 appliquer des URL sur des fonctions est appel\u00e9 routage (routing).<\/p>\n\n\n\n<p>L\u2019instruction :<\/p>\n\n\n\n<p><strong>@app.route(&lsquo;\/&rsquo;, methods=[\u2018GET&rsquo;])<\/strong><\/p>\n\n\n\n<p>apparaissant dans le programme indique \u00e0 Flask que la <strong>fonction home<\/strong> correspond au chemin \/.<\/p>\n\n\n\n<p>La liste methods<strong> (methods=[&lsquo;GET&rsquo;])<\/strong> est un argument mot-clef qui indique \u00e0 Flask le type de requ\u00eates HTTP autoris\u00e9es.<\/p>\n\n\n\n<p>On utilisera uniquement des requ\u00eates GET dans la suite, mais de nombreuses applications Web utilisent \u00e0 la fois des requ\u00eates GET (pour envoyer des donn\u00e9es de l\u2019application aux utilisateurs) et POST (pour recevoir les donn\u00e9es des utilisateurs).<\/p>\n\n\n\n<p>Commentons \u00e0 pr\u00e9sent le programme plus en d\u00e9tail.<\/p>\n\n\n\n<p><strong>import Flask<\/strong> : Cette instruction permet d\u2019importer la biblioth\u00e8que Flask, qui est disponible par d\u00e9faut sous Anaconda.<\/p>\n\n\n\n<p><strong>app = flask.Flask(__name__)<\/strong> : Cr\u00e9e l\u2019objet application Flask, qui contient les donn\u00e9es de l\u2019application et les m\u00e9thodes correspondant aux actions susceptibles d\u2019\u00eatre effectu\u00e9es sur l\u2019objet. La derni\u00e8re instruction app.run( ) est un exemple d\u2019utilisation de m\u00e9thode.<\/p>\n\n\n\n<p><strong>app.config[\u201cDEBUG\u201d = True]<\/strong> : lance le d\u00e9bogueur, ce qui permet d\u2019afficher un message autre que \u00ab Bad Gateway \u00bb s\u2019il y a une erreur dans l\u2019application.<\/p>\n\n\n\n<p><strong>app.run( )<\/strong> : permet d\u2019ex\u00e9cuter l\u2019application.<\/p>\n\n\n\n<p>\u00c0 pr\u00e9sent, afin de cr\u00e9er l\u2019API, on va sp\u00e9cifier nos donn\u00e9es sous la forme d\u2019une liste de dictionnaires Python.<\/p>\n\n\n\n<p>\u00c0 titre d\u2019exemple, on va fournir des donn\u00e9es sur trois employ\u00e9s de notre entreprise. Chaque dictionnaire contiendra un num\u00e9ro d\u2019identification, le nom, le pr\u00e9nom, la fonction et l\u2019anciennet\u00e9 d\u2019un employ\u00e9.<\/p>\n\n\n\n<p>On introduira \u00e9galement une nouvelle fonction : une route permettant aux visiteurs d\u2019acc\u00e9der \u00e0 nos donn\u00e9es.<\/p>\n\n\n\n<p>Ainsi, nous rempla\u00e7ons le code sauvegard\u00e9 dans <strong>api.py<\/strong> par le code suivant :<\/p>\n\n\n\n<pre class=\"wp-block-code has-xsmall-font-size\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><code># Import de biblioth\u00e8ques\nimport flask\nfrom flask import request, jsonify\n\n# Cr\u00e9ation de l'objet Flask\napp = flask.Flask(__name__)\n\n# Lancement du D\u00e9bogueur\napp.config&#091;\"DEBUG\"] = True\n\n# Quelques donn\u00e9es tests pour l\u2019annuaire sous la forme d\u2019une liste de dictionnaires\nemployees = &#091;\n   {'id': 0,\n\t'Nom': 'Dupont',\n\t\u2018Pr\u00e9nom\u2019': 'Jean',\n\t'Fonction': 'D\u00e9veloppeur',\n\t'Anciennet\u00e9': '5'},\n   {'id': 1,\n\t'Nom': 'Durand',\n\t'Pr\u00e9nom': Elodie',\n\t'Fonction': 'Directrice Commerciale',\n\t'Anciennet\u00e9': '4'},\n   {'id': 2,\n\t'Nom': 'Lucas',\n\t'Pr\u00e9nom': 'J\u00e9r\u00e9mie',\n\t'Fonction': 'DRH',\n\t'Anciennet\u00e9': '4'}\n]\n\n@app.route('\/', methods=&#091;'GET'])\ndef home():\n return '''&lt;h1&gt;Annuaire Internet&lt;\/h1&gt;\n&lt;p&gt;Ce site est le prototype d\u2019une API mettant \u00e0 disposition des donn\u00e9es sur les employ\u00e9s d\u2019une entreprise.&lt;\/p&gt;'''\n\n# Route permettant de r\u00e9cup\u00e9rer toutes les donn\u00e9es de l\u2019annuaire\n@app.route('\/api\/v1\/resources\/employees\/all', methods=&#091;'GET'])\ndef api_all():\n   return jsonify(employees)\n\napp.run()<\/code><\/pre>\n\n\n\n<p>On ex\u00e9cute le code sous Spyder 3 et on met \u00e0 jour la fen\u00eatre du navigateur.<\/p>\n\n\n\n<p>Pour acc\u00e9der \u00e0 l\u2019ensemble des donn\u00e9es, il suffit de saisir dans le navigateur l\u2019adresse :<\/p>\n\n\n\n<p><a href=\"http:\/\/127.0.0.1:5000\/api\/v1\/resources\/employees\/all\">http:\/\/127.0.0.1:5000\/api\/v1\/resources\/employees\/all<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/2022\/02\/unnamed.png\" alt=\"\" class=\"wp-image-144080\" style=\"object-fit:contain;width:1000px;height:auto\" \/><\/figure>\n\n\n\n<p>On a utilis\u00e9 la fonction <strong>jsonify<\/strong> de Flask. Celle-ci permet de convertir les listes et les dictionnaires au format JSON.<\/p>\n\n\n\n<p>Via la route qu\u2019on a cr\u00e9\u00e9, nos donn\u00e9es sur les employ\u00e9s sont converties d\u2019une liste de dictionnaires vers le format JSON, avant d\u2019\u00eatre fournies \u00e0 l\u2019utilisateur.<\/p>\n\n\n\n<p>\u00c0 ce stade, nous avons cr\u00e9\u00e9 une <strong>API fonctionnelle<\/strong>, bien que limit\u00e9e.<\/p>\n\n\n\n<p>En effet, en l\u2019\u00e9tat actuel de notre API, les utilisateurs ne peuvent acc\u00e9der qu\u2019\u00e0 l\u2019int\u00e9gralit\u00e9 de nos donn\u00e9es; il ne peuvent sp\u00e9cifier de filtre pour trouver des ressources sp\u00e9cifiques.<\/p>\n\n\n\n<p>Bien que cela ne pose pas probl\u00e8me sur nos donn\u00e9es de test, peu nombreuses, cela devient probl\u00e9matique au fur et \u00e0 mesure qu\u2019on ajoute des donn\u00e9es.<\/p>\n\n\n\n<p>Dans la suite, on va introduire une fonction permettant aux utilisateurs de <strong>filtrer les r\u00e9sultats<\/strong> renvoy\u00e9s \u00e0 l\u2019aide de requ\u00eates plus sp\u00e9cifiques.<\/p>\n\n\n\n<p>Le nouveau code est le suivant :<\/p>\n\n\n\n<pre class=\"wp-block-code has-xsmall-font-size\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><code>app = flask.Flask(__name__)\napp.config&#091;\"DEBUG\"] = True\n# Quelques donn\u00e9es tests pour l\u2019annuaire sous la forme d\u2019une liste de dictionnaires\nemployees = &#091;\n   {'id': 0,\n\t'Nom': 'Dupont',\n\t\u2018Pr\u00e9nom\u2019': 'Jean',\n\t'Fonction': 'D\u00e9veloppeur',\n\t'Anciennet\u00e9': '5'},\n   {'id': 1,\n\t'Nom': 'Durand',\n\t'Pr\u00e9nom': Elodie',\n\t'Fonction': 'Directrice Commerciale',\n\t'Anciennet\u00e9': '4'},\n   {'id': 2,\n\t'Nom': 'Lucas',\n\t'Pr\u00e9nom': 'J\u00e9r\u00e9mie',\n\t'Fonction': 'DRH',\n\t'Anciennet\u00e9': '4'}\n]\n\n@app.route('\/', methods=&#091;'GET'])\ndef home():\n    return '''&lt;h1&gt;Annuaire Internet&lt;\/h1&gt;\n&lt;p&gt;Ce site est le prototype d\u2019une API mettant \u00e0 disposition des donn\u00e9es sur les employ\u00e9s d\u2019une entreprise.&lt;\/p&gt;'''\n \n \n@app.route('\/api\/v1\/resources\/employees\/all', methods=&#091;'GET'])\ndef api_all():\n    return jsonify(employees)\n \n \n@app.route('\/api\/v1\/resources\/employees', methods=&#091;'GET'])\ndef api_id():\n    # V\u00e9rifie si un ID est fourni dans une URL.\n    # Si un ID est fourni, il est affect\u00e9 \u00e0 une variable.\n    # Si aucun ID n\u2019est fourni, un message d\u2019erreur est affich\u00e9 dans le navigateur.\n    if 'id' in request.args:\n        id = int(request.args&#091;'id'])\n    else:\n        return \"Erreur: Pas d\u2019identifiant fourni. Veuillez sp\u00e9cifier un id.\"\n \n    # Cr\u00e9e une liste vide pour stocker les r\u00e9sultats\n    results = &#091;]\n \n    # Boucle sur les donn\u00e9es pour obtenir les r\u00e9sultats correspondant \u00e0 l\u2019ID fourni.\n    # Les IDs sont uniques, mais les autres champs peuvent renvoyer plusieurs r\u00e9sultats\n    for employee in employees:\n        if employee&#091;'id'] == id:\n            results.append(employee)\n \n    # La fonction jsonify de Flask convertit notre liste de dictionnaires Python\n    # au format JSON     return jsonify(results)\n \napp.run()<\/code><\/pre>\n\n\n\n<p>Apr\u00e8s avoir saisi, sauvegard\u00e9 et ex\u00e9cut\u00e9 le code sous Spyder 3, on peut saisir les adresses suivantes dans le navigateur :<\/p>\n\n\n\n<p><strong>127.0.0.1:5000\/api\/v1\/resources\/employees?id=0<\/strong><\/p>\n\n\n\n<p><strong>127.0.0.1:5000\/api\/v1\/resources\/employees?id=1<\/strong><\/p>\n\n\n\n<p><strong>127.0.0.1:5000\/api\/v1\/resources\/employees?id=2<\/strong><\/p>\n\n\n\n<p><strong>127.0.0.1:5000\/api\/v1\/resources\/employees?id=3<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/2022\/02\/API-3.png\" alt=\"\" class=\"wp-image-143762\" style=\"object-fit:contain;width:1000px;height:auto\" \/><\/figure>\n\n\n\n<p>Chacune de ces adresses renvoie un r\u00e9sultat diff\u00e9rent, except\u00e9 la derni\u00e8re, qui renvoie une liste vide, puisqu\u2019il n\u2019y a pas d\u2019employ\u00e9 d\u2019identifiant 3.<\/p>\n\n\n\n<p>Dans la suite, on va examiner notre nouvelle API en d\u00e9tail.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>Nous avons cr\u00e9\u00e9 une nouvelle fonction api_root, avec l\u2019instruction @app_route, appliqu\u00e9e sur le chemin \/api\/v1\/resources\/employees.&nbsp;<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Ainsi, la fonction est ex\u00e9cut\u00e9e d\u00e8s lors qu\u2019on acc\u00e8de \u00e0 <a href=\"http:\/\/127.0.0.1:5000\/api\/v1\/resources\/employees\">http:\/\/127.0.0.1:5000\/api\/v1\/resources\/employees<\/a>.<\/p>\n\n\n\n<p>Notons qu\u2019acc\u00e9der au lien sans sp\u00e9cifier d\u2019ID, renvoie le message d\u2019erreur sp\u00e9cifi\u00e9 dans le code : Erreur: Pas d\u2019identifiant fourni. Veuillez sp\u00e9cifier un id.<\/p>\n\n\n\n<p>Dans notre fonction, on fait deux choses : on commence par examiner l\u2019URL fournie \u00e0 la recherche d\u2019un identifiant, puis on s\u00e9lectionne le livre qui correspond \u00e0 l\u2019identifiant.<\/p>\n\n\n\n<p>L\u2019ID doit \u00eatre fourni avec la syntaxe <strong>?id=0<\/strong>, par exemple.<\/p>\n\n\n\n<p>Les donn\u00e9es pass\u00e9es \u00e0 l\u2019URL de cette fa\u00e7on sont appel\u00e9es param\u00e8tres de requ\u00eate. Ils sont une des caract\u00e9ristique du protocole HTTP.<\/p>\n\n\n\n<p>La partie suivante du code d\u00e9termine s\u2019il y a un param\u00e8tre de requ\u00eate du type ?id=0, puis affecte <strong>l\u2019ID fourni \u00e0 une variable<\/strong>.<\/p>\n\n\n\n<p>Ensuite, on parcourt l\u2019annuaire des employ\u00e9s, on identifie l\u2019employ\u00e9 ayant l\u2019ID sp\u00e9cifi\u00e9 et on le rajoute \u00e0 la liste renvoy\u00e9e en r\u00e9sultat.<\/p>\n\n\n\n<p>Finalement, l\u2019instruction return jsonify(results) renvoie les r\u00e9sultats au format JSON pour affichage dans le navigateur.<\/p>\n\n\n\n<p>A ce stade, on a cr\u00e9\u00e9 une API fonctionnelle. Dans les posts suivants, on va voir comment cr\u00e9er une API un peu plus complexe, qui utilise une <a href=\"https:\/\/liora.io\/bien-choisir-sa-base-de-donnees-typologie\">base de donn\u00e9es<\/a>. Les principes et instructions fondamentaux resteront toutefois les m\u00eames.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-5-quelques-principes-de-bonne-conception-des-api-web\">5. Quelques principes de bonne conception des API Web<\/h2>\n\n\n\n<p>Deux aspects des bonnes API sont la facilit\u00e9 d\u2019utilisation (usability) et la maintenabilit\u00e9 (maintainability). Nous garderons ces exigences pr\u00e9sentes lorsque nous programmerons des API sous Python.<\/p>\n\n\n\n<p>La m\u00e9thodologie la plus r\u00e9pandue de conception des API (API design) s\u2019appelle REST.<\/p>\n\n\n\n<p>L\u2019aspect le plus important de REST est qu\u2019elle est bas\u00e9e sur quatre m\u00e9thodes d\u00e9finies par le protocole HTTP : GET, POST, PUT et DELETE. Celles-ci correspondent aux quatre op\u00e9rations standard effectu\u00e9es sur une base de donn\u00e9es : READ, CREATE, UPDATE et DELETE.<\/p>\n\n\n\n<p>Dans la suite, on ne s\u2019int\u00e9ressera qu\u2019aux requ\u00eates GET, qui permettent de lire dans une base de donn\u00e9es.<\/p>\n\n\n\n<p>Les requ\u00eates HTTP jouent un r\u00f4le essentiel dans le cadre de la m\u00e9thodologie REST, de nombreux principes de conception gravitant autour de la fa\u00e7on dont les requ\u00eates doivent \u00eatre format\u00e9es.<\/p>\n\n\n\n<p>On a d\u00e9j\u00e0 cr\u00e9\u00e9 une requ\u00eate HTTP, qui renvoyait l\u2019int\u00e9gralit\u00e9 de notre catalogue.<\/p>\n\n\n\n<p>Commen\u00e7ons par une requ\u00eate mal con\u00e7ue :&nbsp;<\/p>\n\n\n\n<p><a href=\"http:\/\/api.example.com\/getemployee\/10\">http:\/\/api.example.com\/getemployee\/10<\/a><\/p>\n\n\n\n<p>Cette requ\u00eate pose un certain nombre de probl\u00e8mes : le premier est s\u00e9mantique ; dans une API REST, les verbes typiques sont GET, POST, PUT et DELETE, et sont d\u00e9termin\u00e9s par la m\u00e9thode de requ\u00eate plut\u00f4t que par l\u2019URL de requ\u00eate. Cela entra\u00eene que le mot \u00ab get \u00bb ne doit pas appara\u00eetre dans la requ\u00eate, puisque \u00ab get \u00bb est impliqu\u00e9 par le fait qu\u2019on utilise une requ\u00eate HTTP GET.<\/p>\n\n\n\n<p>De plus, les collections de ressources, comme employees ou users, doivent \u00eatre d\u00e9sign\u00e9es par des noms au pluriel.<\/p>\n\n\n\n<p>Cela permet d\u2019identifier facilement si l\u2019API se r\u00e9f\u00e8re \u00e0 un ensemble d\u2019employ\u00e9s (employees) ou \u00e0 un employ\u00e9 particulier (employee).<\/p>\n\n\n\n<p>Ces remarques pr\u00e9sentes \u00e0 l\u2019esprit, la nouvelle forme de notre requ\u00eate est la suivante :&nbsp;<\/p>\n\n\n\n<p><a href=\"http:\/\/api.example.com\/employees\/10\">http:\/\/api.example.com\/employees\/10<\/a><\/p>\n\n\n\n<p>La requ\u00eate ci-dessus utilise une partie du chemin pour fournir l\u2019identifiant.<\/p>\n\n\n\n<p>Bien que cette approche soit utilis\u00e9e en pratique, elle est trop rigide : avec des URL construites de cette fa\u00e7on, on ne peut filtrer que par un champ \u00e0 la fois.<\/p>\n\n\n\n<p>Les param\u00e8tres de requ\u00eates permettent de filtrer selon plusieurs champs de la base de donn\u00e9es et de sp\u00e9cifier des donn\u00e9es suppl\u00e9mentaires, comme un format de r\u00e9ponse :<\/p>\n\n\n\n<p><a href=\"http:\/\/api.example.com\/employees?nom=Durand&amp;prenom=Elodie&amp;output=xml\">http:\/\/api.example.com\/employees?nom=Durand&amp;prenom=Elodie&amp;output=xml<\/a><\/p>\n\n\n\n<p>Quand on met au point la structure des requ\u00eates soumises \u00e0 une API, il est \u00e9galement raisonnable de pr\u00e9voir les d\u00e9veloppements futurs.<\/p>\n\n\n\n<p>Bien que la version actuelle de l\u2019API ne fournisse de l\u2019information que sur un type de ressources (employees), il fait sens d\u2019envisager qu\u2019on puisse rajouter d\u2019autres ressources ou des fonctionnalit\u00e9s \u00e0 notre API, ce qui donne :<\/p>\n\n\n\n<p><a href=\"http:\/\/api.example.com\/resources\/employees?id=10\">http:\/\/api.example.com\/resources\/employees?id=10<\/a><\/p>\n\n\n\n<p>Sp\u00e9cifier un segment \u00ab resources \u00bb sur le chemin permet d\u2019offrir aux utilisateurs l\u2019option d\u2019acc\u00e9der \u00e0 toutes les ressources disponibles, avec des requ\u00eates du type : <\/p>\n\n\n\n<p><a href=\"https:\/\/api.example.com\/v1\/resources\/images?id=10\">https:\/\/api.example.com\/v1\/resources\/images?id=10<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/api.example.com\/v1\/resources\/all\">https:\/\/api.example.com\/v1\/resources\/all<\/a><\/p>\n\n\n\n<p>Une autre fa\u00e7on d\u2019envisager les d\u00e9veloppements futurs de l\u2019API est de rajouter un num\u00e9ro de version au chemin.<\/p>\n\n\n\n<p>Cela permet de continuer \u00e0 maintenir l\u2019acc\u00e8s \u00e0 l\u2019ancienne API si on est amen\u00e9 \u00e0 concevoir une nouvelle version, par exemple la v2, de l\u2019API.<\/p>\n\n\n\n<p>Cela permet aux applications et aux scripts con\u00e7us avec la premi\u00e8re version de l\u2019API de continuer \u00e0 fonctionner apr\u00e8s la mise \u00e0 jour.<\/p>\n\n\n\n<p>Finalement, une requ\u00eate bien con\u00e7ue, dans les cadres de la m\u00e9thodologie REST, est de la forme suivante :<\/p>\n\n\n\n<p><a href=\"https:\/\/api.example.com\/v1\/resources\/employees?id=10\">https:\/\/api.example.com\/v1\/resources\/employees?id=10<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-6-exemples-et-documentation\">6. Exemples et documentation<\/h2>\n\n\n\n<p>Sans documentation, m\u00eame la meilleure API est inutilisable.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>Une documentation doit \u00eatre associ\u00e9e \u00e0 l\u2019API, qui d\u00e9crit les ressources ou fonctionnalit\u00e9s disponibles via l\u2019API et fournit des exemples concrets d\u2019URLs de requ\u00eate et de code.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Il est n\u00e9cessaire de pr\u00e9voir un paragraphe pour chaque ressource, qui d\u00e9crit les champs pouvant \u00eatre requ\u00eat\u00e9s, comme title et id.<\/p>\n\n\n\n<p>Chaque paragraphe doit fournir un exemple de requ\u00eate HTTP ou un bloc de code.<\/p>\n\n\n\n<p>Une pratique usuelle de la documentation des API consiste \u00e0 annoter le code, les annotations pouvant \u00eatre automatiquement regroup\u00e9es en une documentation \u00e0 l\u2019aide d\u2019outils comme <a href=\"http:\/\/www.doxygen.nl\">Doxygen<\/a> ou <a href=\"http:\/\/www.sphinx-doc.org\/en\/stable\/\">Sphinx<\/a>.<\/p>\n\n\n\n<p>Ces outils g\u00e9n\u00e8rent une documentation \u00e0 partir des \u00ab docstrings \u00bb, c\u2019est-\u00e0-dire des cha\u00eenes de caract\u00e8res documentant les fonctions.<\/p>\n\n\n\n<p>Bien que ce type de documentation soit pr\u00e9cieux, on ne doit pas s\u2019arr\u00eater l\u00e0. Il faut se mettre dans la peau d\u2019un utilisateur et fournir des exemples concrets d\u2019utilisation.<\/p>\n\n\n\n<p>Id\u00e9alement, on doit disposer de trois types de documentation :&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>une <strong>r\u00e9f\u00e9rence<\/strong> d\u00e9taillant chaque route et son comportement ;<\/li>\n\n\n\n<li>un <strong>guide<\/strong> expliquant la r\u00e9f\u00e9rence en prose ;<\/li>\n\n\n\n<li>un ou deux <strong>tutoriels<\/strong> expliquant en d\u00e9tail chaque \u00e9tape.<\/li>\n<\/ul>\n\n\n\n<p>Pour un exemple de documentation d\u2019API, on pourra consulter le <a href=\"http:\/\/api.repo.nypl.org\">New York Public Library Digital Collections API<\/a> qui constitue un bon standard.&nbsp;<\/p>\n\n\n\n<p>Un autre exemple, plus fourni, est celui de la <a href=\"https:\/\/www.mediawiki.org\/wiki\/API:Main_page\">MediaWiki Action API<\/a> qui fournit de la documentation permettant aux utilisateurs de soumettre des requ\u00eates partielles \u00e0 l\u2019API.<\/p>\n\n\n\n<p>Pour d\u2019autres exemples de documentation d\u2019API, on pourra consulter l\u2019<a href=\"https:\/\/datahelpdesk.worldbank.org\/knowledgebase\/articles\/889392-api-documentation\">API de la Banque Mondiale<\/a> et l\u2019<a href=\"https:\/\/pro.europeana.eu\/resources\/apis\">API European Pro<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-7-references-bibliographiques\">7. R\u00e9f\u00e9rences bibliographiques<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>Creating Web APIs with Python and Flask, Patrick Smyth : <a href=\"https:\/\/programminghistorian.org\/en\/lessons\/creating-apis-with-python-and-flask\">https:\/\/programminghistorian.org\/en\/lessons\/creating-apis-with-python-and-flask<\/a><\/em><\/li>\n\n\n\n<li><em>Flask RESTful documentation : <a href=\"https:\/\/flask-restful.readthedocs.io\/en\/latest\/index.html\">https:\/\/flask-restful.readthedocs.io\/en\/latest\/index.html<\/a><\/em><\/li>\n\n\n\n<li><em>Flask Web Development : Developing Web Applications with Python (2\u00e8me \u00e9dition). M. Grinberg. O\u2019Reilly 2018.<\/em><\/li>\n\n\n\n<li><em>Architectural Styles and the Design of Network-Based Software Architectures. Fielding. Th\u00e8se, Universit\u00e9 de Californie, 2000.<\/em><\/li>\n<\/ul>\n\n\n\n<script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Qu\u2019est\u2011ce qu\u2019une API ?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Une API Web permet \u00e0 de l\u2019information et \u00e0 des fonctionnalit\u00e9s d\u2019\u00eatre manipul\u00e9es par des programmes informatiques via internet.\" \n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Quand utiliser une API ?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Si on dispose de donn\u00e9es qu\u2019on souhaite partager avec le monde entier, cr\u00e9er une API Web est une fa\u00e7on de le faire.\" \n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"La terminologie associ\u00e9e aux API\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"HTTP (HyperText Transfert Protocol) : c\u2019est le principal moyen de communiquer de l\u2019information sur Internet.\" \n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Un premier exemple\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Dans la suite, on va voir comment cr\u00e9er une API en utilisant Python et le cadre de travail Flask.\" \n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Quelques principes de bonne conception des API Web\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Deux aspects des bonnes API sont la facilit\u00e9 d\u2019utilisation (usability) et la maintenabilit\u00e9 (maintainability).\" \n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Exemples et documentation\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Sans documentation, m\u00eame la meilleure API est inutilisable.\" \n      }\n    }\n  ]\n}\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>L\u2019article va traiter de la programmation d\u2019API (Application Programming Interfaces) Web sous Python. Celles-ci sont des outils permettant de rendre accessibles de l\u2019information et des fonctionnalit\u00e9s via internet. Vous pouvez \u00e9galement d\u00e9couvrir comment connecter une API \u00e0 une base de donn\u00e9es sous python et comment programmer et documenter une API avec python, flask, swagger et [&hellip;]<\/p>\n","protected":false},"author":95,"featured_media":315930,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"editor_notices":[],"footnotes":""},"categories":[2511],"class_list":["post-140363","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cloud-dev"],"acf":[],"_links":{"self":[{"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/posts\/140363","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/users\/95"}],"replies":[{"embeddable":true,"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/comments?post=140363"}],"version-history":[{"count":4,"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/posts\/140363\/revisions"}],"predecessor-version":[{"id":317861,"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/posts\/140363\/revisions\/317861"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/media\/315930"}],"wp:attachment":[{"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/media?parent=140363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/liora.io\/wp-json\/wp\/v2\/categories?post=140363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}