Persistencia de datos de Python - SQLAlchemy

Cualquier base de datos relacional contiene datos en tablas. La estructura de la tabla define el tipo de datos de los atributos que son básicamente tipos de datos primarios únicamente que se asignan a los correspondientes tipos de datos integrados de Python. Sin embargo, los objetos definidos por el usuario de Python no se pueden almacenar ni recuperar de forma persistente en tablas SQL.

Esta es una disparidad entre los tipos de SQL y los lenguajes de programación orientados a objetos como Python. SQL no tiene un tipo de datos equivalente para otros como dict, tuple, list o cualquier clase definida por el usuario.

Si tiene que almacenar un objeto en una base de datos relacional, sus atributos de instancia deben deconstruirse primero en tipos de datos SQL, antes de ejecutar la consulta INSERT. Por otro lado, los datos recuperados de una tabla SQL están en tipos primarios. Un objeto de Python del tipo deseado deberá construirse utilizando para su uso en el script de Python. Aquí es donde los mapeadores relacionales de objetos son útiles.

Mapeador de relaciones de objetos (ORM)

Un Object Relation Mapper(ORM) es una interfaz entre una clase y una tabla SQL. Una clase de Python se asigna a una determinada tabla en la base de datos, por lo que la conversión entre objetos y tipos de SQL se realiza automáticamente.

La clase de Estudiantes escrita en código Python se asigna a la tabla de Estudiantes en la base de datos. Como resultado, todas las operaciones CRUD se realizan llamando a los métodos respectivos de la clase. Esto elimina la necesidad de ejecutar consultas SQL codificadas en el script Python.

La biblioteca ORM actúa así como una capa de abstracción sobre las consultas SQL sin procesar y puede ser de ayuda en el desarrollo rápido de aplicaciones. SQLAlchemyes un mapeador relacional de objetos popular para Python. Cualquier manipulación del estado del objeto modelo se sincroniza con su fila relacionada en la tabla de la base de datos.

La biblioteca SQLALchemy incluye ORM API y lenguaje de expresión SQL (SQLAlchemy Core). El lenguaje de expresión ejecuta construcciones primitivas de la base de datos relacional directamente.

ORM es un patrón de uso abstracto y de alto nivel construido sobre el lenguaje de expresión SQL. Se puede decir que ORM es un uso aplicado del lenguaje de expresión. Discutiremos la API ORM de SQLAlchemy y usaremos la base de datos SQLite en este tema.

SQLAlchemy se comunica con varios tipos de bases de datos a través de sus respectivas implementaciones DBAPI utilizando un sistema de dialecto. Todos los dialectos requieren que esté instalado un controlador DBAPI apropiado. Se incluyen dialectos para los siguientes tipos de bases de datos:

  • Firebird
  • Microsoft SQL Server
  • MySQL
  • Oracle
  • PostgreSQL
  • SQLite
  • Sybase

La instalación de SQLAlchemy es fácil y sencilla, utilizando la utilidad pip.

pip install sqlalchemy

Para verificar si SQLalchemy está instalado correctamente y su versión, ingrese lo siguiente en el indicador de Python:

>>> import sqlalchemy
>>>sqlalchemy.__version__
'1.3.11'

Las interacciones con la base de datos se realizan a través del objeto Engine obtenido como un valor de retorno de create_engine() función.

engine =create_engine('sqlite:///mydb.sqlite')

SQLite permite la creación de una base de datos en memoria. El motor SQLAlchemy para la base de datos en memoria se crea de la siguiente manera:

from sqlalchemy import create_engine
engine=create_engine('sqlite:///:memory:')

Si tiene la intención de utilizar la base de datos MySQL en su lugar, utilice su módulo DB-API - pymysql y el controlador de dialecto respectivo.

engine = create_engine('mysql+pymydsql://[email protected]/mydb')

Create_engine tiene un argumento de eco opcional. Si se establece en verdadero, las consultas SQL generadas por el motor se repetirán en la terminal.

SQLAlchemy contiene declarative baseclase. Actúa como un catálogo de clases modelo y tablas mapeadas.

from sqlalchemy.ext.declarative import declarative_base
base=declarative_base()

El siguiente paso es definir una clase de modelo. Debe derivarse de base - object de la clase declarative_base como arriba.

