Última actualización: 15 de diciembre de 2023

2.7. SQLAlchemy

Muchas aplicaciones manipulan información que persiste en una base de datos. En Python existen múltiples conectores para acceder y trabajar con una base de datos, puedes usar directamente conectores que implementan la interfaz de comunicación con las bases de datos relacionales más conocidas, como PostgreSQL, MySQL, cx_Oracle, bases de datos NoSQL como MongoDB, etc. O en su lugar, puedes usar SQLAlchemy.

La librería SQLAlchemy es el kit de herramientas SQL de Python y el mapeador relacional de objetos.

SQLAlchemy es el kit de herramientas SQL de Python y el Mapeador relacional de objetos que ofrece a los desarrolladores de aplicaciones la máxima potencia y flexibilidad de SQL. Esta proporciona un conjunto completo de patrones de persistencia conocidos a nivel empresarial, diseñados para un acceso a bases de datos eficiente y de alto rendimiento, adaptados a un lenguaje de dominio simple y Pythonic.

2.7.1. Características

Las principales características de SQLAlchemy incluyen:

  • Un ORM de potencia industrial, construido desde el núcleo en el mapa de identidad, la unidad de trabajo y los patrones del mapeador de datos. Estos patrones permiten la persistencia transparente de objetos utilizando un sistema de configuración declarativo. Los modelos de dominio se pueden construir y manipular de forma natural, y los cambios se sincronizan con la transacción actual automáticamente.

  • Un sistema de consulta orientado a la relación, que expone explícitamente toda la gama de capacidades de SQL, incluidas combinaciones, subconsultas, correlaciones y casi todo lo demás, en términos del modelo de objetos. Las consultas de escritura con el ORM utilizan las mismas técnicas de composición relacional que utiliza al escribir SQL. Si bien puede caer en SQL literal en cualquier momento, virtualmente nunca es necesario.

  • Un sistema completo y flexible de carga impaciente para colecciones y objetos relacionados. Las colecciones se almacenan en caché dentro de una sesión y se pueden cargar en un acceso individual, todo de una vez mediante uniones, o por consulta por colección en todo el conjunto de resultados.

  • Un sistema de construcción Core SQL y una capa de interacción DBAPI. SQLAlchemy Core es independiente del ORM y es una capa de abstracción de base de datos completa por derecho propio, e incluye un lenguaje de expresión SQL basado en Python extensible, metadatos de esquema, agrupación de conexiones, coacción de tipos y tipos personalizados.

  • Se supone que todas las restricciones de clave primaria y externa son compuestas y naturales. Por supuesto, las claves primarias de enteros sustitutos siguen siendo la norma, pero SQLAlchemy nunca asume ni codifica los códigos de este modelo.

  • Base de datos de introspección y generación. Los esquemas de la base de datos se pueden «reflejar» en un solo paso en las estructuras de Python que representan los metadatos de la base de datos; esas mismas estructuras pueden generar declaraciones CREATE de inmediato, todas dentro del Core, independientemente del ORM.

2.7.2. ¿Cómo funciona?

SQLAlchemy proporciona una interfaz única para comunicarte con los diferentes drivers de bases de datos Python que implementan el estándar Python DBAPI.

Este estándar, especifica cómo las librerías Python que se integran con las bases de datos deben exponer sus interfaces. Por tanto, al usar SQLAlchemy no interactuarás directamente con dicho API, sino con la interfaz que precisamente proporciona SQLAlchemy. Esto es lo que permite cambiar el motor de base de datos de una aplicación sin modificar apenas el código que interactúa con los datos.

En definitiva, al usar SQLAlchemy es necesario instalar también un driver que implemente la interfaz DBAPI para la base de datos que vayas a utilizar.

Ejemplos de estos drivers son:

2.7.3. Instalación

Para instalar la librería SQLAlchemy debe ejecutar el siguiente comando, el cual a continuación se presentan el correspondiente comando de tu sistema operativo:

$ pip install SQLAlchemy==1.4.36

