A tu propio ritmo

Explora nuestra extensa colección de cursos diseñados para ayudarte a dominar varios temas y habilidades. Ya seas un principiante o un aprendiz avanzado, aquí hay algo para todos.

Bootcamp

Aprende en vivo

Únete a nosotros en nuestros talleres gratuitos, webinars y otros eventos para aprender más sobre nuestros programas y comenzar tu camino para convertirte en desarrollador.

Próximos eventos en vivo

Catálogo de contenidos

Para los geeks autodidactas, este es nuestro extenso catálogo de contenido con todos los materiales y tutoriales que hemos desarrollado hasta el día de hoy.

Tiene sentido comenzar a aprender leyendo y viendo videos sobre los fundamentos y cómo funcionan las cosas.

Buscar en lecciones


IngresarEmpezar
← Regresar a lecciones
Editar en Github

Todo lo que necesitas saber sobre SQLAlchemy

¿Qué es SQL Alchemy?
¿Por qué usar un ORM?
  • Por ejemplo:

¿Qué es SQL Alchemy?

SQLAlchemy es un Object-Relational Mapper/Mapping-tool, o un ORM, es una librería que los desarrolladores utilizan para crear bases de datos y manipular sus datos sin la necesidad de conocer/usar SQL.

Existen otras alternativas en Python como Peewee, y otros lenguajes tienen sus propios ORMs, como PHP Eloquent o Java Hibernate.

¿Por qué usar un ORM?

Los ORM han ganado popularidad debido a que lidiar con el lenguaje SQL directamente requiere de mucho esfuerzo en la mayoría de los casos. El objetivo del ORM entonces es simplificar el mantenimiento de tus datos. Esto se hace creando objetos para tratar con las interacciones de la base de datos.

Básicamente, con ORM no tendrás que escribir SQL otra vez (el 95% del tiempo) y podrás trabajar con objetos.

Por ejemplo:

Para insertar un usuario con SQL tienes que escribir:

1INSERT INTO user (name, last_name) VALUES ('Bob', 'Ross');

Con un ORM tu código sigue siendo un código familiar como este:

1user = User() 2user.name = "Bob" 3user.last_name = "Ross" 4 5# Agrega el user a la base de datos 6db.session.add(user) 7 8# Parecido al commit de Git, lo que hace esta función es guardar todos los cambios que hayas hecho 9db.session.commit()

Basta con que utilices la función db.session.commit() y todo lo que hayas hecho con tu código se traducirá a código de lenguaje SQL.

Revisemos las operaciones más típicas que se pueden realizar sobre una base de datos

Importando e inicializando la aplicación

Para utilizar SQL Alchemy necesitamos instalar la librería flask de Python. Una vez lo hayamos hecho, estableceremos una conexión a la base de datos y definiremos el objeto db, que es lo más importante para empezar a trabajar con ella.

1from flask import Flask 2from flask_sqlalchemy import SQLAlchemy 3 4app = Flask(__name__) 5app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////tmp/test.db" 6db = SQLAlchemy(app)

Creando nuestra base de datos

El primer paso sería definir nuestro modelo:

1class Person(Base): 2 __tablename__ = "person" 3 4 # Aquí definimos el nombre de la tabla "Person" 5 # Ten en cuenta que cada columna es también un atributo normal de primera instancia de Python. 6 id = Column(Integer, primary_key = True) 7 name = Column(String(250), nullable = False) 8 9 # El método serialize convierte el objeto en un diccionario 10 def serialize(self): 11 return { 12 "id": self.id, 13 "name": self.name 14 }

INSERT: Insertando un registro en la base de datos

Para insertar un registro en la base de datos, es necesario, primero, contar con la instancia que se desea añadir. A continuación, agregarlo a la sesión de la base de datos y completar la acción con un commit. En el siguiente código se visualiza esta funcionalidad (reemplaza <username_value> y <email_value> con los valores reales que desees agregar):

1person = Person(username = <username_value>, email = <email_value>) 2db.session.add(person) 3db.session.commit()

SELECT: Buscando o recuperando registros de la base de datos

Hay 3 formas para obtener información de la base de datos:

  1. Obtener todos los registros de una tabla/modelo en particular usando MyModel.query.all()
  2. Obtener un único registro en función de su clave principal mediante MyModel.query.get(id)
  3. Obtener un grupo de registros en función de una consulta Person.query.filter_by(arg1=value, arg2=value, ...)
1# Obtener todos los registros de una tabla/modelo en particular, en este caso, de Person 2all_people = Person.query.all() 3all_people = list(map(lambda x: x.serialize(), all_people)) 4 5# Obtener un único registro en función de su clave principal, que en este caso es el "id" de la persona (solo funciona con las claves principales) 6person = Person.query.get(3) 7 8# Obtener un grupo de registros en función de una consulta, en este caso, el string "alex" en la columna "name" 9all_people = Person.query.filter_by(name = "alex") 10all_people = list(map(lambda x: x.serialize(), all_people))

