{"id":168354,"date":"2026-02-18T10:45:35","date_gmt":"2026-02-18T09:45:35","guid":{"rendered":"https:\/\/liora.io\/es\/?p=168354"},"modified":"2026-02-25T18:42:13","modified_gmt":"2026-02-25T17:42:13","slug":"programacion-de-api-web-en-python-con-flask","status":"publish","type":"post","link":"https:\/\/liora.io\/es\/programacion-de-api-web-en-python-con-flask","title":{"rendered":"Programaci\u00f3n de API web en Python con Flask"},"content":{"rendered":"\n<p><strong>Este art\u00edculo trata sobre la programaci\u00f3n de API (Application Programming Interfaces) web en Python. Se trata de herramientas que permiten acceder a informaci\u00f3n y funciones a trav\u00e9s de Internet. Tambi\u00e9n descubrir\u00e1s c\u00f3mo conectar una API a una base de datos en Python y c\u00f3mo desarrollarla y documentarla con Python, Flask, Swagger y Connexion. En este art\u00edculo veremos:<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-1-que-es-una-api\">1. \u00bfQu\u00e9 es una API?<\/h2>\n\n\n\n<p>Una <a href=\"https:\/\/liora.io\/es\/api-que-es-y-para-que-sirve\">API<\/a> Web permite manipular informaci\u00f3n y funciones mediante programas inform\u00e1ticos a trav\u00e9s de Internet.<\/p>\n\n\n\n<p>Por ejemplo, con la API Web de Twitter se puede escribir un programa en un lenguaje como Python o Javascript que recoja metadatos sobre tuits.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>De forma m\u00e1s general, en programaci\u00f3n, el t\u00e9rmino API (abreviatura de Application Programming Interface) se refiere a una parte de un programa inform\u00e1tico dise\u00f1ada para ser utilizada o manipulada por otro programa, a diferencia de las interfaces, que est\u00e1n dise\u00f1adas para ser utilizadas o manipuladas por humanos.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Los programas inform\u00e1ticos a menudo necesitan comunicarse entre s\u00ed o con el sistema operativo subyacente, y las API son una forma de hacerlo.<\/p>\n\n\n\n<p>En lo que sigue, sin embargo, nos limitaremos a las API web.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-2-cuando-utilizar-una-api\">2. \u00bfCu\u00e1ndo utilizar una API?<\/h2>\n\n\n\n<p>Cabe se\u00f1alar que se puede proporcionar tanto un volcado de datos como una API; y son los usuarios quienes deben elegir lo que m\u00e1s les conviene.<\/p>\n\n\n\n<p>Si tienes datos que deseas compartir con el mundo, crear una API Web es una forma de hacerlo.<\/p>\n\n\n\n<p>Sin embargo, las API no siempre son la mejor forma de compartir datos con los usuarios.<\/p>\n\n\n\n<p>Si el volumen de datos que quieres compartir es relativamente peque\u00f1o, es mejor ofrecer un volcado de datos en forma de archivo <b>JSON, XML, CSV o Sqlite<\/b>. En funci\u00f3n de los recursos disponibles, este enfoque puede ser viable hasta un volumen de unos pocos gigabytes.<\/p>\n\n\n\n<p>Por lo general, utilizamos una API Web cuando:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Nuestro <b><a href=\"https:\/\/liora.io\/es\/conjunto-de-datos-o-datasets\">conjunto de datos<\/a> es voluminoso<\/b>, por lo que una descarga a trav\u00e9s de FTP resulta engorrosa o consume muchos recursos.<\/li>\n\n\n\n<li>Los usuarios necesitan <b>acceder a los datos en tiempo real<\/b>, por ejemplo, para visualizarlos en un sitio web o como parte de una aplicaci\u00f3n.<\/li>\n\n\n\n<li>Nuestros datos se modifican o actualizan con frecuencia.<\/li>\n\n\n\n<li>Los usuarios solo necesitan acceder a <b>una parte de los datos cada vez<\/b>.<\/li>\n\n\n\n<li>Los usuarios necesitan realizar acciones distintas a la simple consulta de los datos, como por ejemplo <b>contribuir, actualizar o borrar<\/b>.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-3-terminologia-asociada-a-las-api\">3. Terminolog\u00eda asociada a las API<\/h2>\n\n\n\n<p><strong>HTTP (HyperText Transfer Protocol)<\/strong> es el principal medio para intercambiar informaci\u00f3n en Internet. Implementa una serie de \u201cm\u00e9todos\u201d que indican en qu\u00e9 direcci\u00f3n deben desplazarse los datos y qu\u00e9 se debe hacer con ellos. Los m\u00e1s comunes son GET, que permite obtener datos de un servidor, y POST, que se utiliza para enviar nuevos datos a un servidor.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\" 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=\"\" \/><\/figure>\n\n\n\n<p><b>URL (Uniform Resource Locator):<\/b> direcci\u00f3n de un recurso en la web, como <b>http:\/\/www-facultesciences.univ-ubs.fr\/fr<\/b>. Una URL consta de un protocolo (<b>http:\/\/<\/b>), un dominio (<b>www-facultesciences.univ-ubs.fr<\/b>) y una ruta opcional (<b>\/es<\/b>).<\/p>\n\n\n\n<p>Describe la ubicaci\u00f3n de un recurso espec\u00edfico, como una p\u00e1gina web. En el \u00e1mbito de las API, los t\u00e9rminos URL, request, URI y endpoint hacen referencia a ideas similares. A continuaci\u00f3n, solo utilizaremos los t\u00e9rminos URL y request (solicitud), para mayor claridad.<\/p>\n\n\n\n<p>Para realizar una solicitud GET o seguir un enlace, solo se necesita un navegador web.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\" 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=\"\" \/><\/figure>\n\n\n\n<p><b>JSON (JavaScript Object Notation):<\/b> es un formato de almacenamiento de datos basado en texto y dise\u00f1ado para ser le\u00eddo tanto por humanos como por m\u00e1quinas. <b>JSON es el formato m\u00e1s com\u00fan para los datos recuperados por las API<\/b>, el segundo m\u00e1s com\u00fan es XML.<\/p>\n\n\n\n<p><b>REST (REpresentational State Transfer):<\/b> es una metodolog\u00eda que re\u00fane las mejores pr\u00e1cticas en materia de dise\u00f1o e implementaci\u00f3n de API. Las API dise\u00f1adas seg\u00fan los principios de la metodolog\u00eda REST se denominan <b>API REST<\/b>. Sin embargo, hay mucho debate sobre el significado exacto del t\u00e9rmino. En adelante, nos referiremos a ellas simplemente como API web o API HTTP.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-4-un-primer-ejemplo\">4. Un primer ejemplo<\/h2>\n\n\n\n<p>A continuaci\u00f3n veremos c\u00f3mo crear una API utilizando Python y el marco de trabajo Flask. Nuestro ejemplo de API ser\u00e1 un directorio de empleados de una empresa, que facilitar\u00e1 su nombre, apellidos, cargo y antig\u00fcedad. Empezaremos usando <a href=\"\/\">Flask<\/a> para crear una p\u00e1gina web para nuestro sitio. Esto nos permitir\u00e1 ver c\u00f3mo funciona Flask. Una vez que tengamos una aplicaci\u00f3n Flask peque\u00f1a y funcional en forma de p\u00e1gina web, convertiremos el sitio en una API.<\/p>\n\n\n\n<p>\u00bfPor qu\u00e9 Flask? <a href=\"https:\/\/liora.io\/es\/python-un-zoom-en-el-lenguaje-mas-popular\">Python<\/a> tiene varios frameworks para producir p\u00e1ginas web y API. El m\u00e1s conocido es Django, que es muy completo, pero puede ser abrumador para usuarios inexpertos. Las aplicaciones Flask se construyen a partir de frameworks muy sencillos y, por tanto, son m\u00e1s adecuadas para la creaci\u00f3n de prototipos de API.<\/p>\n\n\n\n<p>Empezamos creando un nuevo directorio en el ordenador, que servir\u00e1 como directorio del proyecto y al que llamaremos <b>projects<\/b>. Los archivos de nuestro proyecto se almacenar\u00e1n en un <b>subdirectorio de proyectos<\/b>, llamado <b>api<\/b>. A continuaci\u00f3n lanzamos Spyder 3 o cualquier otro IDE e introducimos el siguiente c\u00f3digo:<\/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>El programa se guarda con el nombre api.py en el directorio api creado anteriormente.<\/p>\n\n\n\n<p>Para ejecutarlo, abrimos una ventana de l\u00ednea de comandos desde este directorio e introducimos los siguientes comandos:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>\u00a0$ export FLASK_APP = api.py<br><br>\u00a0$ export FLASK_ENV = development<br><br>\u00a0$ flask run<\/strong><\/pre>\n\n\n\n<div style=\"height:1px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Alternativamente, se puede ejecutar el programa en Spyder o en cualquier otro IDE que se utilice.<\/p>\n\n\n\n<p>La consola mostrar\u00e1 lo siguiente (entre otras salidas):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><b>* Running on http:\/\/127.0.0.1:5000\/ (Press CTRL+C to quit)<\/b><\/pre>\n\n\n\n<div style=\"height:1px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Basta con introducir el enlace anterior en un navegador web para acceder a la aplicaci\u00f3n.<\/p>\n\n\n\n<p>As\u00ed que ya tienes una aplicaci\u00f3n web funcionando.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter 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\/sites\/7\/2024\/01\/API-1.png\" alt=\"\" style=\"width:auto;height:500px\" \/><\/figure>\n\n\n\n<p>Ahora echemos un vistazo a c\u00f3mo funciona Flask.<\/p>\n\n\n\n<p>Flask env\u00eda peticiones HTTP a funciones Python. En nuestro caso, hemos aplicado una ruta URL (&#8216;\/&#8217;) a una funci\u00f3n: <b>home<\/b>.<\/p>\n\n\n\n<p>Flask ejecuta el c\u00f3digo de la funci\u00f3n y muestra el resultado en el navegador. En nuestro ejemplo, el resultado es un c\u00f3digo HTML de bienvenida al sitio que aloja nuestra API.<\/p>\n\n\n\n<p>El proceso de aplicar URL a funciones se denomina enrutamiento (routing).<\/p>\n\n\n\n<p>La instrucci\u00f3n:<\/p>\n\n\n\n<p><strong>@app.route(\u2018\/\u2019, methods=[\u2018GET\u2019])<\/strong><\/p>\n\n\n\n<p>que aparece en el programa indica a Flask que la <b>funci\u00f3n home<\/b> corresponde a la ruta \/.<\/p>\n\n\n\n<p>La lista de m\u00e9todos <b>(methods=[&#8216;GET&#8217;])<\/b> es un argumento clave que indica a Flask qu\u00e9 tipo de peticiones HTTP est\u00e1n permitidas.<\/p>\n\n\n\n<p>A continuaci\u00f3n solo utilizaremos peticiones GET, pero muchas aplicaciones web utilizan tanto peticiones GET (para enviar datos desde la aplicaci\u00f3n a los usuarios) como peticiones POST (para recibir datos de los usuarios).<\/p>\n\n\n\n<p>Veamos el programa m\u00e1s de cerca.<\/p>\n\n\n\n<p><b>import Flask<\/b>: Esta instrucci\u00f3n se utiliza para importar la librer\u00eda Flask, que est\u00e1 disponible por defecto en Anaconda.<\/p>\n\n\n\n<p><b>app = flask.Flask(__name__)<\/b>: Crea el objeto de aplicaci\u00f3n Flask, que contiene los datos de la aplicaci\u00f3n y los m\u00e9todos correspondientes a las acciones que se pueden realizar sobre el objeto. La \u00faltima instrucci\u00f3n app.run( ) es un ejemplo de uso de un m\u00e9todo.<\/p>\n\n\n\n<p><b>app.config[\u00abDEBUG\u00bb = True]<\/b>: Lanza el depurador, que muestra un mensaje distinto de \u00abBad Gateway\u00bb si hay un error en la aplicaci\u00f3n.<\/p>\n\n\n\n<p><b>app.run( )<\/b>: Permite ejecutar la aplicaci\u00f3n.<\/p>\n\n\n\n<p>Ahora, para crear la API, vamos a especificar nuestros datos en forma de lista de diccionarios Python.<\/p>\n\n\n\n<p>Por ejemplo, vamos a proporcionar los datos de tres empleados de nuestra empresa. Cada diccionario contendr\u00e1 el n\u00famero de identificaci\u00f3n del empleado, sus apellidos, su nombre, su cargo y su antig\u00fcedad.<\/p>\n\n\n\n<p>Tambi\u00e9n introduciremos una nueva funci\u00f3n: una ruta que permita a los visitantes acceder a nuestros datos.<\/p>\n\n\n\n<p>As\u00ed que sustituimos el c\u00f3digo guardado en <b>api.py <\/b>por el siguiente c\u00f3digo:<\/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>Ejecutamos el c\u00f3digo en Spyder 3 y actualizamos la ventana del navegador.<\/p>\n\n\n\n<p>Para acceder a todos los datos, basta con introducir la direcci\u00f3n: <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 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\/sites\/7\/2024\/01\/unnamed.png\" alt=\"\" style=\"width:auto;height:500px\" \/><\/figure>\n\n\n\n<p>Utilizamos la funci\u00f3n <b>jsonify<\/b> de Flask. Esta funci\u00f3n convierte listas y diccionarios en formato JSON.<\/p>\n\n\n\n<p>Utilizando la ruta que hemos creado, los datos de nuestros empleados se convierten de una lista de diccionarios al formato JSON, antes de proporcion\u00e1rselos al usuario.<\/p>\n\n\n\n<p>En esta fase, hemos creado una <b>API funcional<\/b>, aunque limitada.<\/p>\n\n\n\n<p>En el estado actual de nuestra API, los usuarios solo pueden acceder a la totalidad de nuestros datos; no pueden especificar filtros para encontrar recursos espec\u00edficos.<\/p>\n\n\n\n<p>Aunque esto no es un problema con nuestros datos de prueba, que son pocos, se vuelve problem\u00e1tico a medida que se a\u00f1aden m\u00e1s datos.<\/p>\n\n\n\n<p>A continuaci\u00f3n, vamos a introducir una funci\u00f3n que permite a los <b>usuarios filtrar los resultados <\/b>devueltos mediante consultas m\u00e1s espec\u00edficas.<\/p>\n\n\n\n<p>El nuevo c\u00f3digo es el siguiente:<\/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>Una vez introducido, guardado y ejecutado el c\u00f3digo en Spyder 3, se pueden introducir las siguientes direcciones en el navegador:<\/p>\n\n\n\n<p><b>127.0.0.1:5000\/api\/v1\/resources\/employees?id=0<\/b><\/p>\n\n\n\n<p><b>127.0.0.1:5000\/api\/v1\/resources\/employees?id=1<\/b><\/p>\n\n\n\n<p><b>127.0.0.1:5000\/api\/v1\/resources\/employees?id=2<\/b><\/p>\n\n\n\n<p><b>127.0.0.1:5000\/api\/v1\/resources\/employees?id=3<\/b><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter 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\/sites\/7\/2024\/01\/API-3.png\" alt=\"\" style=\"width:auto;height:500px\" \/><\/figure>\n\n\n\n<p>Cada una de estas direcciones devuelve un resultado diferente, excepto la \u00faltima, que devuelve una lista vac\u00eda, ya que no hay ning\u00fan identificador de empleado 3.<\/p>\n\n\n\n<p>A continuaci\u00f3n, vamos a ver en detalle nuestra nueva API.<\/p>\n\n\n\n<p><i>Hemos creado una nueva funci\u00f3n api_root, con la instrucci\u00f3n @app_route, aplicada a la ruta \/api\/v1\/resources\/employees.<\/i><\/p>\n\n\n\n<p>Esto significa que la funci\u00f3n se ejecuta en cuanto se accede a<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>Hay que tener en cuenta que acceder al enlace sin especificar un ID devuelve el mensaje de error especificado en el c\u00f3digo: Error: No ID provided. Por favor, especifique un ID.<\/p>\n\n\n\n<p>En nuestra funci\u00f3n, hacemos dos cosas: primero examinamos la URL proporcionada para buscar un identificador y luego seleccionamos el libro que coincide con el identificador.<\/p>\n\n\n\n<p>El identificador debe proporcionarse con la sintaxis <b>?id=0<\/b>, por ejemplo.<\/p>\n\n\n\n<p>Los datos que se pasan a la URL de esta forma se denominan par\u00e1metros de solicitud. Son una caracter\u00edstica del protocolo HTTP.<\/p>\n\n\n\n<p>La siguiente parte del c\u00f3digo determina si existe un par\u00e1metro de solicitud del tipo ?id=0, y asigna el <b>ID suministrado a una variable<\/b>.<\/p>\n\n\n\n<p>A continuaci\u00f3n, se busca en el directorio de empleados, se identifica al empleado con el ID especificado y se a\u00f1ade a la lista devuelta como resultado.<\/p>\n\n\n\n<p>Por \u00faltimo, la instrucci\u00f3n return jsonify(results) devuelve los resultados en formato JSON para su visualizaci\u00f3n en el navegador.<\/p>\n\n\n\n<p>En esta etapa, hemos creado una API funcional. En las siguientes entradas, veremos c\u00f3mo crear una API un poco m\u00e1s compleja, utilizando una <a href=\"https:\/\/liora.io\/bien-choisir-sa-base-de-donnees-typologie\">base de datos<\/a>. Sin embargo, los principios fundamentales y las instrucciones seguir\u00e1n siendo los mismos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-5-algunos-principios-de-un-buen-diseno-de-api-web\">5. Algunos principios de un buen dise\u00f1o de API web<\/h2>\n\n\n\n<p>Dos aspectos de las buenas API son la usabilidad y la mantenibilidad. Tendremos en cuenta estos requisitos a la hora de programar API en Python.<\/p>\n\n\n\n<p>La metodolog\u00eda de dise\u00f1o de API m\u00e1s utilizada se llama REST.<\/p>\n\n\n\n<p>El aspecto m\u00e1s importante de REST es que se basa en cuatro m\u00e9todos definidos por el protocolo HTTP: GET, POST, PUT y DELETE. Estos corresponden a las cuatro operaciones est\u00e1ndar que se realizan en una base de datos: READ, CREATE, UPDATE y DELETE.<\/p>\n\n\n\n<p>En el resto del art\u00edculo examinaremos las solicitudes GET, que se utilizan para leer de una base de datos.<\/p>\n\n\n\n<p>Las solicitudes HTTP juegan un papel esencial en la metodolog\u00eda REST, con muchos principios de dise\u00f1o que giran en torno a c\u00f3mo deben formatearse las solicitudes.<\/p>\n\n\n\n<p>Ya hemos creado una solicitud HTTP que nos devuelve todo nuestro cat\u00e1logo.<\/p>\n\n\n\n<p>Empecemos con una solicitud mal dise\u00f1ada:<\/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>Esta solicitud plantea varios problemas: el primero es sem\u00e1ntico; en una API REST, los verbos t\u00edpicos son GET, POST, PUT y DELETE, y vienen determinados por el m\u00e9todo de solicitud y no por la URL de la solicitud. Esto significa que la palabra \u00abget\u00bb no deber\u00eda aparecer en la solicitud, ya que \u00abget\u00bb est\u00e1 impl\u00edcito por el hecho de que se est\u00e1 utilizando una solicitud HTTP GET.<\/p>\n\n\n\n<p>Adem\u00e1s, las colecciones de recursos, como empleados o usuarios, deben designarse con nombres en plural.<\/p>\n\n\n\n<p>Esto facilita la identificaci\u00f3n si la API se refiere a una colecci\u00f3n de empleados (employees) o a un empleado en particular (employee).<\/p>\n\n\n\n<p>Teniendo en cuenta estas observaciones, la nueva forma de nuestra solicitud es la siguiente:<\/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 solicitud anterior utiliza parte de la ruta para proporcionar el identificador.<\/p>\n\n\n\n<p>Aunque este enfoque se utiliza en la pr\u00e1ctica, es demasiado r\u00edgido: con las URL construidas de este modo, solo se puede filtrar por un campo cada vez.<\/p>\n\n\n\n<p>Los par\u00e1metros de consulta pueden utilizarse para filtrar por varios campos de la base de datos y para especificar datos adicionales, como un formato de respuesta:<\/p>\n\n\n\n<p><a href=\"http:\/\/api.example.com\/employees?apellidos=Durand&amp;nombre=Elodie&amp;output=xml\">http:\/\/api.example.com\/employees?apellidos=Durand&amp;nombre=Elodie&amp;output=xml<\/a><\/p>\n\n\n\n<p>A la hora de desarrollar la estructura de las solicitudes enviadas a una API, tambi\u00e9n es conveniente planificar futuros desarrollos.<\/p>\n\n\n\n<p>Aunque la versi\u00f3n actual de la API solo proporciona informaci\u00f3n sobre un tipo de recurso (employees), tiene sentido prever incorporar otros recursos o funcionalidades a nuestra API, lo que da:<\/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>Especificar un segmento \u00abrecursos\u00bb en la ruta, permite ofrecer a los usuarios la opci\u00f3n de acceder a todos los recursos disponibles, con solicitudes como: <\/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>Otra forma de contemplar futuros desarrollos de la API es a\u00f1adir un n\u00famero de versi\u00f3n a la ruta.<\/p>\n\n\n\n<p>Esto permite mantener el acceso a la antigua API si se desarrolla una nueva versi\u00f3n, como la v2, de la API.<\/p>\n\n\n\n<p>Esto permite que las aplicaciones y scripts dise\u00f1ados con la primera versi\u00f3n de la API sigan funcionando despu\u00e9s de la actualizaci\u00f3n.<\/p>\n\n\n\n<p>Por \u00faltimo, una solicitud bien dise\u00f1ada, en el marco de la metodolog\u00eda REST, tiene la siguiente forma: <\/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<h3 class=\"wp-block-heading\" id=\"h-6-ejemplos-y-documentacion\">6. Ejemplos y documentaci\u00f3n<\/h3>\n\n\n\n<p>Sin documentaci\u00f3n, incluso la mejor API es inutilizable.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>La documentaci\u00f3n debe estar asociada a la API, que describe los recursos o funcionalidades disponibles a trav\u00e9s de ella y proporciona ejemplos concretos de URL de solicitud y c\u00f3digo.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Debe haber un p\u00e1rrafo para cada recurso en el que se describan los campos que pueden solicitarse, como el t\u00edtulo y el ID.<\/p>\n\n\n\n<p>Cada p\u00e1rrafo debe proporcionar un ejemplo de solicitud HTTP o un bloque de c\u00f3digo.<\/p>\n\n\n\n<p>Una pr\u00e1ctica com\u00fan en la documentaci\u00f3n de API es anotar el c\u00f3digo, y las anotaciones se pueden agrupar autom\u00e1ticamente en una documentaci\u00f3n utilizando herramientas como <a href=\"\/\">Doxygen<\/a> o <a href=\"http:\/\/www.sphinx-doc.org\/en\/stable\/\">Sphinx<\/a>.<\/p>\n\n\n\n<p>Estas herramientas generan documentaci\u00f3n a partir de \u00abdocstrings\u00bb, es decir, cadenas de caracteres que documentan funciones.<\/p>\n\n\n\n<p>Aunque este tipo de documentaci\u00f3n tiene un valor incalculable, no debemos detenernos ah\u00ed. Hay que ponerse en la piel de un usuario y ofrecerle ejemplos concretos de uso.<\/p>\n\n\n\n<p>Lo ideal es disponer de tres tipos de documentaci\u00f3n:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>una <b>referencia<\/b> que detalle cada ruta y su comportamiento;<\/li>\n\n\n\n<li>una <b>gu\u00eda<\/b> que explique la referencia en de manera sencilla;<\/li>\n\n\n\n<li>uno o dos <b>tutoriales<\/b> que expliquen detalladamente cada paso.<\/li>\n<\/ul>\n\n\n\n<p>Para un ejemplo de documentaci\u00f3n de API, consulta la API de <a href=\"\/\">Colecciones Digitales de la Biblioteca P\u00fablica de Nueva York<\/a>, que constituye un buen est\u00e1ndar.<\/p>\n\n\n\n<p>Otro ejemplo m\u00e1s extenso es la <a href=\"https:\/\/www.mediawiki.org\/wiki\/API:Main_page\">MediaWiki Action API<\/a>, que proporciona documentaci\u00f3n que permite a los usuarios enviar solicitudes parciales a la API.<\/p>\n\n\n\n<p>Otros ejemplos de documentaci\u00f3n de API son la <a href=\"https:\/\/datahelpdesk.worldbank.org\/knowledgebase\/articles\/889392-api-documentation\">API del Banco Mundial<\/a> y la <a href=\"https:\/\/pro.europeana.eu\/resources\/apis\">API de European Pro<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-7-referencias\">7. Referencias<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><i>Creating Web APIs with Python and Flask, Patrick Smyth:<\/i><a href=\"https:\/\/programminghistorian.org\/en\/lessons\/creating-apis-with-python-and-flask\"> <i>https:\/\/programminghistorian.org\/en\/lessons\/creating-apis-with-python-and-flask<\/i><\/a><\/li>\n\n\n\n<li><i>Flask RESTful documentation:<\/i><\/li>\n\n\n\n<li><a href=\"https:\/\/flask-restful.readthedocs.io\/en\/latest\/index.html\"><i>https:\/\/flask-restful.readthedocs.io\/en\/latest\/index.html<\/i><\/a><\/li>\n\n\n\n<li><i>Flask Web Development: Developing Web Applications with Python (2.\u00aa edici\u00f3n). M. Grinberg. O\u2019Reilly 2018.<\/i><\/li>\n\n\n\n<li><i>Architectural Styles and the Design of Network-Based Software Architectures. Fielding. Tesis, Universidad de California, 2000<\/i>.<\/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\": \"1. \u00bfQu\u00e9 es una API?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Una API Web permite manipular informaci\u00f3n y funciones mediante programas a trav\u00e9s de Internet (ej. API Twitter para recolectar metadatos). En programaci\u00f3n, API (Application Programming Interface) es una parte de un programa dise\u00f1ada para ser usada por otro programa, a diferencia de interfaces para humanos.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"2. \u00bfCu\u00e1ndo utilizar una API?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Se usa una API Web cuando: conjunto de datos voluminoso (descarga FTP engorrosa), acceso en tiempo real necesario, datos se modifican\/actualizan frecuentemente, usuarios necesitan solo parte de los datos cada vez, o requieren acciones distintas a consulta (contribuir, actualizar, borrar). Para vol\u00famenes peque\u00f1os, mejor volcado JSON\/XML\/CSV\/Sqlite.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"3. Terminolog\u00eda asociada a las API\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"HTTP: protocolo para intercambiar informaci\u00f3n en Internet con m\u00e9todos GET (obtener datos) y POST (enviar nuevos datos). URL: direcci\u00f3n de un recurso (protocolo + dominio + ruta). JSON: formato texto para almacenamiento datos, legible por humanos\/m\u00e1quinas (el m\u00e1s com\u00fan en API). REST: metodolog\u00eda de mejores pr\u00e1cticas para dise\u00f1o de API (API REST = API web\/HTTP).\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"4. Un primer ejemplo\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Ejemplo con Flask (framework Python simple, ideal para prototipos API). Pasos: 1) Crear aplicaci\u00f3n Flask b\u00e1sica con ruta '\/', 2) A\u00f1adir datos de prueba (lista diccionarios empleados), 3) Crear ruta '\/api\/v1\/resources\/employees\/all' que devuelve todos los datos con jsonify, 4) Crear ruta '\/api\/v1\/resources\/employees' que filtra por par\u00e1metro ?id= en URL (ej. ?id=0) usando request.args. Flask asocia URLs a funciones mediante enrutamiento (@app.route).\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"5. Algunos principios de un buen dise\u00f1o de API web\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Dos aspectos clave: usabilidad y mantenibilidad. (El art\u00edculo contin\u00faa con estos principios, pero el contenido se corta).\"\n      }\n    }\n  ]\n}\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>Este art\u00edculo trata sobre la programaci\u00f3n de API (Application Programming Interfaces) web en Python. Se trata de herramientas que permiten acceder a informaci\u00f3n y funciones a trav\u00e9s de Internet. Tambi\u00e9n descubrir\u00e1s c\u00f3mo conectar una API a una base de datos en Python y c\u00f3mo desarrollarla y documentarla con Python, Flask, Swagger y Connexion. En este [&hellip;]<\/p>\n","protected":false},"author":82,"featured_media":183603,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"editor_notices":[],"footnotes":""},"categories":[2439],"class_list":["post-168354","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cloud-dev"],"acf":[],"_links":{"self":[{"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/posts\/168354","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/users\/82"}],"replies":[{"embeddable":true,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/comments?post=168354"}],"version-history":[{"count":5,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/posts\/168354\/revisions"}],"predecessor-version":[{"id":184301,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/posts\/168354\/revisions\/184301"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/media\/183603"}],"wp:attachment":[{"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/media?parent=168354"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/categories?post=168354"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}