Tutorial Flask API REST: Cómo Crear una API RESTful con Python Paso a Paso
Introducción
En el mundo del desarrollo backend, crear APIs RESTful es una habilidad fundamental. Este tutorial te guiará desde cero para construir una API RESTful utilizando Python y el framework Flask. Diseñado para desarrolladores principiantes e intermedios, aprenderás a configurar el entorno, crear rutas, manejar solicitudes HTTP, integrar una base de datos SQLite y agregar autenticación básica.
Al final, tendrás una API funcional y preparada para seguir mejorando según tus necesidades.
Tabla de Contenidos
- Instalación del entorno
- Configuración inicial del proyecto
- Creación de rutas en Flask
- Manejo de solicitudes HTTP
- Integración con bases de datos SQLite
- Autenticación básica en la API
- Conclusión y buenas prácticas
Instalación del entorno
Para comenzar a desarrollar nuestra API RESTful con Flask, debemos instalar las herramientas necesarias.
Paso 1: Instalar Python
Asegúrate de tener Python 3 instalado en tu sistema. Puedes verificarlo ejecutando:
1 2 |
python3 --version |
Si no lo tienes, descarga e instala la última versión desde python.org.
Paso 2: Crear un entorno virtual
Es recomendable trabajar en un entorno virtual para aislar las dependencias del proyecto.
1 2 3 4 |
python3 -m venv venv source venv/bin/activate # En Linux/Mac venv\Scripts\activate # En Windows |
Paso 3: Instalar Flask y extensión para base de datos
Instalamos Flask y Flask-SQLAlchemy para la integración con SQLite:
1 2 |
pip install Flask Flask-SQLAlchemy |
También instalaremos Flask-HTTPAuth para autenticación básica:
1 2 |
pip install Flask-HTTPAuth |
Configuración inicial del proyecto
Creamos una estructura simple para el proyecto:
1 2 3 4 |
/flask_api_tutorial /venv app.py |
Paso 1: Crear app.py
Este archivo contendrá nuestra aplicación Flask.
Paso 2: Configurar la app
Abrimos app.py
y escribimos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # Configuración de SQLite app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///api_database.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) if __name__ == '__main__': app.run(debug=True) |
-
La URI
sqlite:///api_database.db
crea o conecta una base de datos local llamadaapi_database.db
. -
debug=True
activa el modo depuración para desarrollo.
Creación de rutas en Flask
Las rutas permiten definir los puntos de acceso para nuestra API.
Paso 1: Crear ruta básica
Añadimos una ruta en app.py
para verificar que la API está corriendo:
1 2 3 4 5 6 |
from flask import jsonify @app.route('/') def home(): return jsonify({'message': 'API Flask RESTful corriendo'}) |
Paso 2: Crear rutas para recursos
Crearemos un recurso Libro
como ejemplo con rutas para operaciones CRUD.
Manejo de solicitudes HTTP
Éstas son las operaciones principales que una API RESTful debe manejar.
Paso 1: Crear modelo de datos
En app.py
definimos el modelo Libro
:
1 2 3 4 5 6 7 8 |
class Libro(db.Model): id = db.Column(db.Integer, primary_key=True) titulo = db.Column(db.String(100), nullable=False) autor = db.Column(db.String(50), nullable=False) def to_dict(self): return {'id': self.id, 'titulo': self.titulo, 'autor': self.autor} |
Paso 2: Crear base de datos
Ejecutamos lo siguiente en un terminal interactivo de Python:
1 2 3 4 |
from app import db db.create_all() |
Esto crea la tabla Libro
en api_database.db
.
Paso 3: Añadir rutas CRUD
Ahora, definimos rutas para las operaciones fundamentales:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
from flask import request # Obtener todos los libros @app.route('/libros', methods=['GET']) def obtener_libros(): libros = Libro.query.all() return jsonify([libro.to_dict() for libro in libros]) # Crear un libro nuevo @app.route('/libros', methods=['POST']) def crear_libro(): data = request.get_json() titulo = data.get('titulo') autor = data.get('autor') if not titulo or not autor: return jsonify({'error': 'Faltan campos'}), 400 nuevo_libro = Libro(titulo=titulo, autor=autor) db.session.add(nuevo_libro) db.session.commit() return jsonify(nuevo_libro.to_dict()), 201 # Obtener libro por ID @app.route('/libros/<int:id>', methods=['GET']) def obtener_libro(id): libro = Libro.query.get_or_404(id) return jsonify(libro.to_dict()) # Actualizar libro @app.route('/libros/<int:id>', methods=['PUT']) def actualizar_libro(id): libro = Libro.query.get_or_404(id) data = request.get_json() libro.titulo = data.get('titulo', libro.titulo) libro.autor = data.get('autor', libro.autor) db.session.commit() return jsonify(libro.to_dict()) # Eliminar libro @app.route('/libros/<int:id>', methods=['DELETE']) def eliminar_libro(id): libro = Libro.query.get_or_404(id) db.session.delete(libro) db.session.commit() return jsonify({'message': 'Libro eliminado'}) |
Estas rutas cubren las operaciones básicas: obtener (GET), crear (POST), actualizar (PUT) y eliminar (DELETE).
Integración con bases de datos SQLite
Ya integraste SQLite con Flask mediante SQLAlchemy, una poderosa ORM.
Explicación rápida
-
SQLAlchemy permite interactuar con SQLite usando código Python en vez de SQL directo.
-
El método
db.create_all()
crea las tablas usando la definición de clases que creamos. -
La sesión
db.session
se usa para agregar, modificar y eliminar registros.
Puedes ejecutar tu API con:
1 2 |
python app.py |
Y acceder a:
-
http://127.0.0.1:5000/libros
para obtener todos los libros. -
Envío de JSON al endpoint
/libros
para crear nuevos.
Puedes probar usando herramientas como Postman o curl
.
Autenticación básica en la API
Para asegurar nuestras rutas, añadiremos autenticación básica HTTP.
Paso 1: Configurar Flask-HTTPAuth
En app.py
importamos e inicializamos:
1 2 3 4 5 |
from flask_httpauth import HTTPBasicAuth from werkzeug.security import generate_password_hash, check_password_hash auth = HTTPBasicAuth() |
Paso 2: Crear usuarios y passwords
Para este tutorial, usaremos un diccionario simple:
1 2 3 4 5 6 7 8 9 10 |
usuarios = { 'usuario1': generate_password_hash('password123'), 'admin': generate_password_hash('adminpass') } @auth.verify_password def verificar_password(username, password): if username in usuarios and check_password_hash(usuarios.get(username), password): return username |
Paso 3: Proteger rutas
Añade el decorador @auth.login_required
a las rutas que quieras proteger:
1 2 3 4 5 6 |
@app.route('/libros', methods=['GET']) @auth.login_required def obtener_libros(): libros = Libro.query.all() return jsonify([libro.to_dict() for libro in libros]) |
Ahora, para acceder a estas rutas será necesario enviar credenciales HTTP.
Paso 4: Probar la autenticación
Ejemplo con curl
:
1 2 |
curl -u usuario1:password123 http://127.0.0.1:5000/libros |
Esto devuelve la lista de libros sólo si el usuario y la contraseña son correctos.
Conclusión y buenas prácticas
En este tutorial, aprendiste cómo crear una API RESTful paso a paso con Python y Flask. Cubrimos la instalación del entorno, configuración del proyecto, creación y manejo de rutas HTTP, integración con una base de datos SQLite y la incorporación de autenticación básica.
Buenas prácticas para tus APIs Flask RESTful:
-
Estructura el proyecto, separando la lógica en distintos módulos o carpetas a medida que crezca.
-
Valida siempre los datos que recibes para evitar errores y vulnerabilidades.
-
Añade manejo de errores personalizado para devolver respuestas claras.
-
Usa autenticación y autorización robustas, considera JWT o OAuth para proyectos avanzados.
-
Documenta tu API con herramientas como Swagger o Postman.
¡Empieza a construir tu API y sigue explorando el desarrollo backend Flask para crear aplicaciones robustas y escalables!
¿Quieres aprender más sobre desarrollo backend y creación de APIs? ¡Sigue nuestro blog y suscríbete para recibir tutoriales actualizados!
Código completo mínimo ejemplo app.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy from flask_httpauth import HTTPBasicAuth from werkzeug.security import generate_password_hash, check_password_hash app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///api_database.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) auth = HTTPBasicAuth() usuarios = { 'usuario1': generate_password_hash('password123'), 'admin': generate_password_hash('adminpass') } @auth.verify_password def verificar_password(username, password): if username in usuarios and check_password_hash(usuarios.get(username), password): return username class Libro(db.Model): id = db.Column(db.Integer, primary_key=True) titulo = db.Column(db.String(100), nullable=False) autor = db.Column(db.String(50), nullable=False) def to_dict(self): return {'id': self.id, 'titulo': self.titulo, 'autor': self.autor} @app.route('/') def home(): return jsonify({'message': 'API Flask RESTful corriendo'}) @app.route('/libros', methods=['GET']) @auth.login_required def obtener_libros(): libros = Libro.query.all() return jsonify([libro.to_dict() for libro in libros]) @app.route('/libros', methods=['POST']) def crear_libro(): data = request.get_json() titulo = data.get('titulo') autor = data.get('autor') if not titulo or not autor: return jsonify({'error': 'Faltan campos'}), 400 nuevo_libro = Libro(titulo=titulo, autor=autor) db.session.add(nuevo_libro) db.session.commit() return jsonify(nuevo_libro.to_dict()), 201 @app.route('/libros/<int:id>', methods=['GET']) def obtener_libro(id): libro = Libro.query.get_or_404(id) return jsonify(libro.to_dict()) @app.route('/libros/<int:id>', methods=['PUT']) def actualizar_libro(id): libro = Libro.query.get_or_404(id) data = request.get_json() libro.titulo = data.get('titulo', libro.titulo) libro.autor = data.get('autor', libro.autor) db.session.commit() return jsonify(libro.to_dict()) @app.route('/libros/<int:id>', methods=['DELETE']) def eliminar_libro(id): libro = Libro.query.get_or_404(id) db.session.delete(libro) db.session.commit() return jsonify({'message': 'Libro eliminado'}) if __name__ == '__main__': db.create_all() app.run(debug=True) |
¡Feliz desarrollo de APIs con Flask!