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)