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ícate

ORM 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.

Empezar curso de Flask

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.