Puede probar si la instalación se realizo correctamente, ejecutando el siguiente comando correspondiente a tu sistema operativo:

$ python -c "import sqlalchemy ; print(sqlalchemy.__version__)"

Si muestra el numero de la versión instalada de SQLAlchemy, tiene correctamente instalada la librería. Con esto, ya tiene todo listo para continuar.

2.7.4. Crear el Engine

Lo primero que hay que hacer para trabajar con SQLAlchemy es crear un engine. El engine es el punto de entrada a la base de datos, es decir, el que permite a SQLAlchemy comunicarse con esta.

El motor se usa principalmente para manejar dos elementos: los pools de conexiones y el dialecto a utilizar.

Vamos a crear un engine. Para ello, añade un nuevo módulo Python llamado db.py al directorio productos con el siguiente contenido:

1
2
3
4
5
6
7
8
import os
from sqlalchemy import create_engine

DB_PATH = os.path.dirname(os.path.abspath(__file__)) + os.sep
DB_FILE = "productos.sqlite3"

# Configurar conexiones entre SQLAlchemy y SQLite3 DB API
engine = create_engine(f"sqlite:///{DB_PATH}{DB_FILE}")

Como puedes observar, a la función create_engine() se le pasa la cadena de conexión a la base de datos. En este caso, la cadena de conexión a la base de datos SQLite es "sqlite:///{DB_PATH}{DB_FILE}".

Crear el engine no hace que la aplicación se conecte a la base de datos inmediatamente, este hecho se pospone para cuando es necesario.

2.7.5. Pool de conexiones

SQLAlchemy utiliza el patrón Pool de objetos para manejar las conexiones a la base de datos.

Esto quiere decir que cuando se usa una conexión a la base de datos, esta ya está creada previamente y es reutilizada por el programa. La principal ventaja de este patrón es que mejora el rendimiento de la aplicación, dado que abrir y gestionar una conexión de base de datos es una operación costosa y que consume muchos recursos.

Al crear un engine con la función create_engine(), se genera un pool QueuePool que viene configurado como un pool de 5 conexiones como máximo. Esto se puede modificar en la configuración de SQLAlchemy.

2.7.6. Dialectos de base de datos

A pesar de que el lenguaje SQL es universal, cada motor de base de datos introduce ciertas variaciones propietarias sobre dicho lenguaje. A esto se le conoce como dialecto.

Una de las ventajas de usar SQLAlchemy es que, en principio, no te tienes que preocupar del dialecto a utilizar. El engine configura el dialecto por ti y se encarga de hacer las traducciones necesarias a código SQL. Esta es una de las razones por las que puedes cambiar el motor de base de datos realizando muy pocos cambios en tu código.

2.7.7. Sesiones

Una vez creado el engine, lo siguiente que debes hacer para trabajar con SQLAlchemy es crear una sesión. Una sesión viene a ser como una transacción, es decir, un conjunto de operaciones de base de datos que, bien se ejecutan todas de forma atómica, bien no se ejecuta ninguna (si ocurre un fallo en alguna de las operaciones).

Desde el punto de vista de SQLAlchemy, una sesión registra una lista de objetos creados, modificados o eliminados dentro de una misma transacción, de manera que, cuando se confirma la transacción, se reflejan en base de datos todas la operaciones involucradas (o ninguna si ocurre cualquier error).

Va a crear una sesión en el proyecto. Abre el archivo db.py y añade lo siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import os
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

DB_PATH = os.path.dirname(os.path.abspath(__file__)) + os.sep
DB_FILE = "productos.sqlite3"

engine = create_engine(f"sqlite:///{DB_PATH}{DB_FILE}")

Session = sessionmaker(bind=engine)
session = Session()

Para crear una sesión se utiliza el método factoría sessionmaker() asociado a un engine. Después de crear la factoría, objeto Session, hay que hacer llamadas a la misma para obtener las sesiones, objeto session.

2.7.8. Crear los modelos

En este punto, ya tiene casi todo listo para interactuar con el ORM. Ahora le voy a conocer donde realmente ocurre la magia: los modelos.

