Flask: ORM
Descubre cómo usar ORM en Flask con SQLAlchemy para definir modelos, gestionar relaciones y realizar operaciones CRUD de forma eficiente y segura.
Aprende Flask GRATIS y certifícateORM en Flask
El Object-Relational Mapping (ORM) representa una de las técnicas más fundamentales en el desarrollo web moderno, permitiendo que los desarrolladores trabajen con bases de datos utilizando objetos Python en lugar de escribir consultas SQL directamente. En el ecosistema Flask, esta funcionalidad se implementa principalmente a través de SQLAlchemy, una biblioteca que se ha convertido en el estándar de facto para la gestión de datos relacionales.
¿Qué es un ORM?
Un ORM actúa como una capa de abstracción entre el código Python y la base de datos relacional. Esta tecnología traduce automáticamente las operaciones realizadas sobre objetos Python en consultas SQL correspondientes, y viceversa. El resultado es un código más limpio, mantenible y menos propenso a errores de sintaxis SQL.
La principal ventaja del mapeo objeto-relacional radica en su capacidad para representar tablas de base de datos como clases Python, donde cada fila se convierte en una instancia de esa clase. Esta aproximación permite aprovechar todas las características del paradigma orientado a objetos, incluyendo herencia, encapsulación y polimorfismo.
SQLAlchemy como ORM principal
SQLAlchemy se distingue por su arquitectura flexible que ofrece tanto un enfoque de alto nivel (ORM) como acceso de bajo nivel (Core). Para aplicaciones Flask, el patrón más común utiliza Flask-SQLAlchemy, una extensión que integra SQLAlchemy de manera nativa con el framework.
La configuración básica requiere establecer la URI de conexión a la base de datos y inicializar la extensión:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
Definición de modelos
Los modelos en SQLAlchemy son clases Python que heredan de db.Model
y representan tablas en la base de datos. Cada atributo de clase corresponde a una columna, definida mediante el objeto db.Column
:
class Usuario(db.Model):
id = db.Column(db.Integer, primary_key=True)
nombre = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
activo = db.Column(db.Boolean, default=True)
def __repr__(self):
return f'<Usuario {self.nombre}>'
La definición de tipos de datos en SQLAlchemy abarca desde tipos básicos como Integer
, String
y Boolean
, hasta tipos más especializados como DateTime
, Text
y JSON
. Cada tipo se mapea automáticamente al equivalente apropiado en la base de datos subyacente.
Relaciones entre modelos
Las relaciones constituyen uno de los aspectos más potentes de SQLAlchemy, permitiendo modelar asociaciones complejas entre entidades. La relación más común es uno-a-muchos, implementada mediante claves foráneas:
class Categoria(db.Model):
id = db.Column(db.Integer, primary_key=True)
nombre = db.Column(db.String(50), nullable=False)
productos = db.relationship('Producto', backref='categoria', lazy=True)
class Producto(db.Model):
id = db.Column(db.Integer, primary_key=True)
nombre = db.Column(db.String(100), nullable=False)
precio = db.Column(db.Float, nullable=False)
categoria_id = db.Column(db.Integer, db.ForeignKey('categoria.id'), nullable=False)
El parámetro backref
crea automáticamente una referencia inversa, permitiendo acceder desde un producto a su categoría mediante producto.categoria
. El parámetro lazy
controla cuándo se cargan los datos relacionados, optimizando el rendimiento según las necesidades específicas.
Operaciones CRUD básicas
Las operaciones CRUD (Create, Read, Update, Delete) se simplifican considerablemente con SQLAlchemy. La creación de registros implica instanciar el modelo y agregarlo a la sesión:
# Crear
nuevo_usuario = Usuario(nombre='Ana García', email='ana@ejemplo.com')
db.session.add(nuevo_usuario)
db.session.commit()
# Leer
usuario = Usuario.query.filter_by(email='ana@ejemplo.com').first()
todos_usuarios = Usuario.query.all()
# Actualizar
usuario.nombre = 'Ana María García'
db.session.commit()
# Eliminar
db.session.delete(usuario)
db.session.commit()
Consultas avanzadas
SQLAlchemy proporciona una API de consultas rica y expresiva que permite construir consultas complejas de manera intuitiva. Los métodos de filtrado incluyen filter()
, filter_by()
, order_by()
, y limit()
:
# Filtros múltiples
usuarios_activos = Usuario.query.filter(
Usuario.activo == True,
Usuario.email.contains('@empresa.com')
).order_by(Usuario.nombre).all()
# Consultas con joins
productos_categoria = db.session.query(Producto, Categoria).join(Categoria).filter(
Categoria.nombre == 'Electrónicos'
).all()
Migraciones de base de datos
Las migraciones gestionan los cambios en el esquema de la base de datos de forma controlada y versionada. Flask-Migrate, basado en Alembic de SQLAlchemy, automatiza este proceso:
from flask_migrate import Migrate
migrate = Migrate(app, db)
Los comandos de migración permiten generar y aplicar cambios incrementales:
flask db init
flask db migrate -m "Crear tabla usuarios"
flask db upgrade
Gestión de sesiones
La sesión de SQLAlchemy actúa como una unidad de trabajo que agrupa operaciones de base de datos. Flask-SQLAlchemy maneja automáticamente el ciclo de vida de las sesiones, pero es importante comprender conceptos como commit, rollback y flush:
try:
db.session.add(nuevo_registro)
db.session.flush() # Envía a la BD sin confirmar
# Operaciones adicionales
db.session.commit() # Confirma todos los cambios
except Exception as e:
db.session.rollback() # Revierte cambios en caso de error
raise e
La gestión adecuada de transacciones garantiza la integridad de los datos y permite implementar operaciones atómicas complejas que involucren múltiples tablas y registros.
Lecciones de este módulo de Flask
Lecciones de programación del módulo ORM del curso de Flask.
Ejercicios de programación en este módulo de Flask
Evalúa tus conocimientos en ORM con ejercicios de programación ORM de tipo Test, Puzzle, Código y Proyecto con VSCode.