En este tema, aprenderás a construir APIs RESTful utilizando Flask, un microframework de Python. Flask es conocido por su simplicidad y flexibilidad, lo que lo hace ideal para desarrollar aplicaciones web y APIs.
Contenido
- Introducción a las APIs REST
- Instalación y Configuración de Flask
- Creación de Rutas y Endpoints
- Manejo de Solicitudes y Respuestas
- Conexión a una Base de Datos
- Autenticación y Autorización
- Pruebas de la API
- Conclusión
- Introducción a las APIs REST
Las APIs REST (Representational State Transfer) son un estilo arquitectónico para diseñar servicios web. Utilizan métodos HTTP y se basan en recursos, que son identificados por URLs.
Conceptos Clave
- Recursos: Entidades que se pueden crear, leer, actualizar y eliminar (CRUD).
- Métodos HTTP:
GET
: Obtener datos.POST
: Crear un nuevo recurso.PUT
: Actualizar un recurso existente.DELETE
: Eliminar un recurso.
- Endpoints: URLs que representan recursos y permiten interactuar con ellos.
- Instalación y Configuración de Flask
Primero, necesitas instalar Flask. Puedes hacerlo utilizando pip
:
Configuración Básica
Crea un archivo llamado app.py
y configura una aplicación Flask básica:
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' if __name__ == '__main__': app.run(debug=True)
Ejecuta el archivo con:
Visita http://127.0.0.1:5000/
en tu navegador para ver la aplicación en funcionamiento.
- Creación de Rutas y Endpoints
Vamos a crear una API para gestionar una lista de tareas (To-Do List).
Definición de Rutas
from flask import Flask, jsonify, request app = Flask(__name__) tasks = [ {'id': 1, 'title': 'Learn Flask', 'description': 'Learn how to build APIs with Flask', 'done': False}, {'id': 2, 'title': 'Build an API', 'description': 'Build a RESTful API using Flask', 'done': False} ] @app.route('/tasks', methods=['GET']) def get_tasks(): return jsonify({'tasks': tasks}) @app.route('/tasks/<int:task_id>', methods=['GET']) def get_task(task_id): task = next((task for task in tasks if task['id'] == task_id), None) if task is None: return jsonify({'error': 'Task not found'}), 404 return jsonify({'task': task}) if __name__ == '__main__': app.run(debug=True)
Explicación del Código
@app.route('/tasks', methods=['GET'])
: Define una ruta para obtener todas las tareas.@app.route('/tasks/<int:task_id>', methods=['GET'])
: Define una ruta para obtener una tarea específica por su ID.jsonify
: Convierte los datos de Python en JSON.
- Manejo de Solicitudes y Respuestas
Crear una Nueva Tarea
@app.route('/tasks', methods=['POST']) def create_task(): if not request.json or not 'title' in request.json: return jsonify({'error': 'Bad Request'}), 400 task = { 'id': tasks[-1]['id'] + 1, 'title': request.json['title'], 'description': request.json.get('description', ""), 'done': False } tasks.append(task) return jsonify({'task': task}), 201
Actualizar una Tarea
@app.route('/tasks/<int:task_id>', methods=['PUT']) def update_task(task_id): task = next((task for task in tasks if task['id'] == task_id), None) if task is None: return jsonify({'error': 'Task not found'}), 404 if not request.json: return jsonify({'error': 'Bad Request'}), 400 task['title'] = request.json.get('title', task['title']) task['description'] = request.json.get('description', task['description']) task['done'] = request.json.get('done', task['done']) return jsonify({'task': task})
Eliminar una Tarea
@app.route('/tasks/<int:task_id>', methods=['DELETE']) def delete_task(task_id): task = next((task for task in tasks if task['id'] == task_id), None) if task is None: return jsonify({'error': 'Task not found'}), 404 tasks.remove(task) return jsonify({'result': True})
- Conexión a una Base de Datos
Para almacenar datos de manera persistente, puedes conectar tu API a una base de datos. Aquí usaremos SQLite con SQLAlchemy.
Instalación de SQLAlchemy
Configuración de SQLAlchemy
from flask_sqlalchemy import SQLAlchemy app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///tasks.db' db = SQLAlchemy(app) class Task(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(80), nullable=False) description = db.Column(db.String(200), nullable=True) done = db.Column(db.Boolean, default=False) db.create_all()
CRUD con SQLAlchemy
Actualiza las rutas para interactuar con la base de datos:
@app.route('/tasks', methods=['GET']) def get_tasks(): tasks = Task.query.all() return jsonify({'tasks': [task.to_dict() for task in tasks]}) @app.route('/tasks/<int:task_id>', methods=['GET']) def get_task(task_id): task = Task.query.get(task_id) if task is None: return jsonify({'error': 'Task not found'}), 404 return jsonify({'task': task.to_dict()}) @app.route('/tasks', methods=['POST']) def create_task(): if not request.json or not 'title' in request.json: return jsonify({'error': 'Bad Request'}), 400 task = Task( title=request.json['title'], description=request.json.get('description', ""), done=False ) db.session.add(task) db.session.commit() return jsonify({'task': task.to_dict()}), 201 @app.route('/tasks/<int:task_id>', methods=['PUT']) def update_task(task_id): task = Task.query.get(task_id) if task is None: return jsonify({'error': 'Task not found'}), 404 if not request.json: return jsonify({'error': 'Bad Request'}), 400 task.title = request.json.get('title', task.title) task.description = request.json.get('description', task.description) task.done = request.json.get('done', task.done) db.session.commit() return jsonify({'task': task.to_dict()}) @app.route('/tasks/<int:task_id>', methods=['DELETE']) def delete_task(task_id): task = Task.query.get(task_id) if task is None: return jsonify({'error': 'Task not found'}), 404 db.session.delete(task) db.session.commit() return jsonify({'result': True})
- Autenticación y Autorización
Para proteger tu API, puedes implementar autenticación y autorización. Aquí usaremos tokens JWT (JSON Web Tokens).
Instalación de Flask-JWT-Extended
Configuración de JWT
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity app.config['JWT_SECRET_KEY'] = 'your_secret_key' jwt = JWTManager(app) @app.route('/login', methods=['POST']) def login(): if not request.json or not 'username' in request.json or not 'password' in request.json: return jsonify({'error': 'Bad Request'}), 400 username = request.json['username'] password = request.json['password'] # Aquí deberías verificar el usuario y la contraseña access_token = create_access_token(identity=username) return jsonify(access_token=access_token), 200 @app.route('/tasks', methods=['GET']) @jwt_required() def get_tasks(): current_user = get_jwt_identity() tasks = Task.query.all() return jsonify({'tasks': [task.to_dict() for task in tasks]})
- Pruebas de la API
Para probar tu API, puedes usar herramientas como Postman o escribir pruebas automatizadas con unittest
.
Prueba con Postman
- GET /tasks: Verifica que puedes obtener la lista de tareas.
- POST /tasks: Crea una nueva tarea y verifica que se añade correctamente.
- PUT /tasks/{id}: Actualiza una tarea existente.
- DELETE /tasks/{id}: Elimina una tarea.
Pruebas Automatizadas
import unittest import json from app import app, db, Task class APITestCase(unittest.TestCase): def setUp(self): self.app = app.test_client() db.create_all() def tearDown(self): db.session.remove() db.drop_all() def test_get_tasks(self): response = self.app.get('/tasks') self.assertEqual(response.status_code, 200) def test_create_task(self): response = self.app.post('/tasks', data=json.dumps({'title': 'Test Task'}), content_type='application/json') self.assertEqual(response.status_code, 201) if __name__ == '__main__': unittest.main()
- Conclusión
En este tema, has aprendido a construir una API RESTful utilizando Flask. Has cubierto desde la creación de rutas y endpoints hasta la conexión a una base de datos y la implementación de autenticación. Además, has visto cómo probar tu API para asegurarte de que funciona correctamente.
Resumen
- APIs REST: Estilo arquitectónico para diseñar servicios web.
- Flask: Microframework de Python para desarrollar aplicaciones web y APIs.
- SQLAlchemy: ORM para interactuar con bases de datos.
- JWT: Método para autenticación y autorización.
Con estos conocimientos, estás preparado para construir y desplegar tus propias APIs RESTful utilizando Flask. ¡Sigue practicando y explorando más funcionalidades avanzadas de Flask y sus extensiones!
Curso de Programación en Python
Módulo 1: Introducción a Python
- Introducción a Python
- Configuración del Entorno de Desarrollo
- Sintaxis de Python y Tipos de Datos Básicos
- Variables y Constantes
- Entrada y Salida Básica
Módulo 2: Estructuras de Control
- Sentencias Condicionales
- Bucles: for y while
- Herramientas de Control de Flujo
- Comprensiones de Listas
Módulo 3: Funciones y Módulos
- Definición de Funciones
- Argumentos de Función
- Funciones Lambda
- Módulos y Paquetes
- Visión General de la Biblioteca Estándar
Módulo 4: Estructuras de Datos
Módulo 5: Programación Orientada a Objetos
Módulo 6: Manejo de Archivos
- Lectura y Escritura de Archivos
- Trabajo con Archivos CSV
- Manejo de Datos JSON
- Operaciones de Archivos y Directorios
Módulo 7: Manejo de Errores y Excepciones
- Introducción a las Excepciones
- Manejo de Excepciones
- Lanzamiento de Excepciones
- Excepciones Personalizadas
Módulo 8: Temas Avanzados
- Decoradores
- Generadores
- Administradores de Contexto
- Concurrencia: Hilos y Procesos
- Asyncio para Programación Asíncrona
Módulo 9: Pruebas y Depuración
- Introducción a las Pruebas
- Pruebas Unitarias con unittest
- Desarrollo Guiado por Pruebas
- Técnicas de Depuración
- Uso de pdb para Depuración
Módulo 10: Desarrollo Web con Python
- Introducción al Desarrollo Web
- Fundamentos del Framework Flask
- Construcción de APIs REST con Flask
- Introducción a Django
- Construcción de Aplicaciones Web con Django
Módulo 11: Ciencia de Datos con Python
- Introducción a la Ciencia de Datos
- NumPy para Computación Numérica
- Pandas para Manipulación de Datos
- Matplotlib para Visualización de Datos
- Introducción al Aprendizaje Automático con scikit-learn