La integración de una base de datos MySQL en una aplicación Flask se logra mediante SQLAlchemy como ORM y Flask-Migrate para gestionar las migraciones del esquema. A continuación se detalla el proceso completo de configuración, modelado y operaciones CRUD.
Instalación de dependencias
pip install flask flask-sqlalchemy flask-migrate pymysql
flask-sqlalchemy: ofrece la integración del ORM SQLAlchemy con Flask.flask-migrate: permite versionar y aplicar cambios en el esquema de base de datos.pymysql: driver de conexión para MySQL.
Configuración de la conexión
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
application = Flask(__name__)
DB_HOST = '127.0.0.1'
DB_PORT = 3306
DB_USER = 'root'
DB_PASS = '123456789'
DB_NAME = 'flask_study'
application.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8'
application.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
database = SQLAlchemy(application)
migrate = Migrate(application, database)
La cadena de conexión se construye con el formato mysql+pymysql://usuario:contraseña@host:puerto/base. Al pasar la instancia de la aplicación a SQLAlchemy, este lee automáticamente la configuración y establece la conexión.
Definición de modelos ORM
class Account(database.Model):
__tablename__ = 'account'
oid = database.Column(database.Integer, primary_key=True, autoincrement=True)
name = database.Column(database.String(50), nullable=False)
secret = database.Column(database.String(50), nullable=False)
mail = database.Column(database.String(50), nullable=False)
class Post(database.Model):
__tablename__ = 'post'
oid = database.Column(database.Integer, primary_key=True, autoincrement=True)
headline = database.Column(database.String(200), nullable=False)
body = database.Column(database.Text, nullable=False)
account_oid = database.Column(database.Integer, database.ForeignKey('account.oid'), nullable=False)
writer = database.relationship('Account', backref='posts')
Puntos clave del modelado:
database.ForeignKey('account.oid'): establece la relación de clave foránea hacia la columnaoidde la tablaaccount.database.relationship('Account', backref='posts'): crea una relación bidireccional. Mediantebackref, cada objetoAccountexpone el atributopostspara acceder a sus publicaciones relacionadas.
Mgiraciones de base de datos
El flujo de migraciones consta de tres comandos:
- Inicializar el repositorio de migraciones (solo se ejecuta una vez):
flask db init
- Generar el script de migración (detecta cambios en los modelos):
flask db migrate -m "Crear tablas account y post"
- Aplicar la migración (sincroniza los cambios con la base de datos):
flask db upgrade
Tras modificar la estructura de un modelo, basta con ejecutar los pasos 2 y 3.
Como alternativa en entorno de desarrollo, se pueden crear las tablas directamente:
with application.app_context():
database.create_all()
Operaciones CRUD
Inserción de registros
@application.route("/account/create")
def create_account():
new_account = Account(name='admin', secret='123456', mail='admin@example.com')
database.session.add(new_account)
database.session.commit()
return "Registro creado"
Consulta de registros
@application.route("/account/search")
def search_accounts():
# Búsqueda por clave primaria
found = Account.query.get(1)
# Búsqueda por condición
results = Account.query.filter(Account.name == 'admin').all()
for item in results:
print(item.name)
return "Búsqueda completada"
Actualización de registros
@application.route("/account/modify")
def modify_account():
target = Account.query.filter(Account.name == 'admin').first()
target.secret = 'new_secret'
database.session.commit()
return "Registro actualizado"
Eliminación de registros
@application.route("/account/remove")
def remove_account():
target = Account.query.filter(Account.name == 'admin').first()
database.session.delete(target)
database.session.commit()
return "Registro eliminado"
Operaciones con relaciones
@application.route("/post/create")
def create_post():
owner = Account.query.get(2)
new_post = Post(headline='Guía de Flask', body='Contenido del artículo', writer=owner)
database.session.add(new_post)
database.session.commit()
return "Publicación creada"
@application.route("/post/search")
def search_posts():
author = Account.query.get(2)
for publication in author.posts:
print(publication.headline)
return "Búsqueda completada"
Conceptos fundamentales
ORM (Mapeo Objeto-Relacional): transforma las tablas de la base de datos en clases de Python y las columnas en atributos. Esto permite interactuar con la base de datos manipulando objetos, evitando la escritura directa de SQL.
Relaciones y referencias inversas: La combinación de ForeignKey y relationship con backref establece relaciones uno-a-muchos. Desde el objeto hijo (Post) se accede al padre mediante el atributo definido en relationship (writer), y desde el padre (Account) se accede a los hijos mediante el atributo definido en backref (posts).
Gestión de sesiones: Todas las operaciones de escritura deben confirmarse explícitamente con database.session.commit(). La sesión garantiza la atomicidad de las transacciones; en caso de error se puede revertir con database.session.rollback().
Contexto de aplicación: En escenarios fuera de una petición HTTP (como scripts o consola), es necesario activar el contexto de la aplicación con with application.app_context() antes de interactuar con la base de datos.
Problemas frecuentes
- Eror de conexión: verificar las credredenciales, el driver
pymysqly que el servidor MySQL esté accesible. - Cambios no reflejados: ejecutar los comandos de migración o
database.create_all(). - Violación de clave foránea: asegurar que el registro padre referenciado existe antes de insertarr el hijo.
- Datos no persistidos: confirmar que se llama a
database.session.commit()después de cada operación de escritura.