Muchas aplicaciones manipulan información que está almacenada en una base de datos. En Python existen múltiples opciones 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 más conocidas, como PostgreSQL, MySQL, Oracle, Mongo, etc. O bien, puedes usar SQLAlchemy.
Tal y como indican en la propia web del proyecto, SQLAlchemy es un kit de herramientas SQL para Python y un ORM (Object Relational Mapper) que brinda a los desarrolladores de aplicaciones toda la potencia y flexibilidad de SQL.
En este tutorial de Introducción a SQLAlchemy, me voy a centrar en una de sus características más importantes (y quizá desconocida para muchos desarrolladores): su ORM.
Índice
Qué es un ORM
Un ORM (de sus siglas en inglés, Object Relational Mapper), no es más que una utilidad o librería que permite manipular las tablas de una base de datos como si fueran objetos de nuestro programa.
Lo más habitual es que una tabla se corresponda con una clase, cada fila de una tabla con un objeto (o instancia de una clase), las columnas de una tabla con los atributos de una clase y las claves ajenas (o Foreign Keys) con relaciones entre clases (definidas también a partir de atributos).
La siguiente imagen muestra la correspondencia entre los elementos de una base de datos y las clases y objetos de un programa:

Ventajas de usar un ORM
Las principales ventajas de usar un ORM son:
- Acceder a las tablas y filas de una base de datos como clases y objetos.
- En la mayoría de ocasiones no es necesario usar el lenguaje SQL. El ORM se encarga de hacer las traducciones oportunas.
- Independencia de la base de datos. Es posible cambiar de motor de base de datos modificando muy poco código en la aplicación.
- Incrementa la productividad del desarrollador.
Qué es SQLALchemy
Como te comentaba en la introducción, SQLAlchemy es una librería para Python que facilita el acceso a una base de datos relacional, así como las operaciones a realizar sobre la misma.
Es independiente del motor de base de datos a utilizar, es decir, en principio, es compatible con la mayoría de bases de datos relacionales conocidas: PostgreSQL, MySQL, Oracle, Microsoft SQL Server, Sqlite, …
Aunque se puede usar SQLAlchemy utilizando consultas en lenguaje SQL nativo, la principal ventaja de trabajar con esta librería se consigue haciendo uso de su ORM. El ORM de SQLAlchemy mapea tablas a clases Python y convierte automáticamente llamadas a funciones dentro de estas clases a sentencias SQL.
Además, SQLAlchemy implementa múltiples patrones de diseño que te permiten desarrollar aplicaciones rápidamente y te abstrae de ciertas tareas, como manejar el pool de conexiones a la base de datos.
¿Cómo funciona SQLALchemy?
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 PostgreSQL
- mysql-connector para MySQL
- cx_Oracle para Oracle
Tutorial de SQLAlchemy
A partir de aquí voy hacer un tutorial de introducción a SQLAlchemy para que veas y entiendas cómo funciona. Utilizaremos una base de datos Sqlite ya que no hace falta instalar ninguna dependencia extra.
Tomaremos como referencia la siguiente tabla de base de datos:

