Dominando SQLAlchemy ORM para operaciones de bases de datos en Python

Instalación y configuración

Para instalar SQLAlchemy, se utiliza el gestor de paquetes pip. Además, es necesario el controlador específico según el sistema de base de datos elegido.

pip install sqlalchemy
pip install psycopg2  # Para PostgreSQL
pip install pymysql   # Para MySQL

Componentes fundamentales

SQLAlchemy se basa en componentes clave: Engine gestiona la comunicación con la base de datos, Session administra las operaciones de persistencia, y los Modelos representan la estructura de las tablas.

Estableciendo la conexión

Se inicia la conexión mediante una cadena de conexión. La sesión se configura para desactivar la confirmación y vaciado automáticos.

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

conexion = create_engine('sqlite:///mi_base.db', echo=False)
FabricaSesion = sessionmaker(autocommit=False, autoflush=False, bind=conexion)
sesion_activa = FabricaSesion()

Definición de modelos de datos

Los modelos se definen como clases que heredan de una base declraativa. Las columnas se especifican con tipos y restricciones.

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, declarative_base

Base = declarative_base()

class Cliente(Base):
    __tablename__ = 'clientes'
    identificador = Column(Integer, primary_key=True)
    nombre_completo = Column(String(100), nullable=False)
    correo_electronico = Column(String(150), unique=True)
    
    pedidos = relationship("Pedido", back_populates="cliente")

class Producto(Base):
    __tablename__ = 'productos'
    codigo = Column(Integer, primary_key=True)
    descripcion = Column(String(200))
    precio_unitario = Column(Integer)
    
class Pedido(Base):
    __tablename__ = 'pedidos'
    numero = Column(Integer, primary_key=True)
    cliente_id = Column(Integer, ForeignKey('clientes.identificador'))
    
    cliente = relationship("Cliente", back_populates="pedidos")
    items = relationship("DetallePedido", back_populates="pedido")

class DetallePedido(Base):
    __tablename__ = 'detalle_pedidos'
    pedido_numero = Column(Integer, ForeignKey('pedidos.numero'), primary_key=True)
    producto_codigo = Column(Integer, ForeignKey('productos.codigo'), primary_key=True)
    cantidad = Column(Integer, default=1)
    
    pedido = relationship("Pedido", back_populates="items")
    producto = relationship("Producto")

Creación y eliminación de tablas

Se pueden generar todas las tablas defniidas en los modelos o eliminarlas por completo.

Base.metadata.create_all(bind=conexion)
# Base.metadata.drop_all(bind=conexion)

Operaciones CRUD básicas

Inserción de datos

Para agregar registros se utiliza el método add o add_all seguido de la confirmación.

nuevo_cliente = Cliente(nombre_completo="Ana Martínez", correo_electronico="ana@ejemplo.com")
sesion_activa.add(nuevo_cliente)
sesion_activa.commit()

sesion_activa.add_all([
    Cliente(nombre_completo="Carlos López", correo_electronico="carlos@ejemplo.com"),
    Cliente(nombre_completo="María García", correo_electronico="maria@ejemplo.com")
])
sesion_activa.commit()

Consulta de datos

Se utilizan métodos como all(), first() y get() para recuperar registros.

todos_clientes = sesion_activa.query(Cliente).all()
primer_cliente = sesion_activa.query(Cliente).first()
cliente_especifico = sesion_activa.query(Cliente).get(1)

Actualizacción de datos

Los atributos del objeto se modifican directamente y se confirman los cambios.

registro = sesion_activa.query(Cliente).get(1)
registro.nombre_completo = "Ana Martínez de López"
sesion_activa.commit()

Eliminación de datos

Se elimina el objeto de la sesión y se confirma la operación.

registro_a_eliminar = sesion_activa.query(Cliente).get(1)
sesion_activa.delete(registro_a_eliminar)
sesion_activa.commit()

Consultas avanzadas

SQLAlchemy permite construir consultas complejas con filtros, ordenamiento y operaciones de agregación.

from sqlalchemy import func

# Filtros con condiciones múltiples
from sqlalchemy import and_, or_

resultados = sesion_activa.query(Cliente).filter(
    and_(
        Cliente.nombre_completo.like("A%"),
        Cliente.correo_electronico.contains("@ejemplo.com")
    )
).all()

# Operaciones de agregación
total_clientes = sesion_activa.query(func.count(Cliente.identificador)).scalar()
resumen = sesion_activa.query(
    Cliente.nombre_completo,
    func.count(Pedido.numero)
).join(Pedido).group_by(Cliente.nombre_completo).all()

Manejo de relaciones entre modelos

Las relaciones se definen con relationship y permiten navegar entre objetos relacionados.

# Crear cliente con pedido asociado
cliente_nuevo = Cliente(nombre_completo="Pedro Sánchez", correo_electronico="pedro@ejemplo.com")
pedido_nuevo = Pedido(numero=1001, cliente=cliente_nuevo)
sesion_activa.add(pedido_nuevo)
sesion_activa.commit()

# Acceder a través de la relación
print(f"Pedido #{pedido_nuevo.numero} realizado por: {pedido_nuevo.cliente.nombre_completo}")

Gestión de transacciones

Las transacciones se controlan manualmente para garantizar la integridad de los datos.

try:
    cliente = Cliente(nombre_completo="Usuario Prueba", correo_electronico="prueba@test.com")
    sesion_activa.add(cliente)
    sesion_activa.commit()
except Exception as error:
    sesion_activa.rollback()
    print(f"Error en la transacción: {error}")

# Uso de contextos para sesiones
from contextlib import contextmanager

@contextmanager
def obtener_sesion():
    sesion = FabricaSesion()
    try:
        yield sesion
        sesion.commit()
    except:
        sesion.rollback()
        raise
    finally:
        sesion.close()

Recomendaciones de implementación

Para un uso eficiente, se recomienda gestionar sesiones por contexto, implementar manejo de errores, y optimizar consultas con carga ansiosa cuando sea necesario.

with obtener_sesion() as sesion:
    usuario = Cliente(nombre_completo="Ejemplo", correo_electronico="ejemplo@test.com")
    sesion.add(usuario)

Etiquetas: SQLAlchemy Python ORM SQLite PostgreSQL

Publicado el 6-12 03:07