Integración de Base de Datos con Flask y SQLAlchemy

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 columna oid de la tabla account.
  • database.relationship('Account', backref='posts'): crea una relación bidireccional. Mediante backref, cada objeto Account expone el atributo posts para acceder a sus publicaciones relacionadas.

Mgiraciones de base de datos

El flujo de migraciones consta de tres comandos:

  1. Inicializar el repositorio de migraciones (solo se ejecuta una vez):
flask db init

  1. Generar el script de migración (detecta cambios en los modelos):
flask db migrate -m "Crear tablas account y post"

  1. 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 pymysql y 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.

Etiquetas: Flask SQLAlchemy Flask-Migrate MySQL ORM

Publicado el 6-25 04:07