Establecer __tablename__ propiedad al nombre de la tabla que desea crear en la base de datos. Otros atributos corresponden a los campos. Cada uno es un objeto Column en SQLAlchemy y su tipo de datos es de uno de la lista a continuación:

  • BigInteger
  • Boolean
  • Date
  • DateTime
  • Float
  • Integer
  • Numeric
  • SmallInteger
  • String
  • Text
  • Time

El siguiente código es la clase modelo denominada Estudiante que se asigna a la tabla Estudiantes.

#myclasses.py
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Numeric
base=declarative_base()
class Student(base):
   __tablename__='Students'
   StudentID=Column(Integer, primary_key=True)
   name=Column(String)
   age=Column(Integer)
   marks=Column(Numeric)

Para crear una tabla de Estudiantes que tenga la estructura correspondiente, ejecute el método create_all () definido para la clase base.

base.metadata.create_all(engine)

Ahora tenemos que declarar un objeto de nuestra clase Student. Todas las transacciones de la base de datos, como agregar, eliminar o recuperar datos de la base de datos, etc., son manejadas por un objeto Session.

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()

Los datos almacenados en el objeto Student se agregan físicamente en la tabla subyacente mediante el método add () de la sesión.

s1 = Student(name='Juhi', age=25, marks=200)
sessionobj.add(s1)
sessionobj.commit()

Aquí está el código completo para agregar registros en la tabla de estudiantes. A medida que se ejecuta, el registro de la instrucción SQL correspondiente se muestra en la consola.

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from myclasses import Student, base
engine = create_engine('sqlite:///college.db', echo=True)
base.metadata.create_all(engine)

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()
s1 = Student(name='Juhi', age=25, marks=200)
sessionobj.add(s1)
sessionobj.commit()

Salida de consola

CREATE TABLE "Students" (
   "StudentID" INTEGER NOT NULL,
   name VARCHAR,
   age INTEGER,
   marks NUMERIC,
   PRIMARY KEY ("StudentID")
)
INFO sqlalchemy.engine.base.Engine ()
INFO sqlalchemy.engine.base.Engine COMMIT
INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
INFO sqlalchemy.engine.base.Engine INSERT INTO "Students" (name, age, marks) VALUES (?, ?, ?)
INFO sqlalchemy.engine.base.Engine ('Juhi', 25, 200.0)
INFO sqlalchemy.engine.base.Engine COMMIT

los session object también proporciona el método add_all () para insertar más de un objeto en una sola transacción.

sessionobj.add_all([s2,s3,s4,s5])
sessionobj.commit()

Ahora que los registros se agregan a la tabla, nos gustaría obtenerlos de ella tal como lo hace la consulta SELECT. El objeto de sesión tiene el método query () para realizar la tarea. El objeto de consulta es devuelto por el método query () en nuestro modelo Student.

qry=seesionobj.query(Student)

Utilice el método get () de este objeto de consulta para obtener el objeto correspondiente a la clave primaria dada.

S1=qry.get(1)

Mientras se ejecuta esta declaración, su correspondiente declaración SQL repetida en la consola será la siguiente:

BEGIN (implicit)
SELECT "Students"."StudentID" AS "Students_StudentID", "Students".name AS 
   "Students_name", "Students".age AS "Students_age", 
   "Students".marks AS "Students_marks"
FROM "Students"
WHERE "Products"."Students" = ?
sqlalchemy.engine.base.Engine (1,)

El método query.all () devuelve una lista de todos los objetos que se pueden atravesar mediante un bucle.

from sqlalchemy import Column, Integer, String, Numeric
from sqlalchemy import create_engine
from myclasses import Student,base
engine = create_engine('sqlite:///college.db', echo=True)
base.metadata.create_all(engine)
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()
qry=sessionobj.query(Students)
rows=qry.all()
for row in rows:
   print (row)

Actualizar un registro en la tabla asignada es muy fácil. Todo lo que tiene que hacer es buscar un registro usando el método get (), asignar un nuevo valor al atributo deseado y luego confirmar los cambios usando el objeto de sesión. A continuación, cambiamos las calificaciones del estudiante Juhi a 100.

S1=qry.get(1)
S1.marks=100
sessionobj.commit()

Eliminar un registro es tan fácil como eliminar el objeto deseado de la sesión.

S1=qry.get(1)
Sessionobj.delete(S1)
sessionobj.commit()