Los modelos son las clases que representan las tablas de base de datos. En el ejemplo tenemos la tabla productos, por tanto, dado que esta usando un ORM, tiene que crear el modelo (o clase) equivalente a la misma.

Para que se pueda realizar el mapeo de forma automática de una clase a una tabla, y viceversa, vamos a utilizar una clase base en los modelos que implementa toda esta lógica.

De nuevo, abre el archivo db.py y modificarlo para que su contenido sea como el que te muestro a continuación:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import os
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

DB_PATH = os.path.dirname(os.path.abspath(__file__)) + os.sep
DB_FILE = "productos.sqlite3"

engine = create_engine(f"sqlite:///{DB_PATH}{DB_FILE}")

Session = sessionmaker(bind=engine)
session = Session()

Base = declarative_base()

Al final del mismo hemos creado una clase llamada Base con el método declarative_base(). Esta clase será de la que hereden todos los modelos y tiene la capacidad de realizar el mapeo correspondiente a partir de la meta información (atributos de clase, nombre de la clase, etc.) que encuentre, precisamente, en cada uno de los modelos.

A continuación, le presento como debe quedar el archivo db.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import os
from dotenv import load_dotenv

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, exc
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import insert, select, update, delete

load_dotenv()

DB_PATH = os.path.dirname(os.path.abspath(__file__)) + os.sep
DB_FILE = os.getenv("DB")

# Configurar conexiones entre SQLAlchemy y SQLite3 DB API
engine = create_engine(f"sqlite:///{DB_PATH}{DB_FILE}")

# Crear sesión con el engine de base de datos
Session = sessionmaker(bind=engine)
session = Session()

Por tanto, lo siguiente que debe hacer es crear el modelo Productos. Crea un nuevo archivo en el directorio productos llamado models.py y añade el código que te muestro a continuación:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from db import Base

from sqlalchemy import Column, Integer, String, Float


class Productos(Base):
    """Clase de Productos

    Args:
        Base (Base): clase base declarativa

    Returns:
        class 'models.Productos': Clase de Productos
    """

    __tablename__ = "productos"

    id = Column(Integer, primary_key=True)
    nombre = Column(String, nullable=False)
    categoria = Column(String, nullable=False)
    precio = Column(Float)

    def __init__(self, nombre, categoria, precio):
        self.nombre = nombre
        self.categoria = categoria
        self.precio = precio

    def __repr__(self):
        return f"Productos({self.nombre}, {self.categoria}, {self.precio})"

    def __str__(self):
        return self.nombre

Asi de esta forma tiene definido una clase modelo llamado Productos la cual mapea la tabla productos.

2.7.8.1. Mapeo entre la clase y la tabla

La clase Productos del código anterior representa la tabla productos.

Para que se pueda realizar el mapeo automático clase-tabla, la clase hereda de la clase Base que creo en la sección anterior y que se encuentra en el módulo db.py. Además, hay que especificar el nombre de la tabla a través del atributo de clase __tablename__.

Por otro lado, cada una de las columnas de la tabla tienen su correspondiente representación en la clase a través de atributos de tipo Column. En este caso concreto, los atributos son los siguientes: id, nombre, categoria y precio.

Como puedes observar, SQLAlchemy define distintos tipos de datos para las columnas (Integer, String o Float, entre otros). En función del dialecto seleccionado, estos tipos se mapearán al tipo correcto de la base de datos utilizada.

Por último, y no menos importante, es necesario que al menos un atributo de la clase se especifique como primary_key. En el ejemplo es el atributo id. Este será el atributo que representa a la clave primaria de la tabla.

Nota

En la mayoría de motores de bases de datos, al especificar una columna de tipo Integer como primary_key, se generará una columna de tipo entero con valores que se incrementan de manera automática. Además, al crear un objeto no es necesario indicar el valor de esta columna ya que lo establecerá la base de datos cuando se confirmen los cambios.

2.7.9. Crear tablas

Una vez definidos los modelos, hay que crear las tablas correspondientes.

