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:
psycopg para conexiones a PostgreSQL.
PyMySQL para conexiones a MySQL.
cx_Oracle para conexiones a Oracle.
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
> 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__)"
> 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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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
> 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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
2.7.12. Actualizar registros¶
Si requiere actualizar registro de tabla, a continuación tiene un ejemplo:
1 2 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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
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:
> copy .env.example .env
> notepad.exe .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.