La primera tarea del tutorial será crear el directorio para guardar el proyecto. Llámalo productos
.
Accede al directorio y crea un entorno virtual con virtualenv
ejecutando el siguiente comando:
$> virtualenv env
A continuación, activa el entorno virtual e instala SQLAlchemy:
$> pip install sqlalchemy
Con esto, ya tenemos todo listo para continuar.
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:
from sqlalchemy import create_engine engine = create_engine('sqlite:///productos.sqlite')
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:///productos.sqlite'
.
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.
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.
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.
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).
Vamos a crear una sesión en nuestro proyecto. Abre el fichero db.py
y añade lo siguiente:
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine('sqlite:///keywords.sqlite') 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
.
Crear los modelos para trabajar con tablas
Llegados a este punto, ya lo tenemos casi todo listo para interactuar con el ORM. Ahora te voy a enseñar 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 producto
, por tanto, dado que estamos usando un ORM, tenemos 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 fichero db.py
y modifícalo para que su contenido sea como el que te muestro a continuación:
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker engine = create_engine('sqlite:///productos.sqlite') 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 metainformación (atributos de clase, nombre de la clase, etc.) que encuentre, precisamente, en cada uno de los modelos.
Por tanto, lo siguiente que debes hacer es crear el modelo Producto
. Crea un nuevo fichero en el directorio productos
llamado models.py
y añade el código que te muestro a continuación:
import db from sqlalchemy import Column, Integer, String, Float class Producto(db.Base): __tablename__ = 'producto' id = Column(Integer, primary_key=True) nombre = Column(String, nullable=False) precio = Column(Float) def __init__(self, nombre, precio): self.nombre = nombre self.precio = precio def __repr__(self): return f'Producto({self.nombre}, {self.precio})' def __str__(self): return self.nombre
Mapeo clase-tabla
La clase Producto
del código anterior representa la tabla producto
que vimos al comienzo del tutorial.
Para que se pueda realizar el mapeo automático clase-tabla, la clase hereda de la clase Base
que creamos 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
y precio
.
Como puedes observar, SQLAlchemy define distintos tipos de datos para las columnas (Integer
, String
o Numeric
, 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.
Recrear las tablas en la base de datos
Una vez definidos los modelos, hay que crear las tablas correspondientes.
Crea un nuevo fichero Python en el directorio productos
llamado main.py
. En este fichero será donde escribas el código de ejemplo del programa.
Añade lo siguiente al fichero main.py
:
import db from models import Producto def run(): pass if __name__ == '__main__': db.Base.metadata.create_all(db.engine) run()
Lo importante en este punto es la línea db.Base.metadata.create_all(db.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
Parece que no ocurre nada pero realmente se ha creado la tabla producto
en la base de datos productos.sqlite
. Verás que aparece un fichero con dicho nombre en el directorio productos
.

Guardar un modelo añade un registro a la base de datos
Ahora sí que vamos a jugar un poco con la base de datos. ¿Tienes ganas? Yo sí 😜
Vamos a crear varias filas en la tabla producto
. 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 Producto
, añadirlo a la sesión y finalmente aplicar los cambios.
Actualiza el método run()
del fichero main.py
con el siguiente código:
def run(): arroz = Producto('Arroz', 1.25) db.session.add(arroz) print(arroz.id) agua = Producto('Agua', 0.3) db.session.add(agua) db.session.commit() print(arroz.id)
Te explico paso a paso el código y lo que ocurre. Inicialmente se crea el objeto arroz
de tipo Producto
. Seguidamente, se añade a la sesión con db.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 el objeto agua
. 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 producto
.
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 Producto
deberíamos ejecutar el siguiente código:
consulta = db.session.query(Producto)
La variable consulta
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:
Obtener un objeto a partir de su id
ob = db.session.query(Producto).get(1)
get()
devuelve un objeto del tipo indicado en la Query
a partir de su primary_key
. Si no encuentra el objeto, devuelve None
.
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:
productos = db.session.query(Producto).all()
También puedes llamar al método first()
. first()
devuelve el primer objeto encontrado por la consulta. Es útil si sabes que solo existe un elemento que cumpla una determinada condición.
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()
:
num_productos = db.session.query(Producto).count()
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()
:
agua = db.session.query(Producto).filter_by(nombre='Agua').first() menos_de_1 = db.session.query(Producto).filter(Producto.precio < 1).all()
Conclusiones
Este tutorial es solo una introducción al ORM SQLAlchemy. Todavía quedan muchos temas por tratar que iré publicando poco a poco, como: cómo hacer un JOIN de dos tablas, herencia de clases, ordenar las consultas, índices, etc.
Para finalizar, simplemente quiero añadir una pequeña reflexión. Hay dos corrientes de pensamiento entre los programadores: los que están a favor y los que están en contra de usar un ORM.
Yo, personalmente, estoy a favor porque en mi día a día me facilita mucho el trabajo, lo que mejora mi productividad. Sin embargo, soy consciente de las posibles limitaciones y/o problemas que te puedes encontrar a la hora de usar una solución de este tipo. Por ejemplo, no saber cómo hacer una determinada consulta o filtro. En estos casos no te compliques, cualquier ORM te permite ejecutar consultas nativas. Si lo requieres, haz uso de ellas.