Crea un nuevo archivo Python en el directorio productos llamado main.py. En este archivo será donde escribas el código de ejemplo del programa.

Añade el siguiente código fuente al archivo main.py:

1
2
3
4
5
6
from db import *
from models import Productos

if __name__ == "__main__":
    Base.metadata.create_all(engine)
    print("¡Creación exitosa de la tabla productos!\n")

Lo importante en este punto es la línea Base.metadata.create_all(engine). En ella estamos indicando a SQLAlchemy que cree, si no existen, las tablas de todos los modelos que encuentre en la aplicación. Sin embargo, para que esto ocurra es necesario que cualquier modelo se haya importado previamente antes de llamar a la función create_all().

Importante

Si un modelo no ha sido importado en el código antes de llamar a la función create_all(), no se tendrá en cuenta para crear su tabla correspondiente.

Ejecuta ahora el programa con el siguiente comando:

$ python main.py

El anterior código al ejecutar debe mostrar el siguiente mensaje:

¡Creación exitosa de la tabla productos!

Se ha creado la tabla productos en la base de datos productos.sqlite3. Verás que aparece un archivo con dicho nombre en el directorio productos.

2.7.10. Insertar registros

Va a crear varias filas en la tabla productos. Como te he indicado anteriormente, una fila de una tabla se corresponde con un objeto Python. Por tanto, para crear una fila debemos instanciar un objeto de la clase Productos, añadirlo a la sesión y finalmente aplicar los cambios.

Añade un método ingresar_data() del archivo main.py con el siguiente código:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from db import *
from models import Productos


def ingresar_data():
    arroz = Productos(nombre="Arroz", categoria="Granos", precio=1.25)
    session.add(arroz)
    print(arroz.id)
    agua = Productos(nombre="Agua", categoria="Líquidos", precio=0.3)
    mantequilla = Productos("Mantequilla", "Lácteos", 3.56)
    queso = Productos("Queso", "Lácteos", 8.56)
    session.add_all([agua, mantequilla, queso])
    session.commit()
    print(arroz.id)
    print("¡Inserción exitosa de los 4 productos!\n")


if __name__ == "__main__":
    Base.metadata.create_all(engine)
    print("¡Creación exitosa de la tabla productos!\n")
    ingresar_data()

Te explico paso a paso el código y lo que ocurre. Inicialmente se crea el objeto arroz de tipo Productos. Seguidamente, se añade a la sesión con session.add(arroz). Después se muestra el valor del atributo id que es None, puesto que todavía no se han confirmado los cambios en la base de datos. A continuación, se crea y se añade a la sesión los objetos agua, mantequilla y queso usando session.add_all([agua, mantequilla, queso]). Por último, se hace un commit() de la sesión actual para confirmar los cambios en la base de datos y se muestra, de nuevo, el valor del atributo id del objeto arroz. En esta ocasión puedes observar que su valor es 1 y que coincide con el valor de la columna id de la primera fila de la tabla productos.

El anterior código al ejecutar debe mostrar el siguiente mensaje:

¡Creación exitosa de la tabla productos!

¡Inserción exitosa de los 4 productos!

2.7.11. Consultar registros

Las consultas devuelven modelos

Una vez que te he mostrado cómo guardar datos en la base de datos usando el ORM de SQLAlchemy, en esta última parte del tutorial vas a descubrir cómo hacer los principales tipos de consultas.

Las consultas a la base de datos se realizan fundamentalmente a través de la función query del objeto session. Esta función recibe como parámetro el nombre de la clase sobre la que realizar las consultas y devuelve un objeto Query con la consulta a realizar.

Siguiendo con el ejemplo, para realizar consultas sobre la clase Productos deberíamos ejecutar el siguiente código:

1
productos = session.query(Productos)

La variable productos es de tipo Query pero todavía no se ha ejecutado sobre la base de datos, para ello, debemos indicarle qué operación queremos realizar. Las más comunes son las siguientes:

2.7.11.1. Obtener un objeto a partir de su id

1
producto = session.query(Productos).get(1)