DELETE: Eliminando un registro de la base de datos

Para eliminar un registro de la base de datos es necesario seleccionar previamente la instancia que se desee borrar (a través de su clave primaria, el id) y eliminarla utilizando db.session.delete(person), de acuerdo al siguiente ejemplo:

1person = Person.query.get(3) 2db.session.delete(person) 3db.session.commit()

UDPATE: Actualizar un registro

Para modificar un registro, hay que seleccionar previamente el mismo de la base de datos, luego puedes trabajar con él cambiando sus propiedades y hacer commit nuevamente, según el siguiente ejemplo:

1person = Person.query.get(3) 2person.name = "Bob" 3db.session.commit()

Transacciones

Una transacción es una secuencia de operaciones (como INSERT, UPDATE, SELECT) realizadas en tu base de datos. Para que una transacción esté completa, todas las operaciones deben ser exitosas. Si una operación falla, toda la transacción falla.

Todas las transacciones deben asegurar 4 propiedades principales (conocidas como propiedades ACID): Atomicidad, Consistencia, Aislamiento y Durabilidad.

Propiedades ACID

Una transacción termina con COMMIT o ROLLBACK.

COMMIT: session.commit()

El comando COMMIT se usa para guardar de manera permanente los cambios realizados en una transacción dentro de la base de datos.

Cuando usas INSERT, UPDATE o DELETE, los cambios realizados con estos comandos no son permanentes, los cambios hechos pueden deshacerse o, dicho con otras palabras, podemos volver atrás.

Sin embargo, cuando usas el comando COMMIT los cambios en tu base de datos serán permanentes.

ROLLBACK: session.rollback()

El comando ROLLBACK restaura tu base de datos hasta tu último COMMIT. También puedes usarlo con el comando SAVEPOINT para saltar a un punto que hayas guardado durante una transacción en curso.

Del mismo modo, si usas UPDATE para hacer cambios en tu base de datos, puedes deshacerlos usando el comando ROLLBACK, pero solo si aún no has usado el comando COMMIT de esta forma:

1db.session.rollback()

SAVEPOINT: session.begin_nested()

El comando SAVEPOINT se usa para guardar temporalmente una transacción para así poder volver a cierto punto utilizando el comando ROLLBACK si así lo necesitas. Puedes usarlo así:

1db.session.begin_nested()

Este comando se puede llamar muchas veces, y con cada llamada se establece un punto de control llamado checkpoint y que lleva asociado un identificador único.

SQL checkpoint

Pongamos, por ejemplo, el caso de que queramos preparar una pizza y preparemos una base de datos en la que introducir los ingredientes que lleva. La base de esta pizza que queremos preparar lleva tres ingredientes: mozzarella, tomate y aceitunas. Nuestra tabla se va a llamar 'Pizza' y, después de insertar los ingredientes, se vería de la siguiente manera:

SQL tabla pizza

Además, tenemos una lista de ingredientes extra que podemos añadir: escogemos carne primero, pero luego cambiamos de parecer y queremos reemplazarla por champiñones. También añadiremos pepperoni y bacon. Veamos como se haría esta transacción:

1# Supongamos que ya tenemos los ingredientes base añadidos con anterioridad 2 3# Ahora insertamos un nuevo ingrediente en la pizza, la carne 4ingredient = Ingredient() 5ingredient.name = "meat" 6ingredient.id = 4 7db.session.add(ingredient) 8 9# Ahora hacemos COMMIT y lo guardamos en la base de datos, de tal forma que fijamos el ingrediente en la Pizza 10db.session.commit() 11 12# Reemplazamos el cuarto ingrediente, que antes era la carne, por los champiñones 13ingredient = Ingredient.query.get(4) 14ingredient.name = "mushrooms" 15db.session.commit() 16 17# Guardamos un "checkpoint" 18checkpoint_a = db.session.begin_nested() 19 20# Añadimos pepperoni en la pizza 21ingredient = Ingredient() 22ingredient.name = "pepperoni" 23db.session.add(ingredient) 24db.session.commit() 25 26# Un último "checkpoint" antes de añadir el bacon 27checkpoint_b = db.session.begin_nested() 28 29# Insertamos el bacon 30ingredient = Ingredient() 31ingredient.name = "bacon" 32db.session.add(ingredient)

Ahora nuestra 'Pizza' tiene los siguientes ingredientes:

SQL tabla Pizza

Sin embargo, antes de meterla en el horno hemos decidido que no queremos bacon, así que usamos el rollback:

1checkpoint_b.rollback() 2# Vuelve atrás, hasta el checkpoint B, donde no se incluye el bacon

Finalmente, nuestra 'Pizza' se ve así:

SQL tabla Pizza despues de rollback

... Me ha dado hambre después de leer esta lección ¿¿tú no tienes hambre??