Objetivos de Aprendizaje
Al finalizar esta clase, serás capaz de:
- Entender qué son las migraciones de base de datos
- Configurar Alembic en un proyecto de Python
- Crear migraciones automáticas y manuales
- Aplicar y revertir migraciones de esquema
- Manejar cambios de base de datos en entornos de producción
Que es Alembic? (10 min)
Alembic es una herramienta de migracion para SQLAlchemy. Permite:
- Versionar cambios en el esquema de base de datos
- Aplicar cambios de forma controlada
- Revertir cambios si algo falla
- Mantener sincronizados modelos y base de datos
Cuando usar migraciones:
- Agregar/eliminar tablas
- Agregar/eliminar columnas
- Cambiar tipos de datos
- Crear indices
Configuracion (15 min)
Instalacion
pip install alembic
Inicializar Alembic
# En la raiz del proyecto
alembic init alembic
Configurar alembic.ini
# alembic.ini
[alembic]
script_location = alembic
prepend_sys_path = .
version_path_separator = os
sqlalchemy.url = sqlite:///./taskflow.db
Configurar env.py
# alembic/env.py
from logging.config import fileConfig
from sqlalchemy import engine_from_config, pool
from alembic import context
import sys
import os
# Agregar el path del proyecto
sys.path.insert(0, os.getcwd())
# Importar modelos
from database import Base
from models.usuario import Usuario
from models.proyecto import Proyecto
from models.tarea import Tarea
from models.comentario import Comentario
config = context.config
fileConfig(config.config_file_name)
target_metadata = Base.metadata
Crear Migraciones (20 min)
Migracion Automatica
# Detectar cambios automaticamente
alembic revision --autogenerate -m "Crear tablas iniciales"
Migracion Manual
# Crear migracion vacia
alembic revision -m "Agregar columna avatar a usuarios"
Contenido de una migracion
# alembic/versions/xxxx_agregar_avatar.py
from alembic import op
import sqlalchemy as sa
def upgrade():
# Agregar columna
op.add_column('usuarios',
sa.Column('avatar', sa.String(255), nullable=True)
)
def downgrade():
# Eliminar columna
op.drop_column('usuarios', 'avatar')
Operaciones comunes
def upgrade():
# Crear tabla
op.create_table(
'notificaciones',
sa.Column('id', sa.Integer(), primary_key=True),
sa.Column('mensaje', sa.String(200), nullable=False),
sa.Column('leida', sa.Boolean(), default=False),
sa.Column('usuario_id', sa.Integer(), sa.ForeignKey('usuarios.id'))
)
# Agregar columna
op.add_column('tareas', sa.Column('prioridad', sa.String(20), default='media'))
# Crear indice
op.create_index('ix_tareas_prioridad', 'tareas', ['prioridad'])
# Modificar columna
op.alter_column('usuarios', 'email', nullable=False)
def downgrade():
op.drop_index('ix_tareas_prioridad', 'tareas')
op.drop_column('tareas', 'prioridad')
op.drop_table('notificaciones')
Aplicar Migraciones (10 min)
# Aplicar todas las migraciones pendientes
alembic upgrade head
# Aplicar una migracion especifica
alembic upgrade +1
# Revertir ultima migracion
alembic downgrade -1
# Revertir todo
alembic downgrade base
# Ver historial
alembic history
# Ver version actual
alembic current
Importante: Siempre revisa el SQL generado antes de aplicar en produccion.
Ejercicio: Agregar Tabla Etiquetas (20 min)
Crear migracion para agregar sistema de etiquetas a las tareas:
# 1. Crear modelo Etiqueta
# models/etiqueta.py
from sqlalchemy import String, Table, Column, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from typing import List
# Tabla de asociacion (muchos a muchos)
tarea_etiqueta = Table(
'tarea_etiqueta',
Base.metadata,
Column('tarea_id', ForeignKey('tareas.id'), primary_key=True),
Column('etiqueta_id', ForeignKey('etiquetas.id'), primary_key=True)
)
class Etiqueta(Base):
__tablename__ = "etiquetas"
id: Mapped[int] = mapped_column(primary_key=True)
nombre: Mapped[str] = mapped_column(String(50), unique=True)
color: Mapped[str] = mapped_column(String(7), default="#3498db") # Hex
# Relacion muchos a muchos
tareas: Mapped[List["Tarea"]] = relationship(
secondary=tarea_etiqueta,
back_populates="etiquetas"
)
# 2. Actualizar Tarea
class Tarea(Base):
# ... columnas existentes ...
etiquetas: Mapped[List["Etiqueta"]] = relationship(
secondary=tarea_etiqueta,
back_populates="tareas"
)
# 3. Crear migracion
# alembic revision --autogenerate -m "Agregar tabla etiquetas"
# 4. Aplicar migracion
# alembic upgrade head
E5 Proyecto: Implementa el sistema de etiquetas y migra la base de datos.
Resumen
- Alembic: Sistema de migraciones para SQLAlchemy
- upgrade(): Aplicar cambios
- downgrade(): Revertir cambios
- revision --autogenerate: Crear migracion automatica
- upgrade head: Aplicar todas las migraciones
- downgrade -1: Revertir ultima migracion