El método get() devuelve un objeto del tipo indicado en la Query a partir de su primary_key. Si no encuentra el objeto, devuelve None.

2.7.11.2. Obtener los objetos de una consulta

Para obtener todos los objetos de un tabla o consulta, simplemente hay que llamar al método all(). Este método devuelve una lista con los objetos devueltos por la consulta:

1
productos = session.query(Productos).all()

También puedes llamar al método first(). El método first() devuelve el primer objeto encontrado por la consulta. Es útil si sabes que solo existe un elemento que cumpla una determinada condición.

2.7.11.3. Contar el número de elementos devueltos por una consulta

Si quieres contar el número de elementos que devuelve una consulta, utiliza el método count():

1
contar_productos = session.query(Productos).count()

2.7.11.4. Aplicar filtros a una consulta

Para aplicar un filtro a una consulta, lo que sería la cláusula WHERE de SQL, puedes llamar a los métodos filter_by(keyword) o filter():

1
2
agua = session.query(Productos).filter_by(nombre="Agua").first()
menos_de_1 = session.query(Productos).filter(Productos.precio < 1).all()

2.7.12. Actualizar registros

Si requiere actualizar registro de tabla, a continuación tiene un ejemplo:

1
2
session.query(Productos).filter(Productos.id == 1).update({Productos.precio: 11.50})
session.commit()

El método update() le permite actualizar la fila del registro, tratando las columnas como un tipo diccionario.

2.7.13. Eliminar registros

Si requiere eliminar registro de tabla, a continuación tiene un ejemplo:

1
2
session.query(Productos).filter(Productos.id == 1).delete()
session.commit()

El método delete() le permite eliminar el registro en base a la clave primaria del campo id.

2.7.14. Práctica - Caso real

A continuación se presenta una práctica más real de implementar el uso de proyectos con SQLAlchemy, a continuación la estructura de proyecto llamado productos:

productos/
├── .env.example
├── db.py
├── __init__.py
├── main.py
├── models.py
├── productos.sqlite3
└── requirements.txt

A continuación se presenta y explica el uso de cada archivo para este proyecto:

Archivo .env.example

Archivo plantilla dotenv del paquete adicional python-dotenv.

1
2
### SQLite #############################
DB=productos.sqlite3

Archivo db.py

Modulo de configuraciones del programa.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import os
from dotenv import load_dotenv

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, exc
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import insert, select, update, delete

load_dotenv()

DB_PATH = os.path.dirname(os.path.abspath(__file__)) + os.sep
DB_FILE = os.getenv("DB")

# Configurar conexiones entre SQLAlchemy y SQLite3 DB API
engine = create_engine(f"sqlite:///{DB_PATH}{DB_FILE}")

# Crear sesión con el engine de base de datos
Session = sessionmaker(bind=engine)
session = Session()

Base = declarative_base()

Archivo main.py

Modulo de principal del programa.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from db import *
from models import Productos


def ingresar_data():
    # INSERT INTO productos (id, nombre, categoria, precio) VALUES (1,'Arroz','Granos','1.25');
    arroz = Productos(nombre="Arroz", categoria="Granos", precio=1.25)
    session.add(arroz)

    # INSERT INTO productos (id, nombre, categoria, precio) VALUES (2, "Agua", "Líquidos", 0.3);
    agua = Productos(nombre="Agua", categoria="Líquidos", precio=0.3)
    # INSERT INTO productos (id, nombre, categoria, precio) VALUES (3, "Mantequilla", "Lácteos", 3.56);
    mantequilla = Productos("Mantequilla", "Lácteos", 3.56)
    # INSERT INTO productos (id, nombre, categoria, precio) VALUES (4, "Queso", "Lácteos", 8.56);
    queso = Productos("Queso", "Lácteos", 8.56)
    session.add_all([agua, mantequilla, queso])

    session.commit()
    print("¡Inserción exitosa de los 4 productos!\n")


def consultar_data():
    print("¡Consulta todos los productos!")
    # SELECT * FROM productos;
    todos_productos = session.query(Productos).all()
    for cada_producto in todos_productos:
        print(cada_producto)

    print("\n¡Consulta todos los productos con más atributos!")
    # SELECT * FROM productos;
    consulta = select(Productos)
    for producto in session.scalars(consulta):
        print(f"{producto.nombre} {str(producto.precio)}")


def consultar_id_data(producto_id):
    print("\n¡Consulta de producto en base a su clave primaria!")
    # SELECT * FROM productos WHERE id == 1
    producto = session.query(Productos).get(producto_id)
    print(producto)


def consultar_categoria_precio():
    print("\n¡Consulta de productos lácteos!")
    # SELECT * FROM productos WHERE categoria == "Lácteos" AND precio >= 3.0
    lacteos = (
        session.query(Productos)
        .filter(Productos.categoria == "Lácteos")
        .filter(Productos.precio >= 3.0)
    )
    for lacteo in lacteos:
        print(lacteo)


def consultar_nombre_tupla():
    print("\n¡Otra consulta de productos lácteos!")
    # SELECT id, nombre, categoria FROM productos WHERE categoria == "Lácteos"
    lacteos = session.query(Productos).filter(Productos.categoria == "Lácteos")
    for lacteo in lacteos:
        print(f"{lacteo.id}, {lacteo.nombre}, {lacteo.categoria}")


def consultar_nombre_primero():
    print("\n¡Consulta del primer producto!")
    # SELECT * FROM productos WHERE categoria == "Lácteos" LIMIT 1
    producto = session.query(Productos).filter(Productos.categoria == "Lácteos").first()
    if producto:
        print(producto)
    else:
        print("¡No hay ningún Producto con ese criterio en la base de datos!")


def consultar_nombre_unico():
    print("\n¡Consulta del único producto!")
    try:
        # SELECT * FROM productos WHERE categoria == "Lácteos"
        producto = (
            session.query(Productos).filter(Productos.categoria == "Líquidos").one()
        )
        print(producto)
    except exc.NoResultFound as err:
        print("¡No hay ningún Producto con ese criterio en la base de datos!")
    finally:
        engine.dispose()
        session.close()


def consultar_nombres_data(nombres):
    print("\n¡Consulta los productos cuyos nombres coincidan con los suministrados!")
    # SELECT * FROM productos WHERE nombre IN ("Agua", "Arroz")
    consulta = select(Productos).where(Productos.nombre.in_(nombres))
    for producto in session.scalars(consulta):
        print(producto)


def actualizar_data(producto_id):
    print("\n¡Actualiza el producto suministrado!")
    # SELECT * FROM productos WHERE id == 1 LIMIT 1
    # UPDATE productos SET precio = 11.50 WHERE id = 1;
    producto = session.query(Productos).filter(Productos.id == producto_id).first()
    print("Precio anterior:", producto, producto.precio)
    producto.precio = 11.50
    print("Precio nuevo:", producto, producto.precio)

    session.add(producto)
    session.commit()
    print("¡Actualización exitosa de precio del producto!\n")


def actualizar_otra_data(producto_id, precio_nuevo):
    print("¡Actualiza el producto suministrado!")
    # UPDATE productos SET precio = 3.33 WHERE id = 2;
    session.query(Productos).filter(Productos.id == producto_id).update(
        {Productos.precio: precio_nuevo}
    )
    session.commit()
    print("¡Actualización exitosa de precio del producto!\n")


def eliminar_data(producto_id):
    print("¡Elimina los productos suministrados!")
    # DELETE FROM productos WHERE id = 1;
    session.query(Productos).filter(Productos.id == producto_id).delete()
    session.commit()
    print("¡Eliminación exitosa del producto!\n")


if __name__ == "__main__":
    Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)
    print("¡Creación exitosa de la tabla productos!\n")
    ingresar_data()
    consultar_data()
    consultar_id_data(1)
    consultar_categoria_precio()
    consultar_nombre_tupla()
    consultar_nombre_primero()
    consultar_nombre_unico()
    consultar_nombres_data(["Agua", "Arroz"])
    actualizar_data(1)
    actualizar_otra_data(2, 3.33)
    eliminar_data(1)

Archivo models.py

Modulo de modelos de SQLAlchemy.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from db import Base

from sqlalchemy import Column, Integer, String, Float


class Productos(Base):
    """Clase de Productos

    Args:
        Base (Base): clase base declarativa

    Returns:
        class 'models.Productos': Clase de Productos
    """

    __tablename__ = "productos"

    id = Column(Integer, primary_key=True)
    nombre = Column(String, nullable=False)
    categoria = Column(String, nullable=False)
    precio = Column(Float)

    def __init__(self, nombre, categoria, precio):
        self.nombre = nombre
        self.categoria = categoria
        self.precio = precio

    def __repr__(self):
        return f"Productos({self.nombre}, {self.categoria}, {self.precio})"

    def __str__(self):
        return self.nombre

Archivo productos.sqlite3

Archivo de base de datos de SQLite llamado productos.sqlite3 la cual no se incluye ya que cada vez que se inicia el programa main.py se elimina y crea nuevamente, para cuidar la creación de los datos iniciales.

Archivo requirements.txt

Archivo de requirements.txt de la herramienta de gestión de paquetes pip.

1
2
3
# Install the packages from PyPi repository.
SQLAlchemy>=1.4.36
python-dotenv==0.21.0

Teniendo creada la anterior estructura de proyecto, vuelva a ejecutar ahora el modulo con el siguiente comando, el cual a continuación se presentan el correspondiente comando de tu sistema operativo:

Antes de ejecutar debes instalar sus dependencias, con el siguiente comando:

$ pip install -r requirements.txt

Ademas debe instalar y editar el archivo .env, con el siguiente comando:

$ cp .env.example .env
$ nano .env

Truco

El archivo .env se definen las configuraciones de conexión a la base de datos, puede modificarlo cambiar valores de la conexión.

Nota

Para conexiones a base de datos MySQL y PostgreSQL debe definir las variables que por defecto no están definidas.

Truco

Para ejecutar el código fuente de esta practica debe invocar al modulo main.py, abra una consola de comando, acceda al directorio donde se encuentra la estructura previa y ejecute el siguiente comando:

$ python main.py

El anterior código al ejecutar debe mostrar el siguiente mensaje:

¡Creación exitosa de la tabla productos!

¡Inserción exitosa de los 4 productos!

¡Consulta todos los productos!
Arroz
Agua
Mantequilla
Queso

¡Consulta todos los productos con más atributos!
Arroz 1.25
Agua 0.3
Mantequilla 3.56
Queso 8.56

¡Consulta de producto en base a su clave primaria!
Arroz

¡Consulta de productos lácteos!
Mantequilla
Queso

¡Otra consulta de productos lácteos!
3, Mantequilla, Lácteos
4, Queso, Lácteos

¡Consulta del primer producto!
Mantequilla

¡Consulta del único producto!
Agua

¡Consulta los productos cuyos nombres coincidan con los suministrados!
Arroz
Agua

¡Actualiza el producto suministrado!
Precio anterior: Arroz 1.25
Precio nuevo: Arroz 11.5
¡Actualización exitosa de precio del producto!

¡Actualiza el producto suministrado!
¡Actualización exitosa de precio del producto!

¡Elimina los productos suministrados!
¡Eliminación exitosa del producto!

Asi de esta forma puede ingresar, consultar, actualizar y eliminar registro en una tabla usando SQLAlchemy.


Ver también

Consulte la sección de lecturas suplementarias del entrenamiento para ampliar su conocimiento en esta temática.


¿Cómo puedo ayudar?

¡Mi soporte está aquí para ayudar!

Mi horario de oficina es de lunes a sábado, de 9 AM a 5 PM. GMT-4 - Caracas, Venezuela.

La hora aquí es actualmente 7:35 PM GMT-4.

Mi objetivo es responder a todos los mensajes dentro de un día hábil.

Contrata mi increíble soporte profesional