Persistenza dei dati Python - SQLAlchemy

Qualsiasi database relazionale conserva i dati nelle tabelle. La struttura della tabella definisce il tipo di dati degli attributi che sono fondamentalmente solo dei tipi di dati primari che sono mappati ai corrispondenti tipi di dati incorporati di Python. Tuttavia, gli oggetti definiti dall'utente di Python non possono essere archiviati e recuperati in modo persistente da / a tabelle SQL.

Questa è una disparità tra i tipi SQL e linguaggi di programmazione orientati agli oggetti come Python. SQL non ha un tipo di dati equivalente per altri come dict, tuple, list o qualsiasi classe definita dall'utente.

Se devi memorizzare un oggetto in un database relazionale, i suoi attributi di istanza dovrebbero essere prima decostruiti in tipi di dati SQL, prima di eseguire la query INSERT. D'altra parte, i dati recuperati da una tabella SQL sono in tipi primari. Un oggetto Python del tipo desiderato dovrà essere costruito utilizzando per l'uso nello script Python. È qui che sono utili i mapping relazionali degli oggetti.

Object Relation Mapper (ORM)

Un Object Relation Mapper(ORM) è un'interfaccia tra una classe e una tabella SQL. Una classe Python viene mappata a una determinata tabella nel database, in modo che la conversione tra i tipi di oggetto e SQL venga eseguita automaticamente.

La classe Studenti scritta in codice Python è mappata alla tabella Studenti nel database. Di conseguenza, tutte le operazioni CRUD vengono eseguite chiamando i rispettivi metodi della classe. Ciò elimina la necessità di eseguire query SQL hardcoded nello script Python.

La libreria ORM funge quindi da livello di astrazione sulle query SQL non elaborate e può essere di aiuto nello sviluppo rapido dell'applicazione. SQLAlchemyè un popolare mappatore relazionale di oggetti per Python. Qualsiasi manipolazione dello stato dell'oggetto modello viene sincronizzata con la relativa riga nella tabella del database.

La libreria SQLALchemy include ORM API e linguaggio di espressione SQL (SQLAlchemy Core). Il linguaggio di espressione esegue direttamente i costrutti primitivi del database relazionale.

ORM è un modello di utilizzo astratto e di alto livello costruito sulla base del linguaggio di espressione SQL. Si può dire che ORM è un uso applicato del linguaggio delle espressioni. Discuteremo l'API ORM di SQLAlchemy e utilizzeremo il database SQLite in questo argomento.

SQLAlchemy comunica con vari tipi di database tramite le rispettive implementazioni DBAPI utilizzando un sistema dialettale. Tutti i dialetti richiedono che sia installato un driver DBAPI appropriato. Sono inclusi i dialetti per i seguenti tipi di database:

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

L'installazione di SQLAlchemy è facile e diretta, utilizzando l'utilità pip.

pip install sqlalchemy

Per verificare se SQLalchemy è installato correttamente e la sua versione, inserisci quanto segue al prompt di Python:

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

Le interazioni con il database vengono eseguite tramite l'oggetto Engine ottenuto come valore restituito di create_engine() funzione.

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

SQLite consente la creazione di database in memoria. Il motore SQLAlchemy per il database in memoria viene creato come segue:

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

Se invece intendi utilizzare il database MySQL, usa il suo modulo DB-API - pymysql e il rispettivo driver dialetto.

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

Il create_engine ha un argomento echo opzionale. Se impostato su true, le query SQL generate dal motore verranno visualizzate sul terminale.

SQLAlchemy contiene declarative baseclasse. Funziona come un catalogo di classi di modelli e tabelle mappate.

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

Il prossimo passo è definire una classe modello. Deve essere derivato dall'oggetto base della classe dichiarative_base come sopra.

Impostato __tablename__ proprietà al nome della tabella che si desidera creare nel database. Altri attributi corrispondono ai campi. Ognuno è un oggetto Colonna in SQLAlchemy e il suo tipo di dati proviene da uno degli elenchi seguenti:

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

Il codice seguente è la classe modello denominata Student che è mappata alla tabella Studenti.

#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)

Per creare una tabella Studenti con una struttura corrispondente, eseguire il metodo create_all () definito per la classe base.

base.metadata.create_all(engine)

Ora dobbiamo dichiarare un oggetto della nostra classe Student. Tutte le transazioni del database come l'aggiunta, l'eliminazione o il recupero dei dati dal database, ecc., Vengono gestite da un oggetto Session.

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

I dati memorizzati nell'oggetto Student vengono aggiunti fisicamente nella tabella sottostante dal metodo add () della sessione.

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

Ecco l'intero codice per l'aggiunta di record nella tabella degli studenti. Durante l'esecuzione, il registro delle istruzioni SQL corrispondente viene visualizzato sulla console.

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()

Uscita console

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

Il session object fornisce anche il metodo add_all () per inserire più di un oggetto in una singola transazione.

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

Ora che i record vengono aggiunti nella tabella, vorremmo recuperarli proprio come fa la query SELECT. L'oggetto sessione dispone del metodo query () per eseguire l'attività. L'oggetto query viene restituito dal metodo query () sul nostro modello Student.

qry=seesionobj.query(Student)

Utilizzare il metodo get () di questo oggetto Query recupera l'oggetto corrispondente alla chiave primaria specificata.

S1=qry.get(1)

Mentre questa istruzione viene eseguita, la sua istruzione SQL corrispondente echeggiata sulla console sarà la seguente:

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,)

Il metodo query.all () restituisce un elenco di tutti gli oggetti che possono essere attraversati utilizzando un ciclo.

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)

L'aggiornamento di un record nella tabella mappata è molto semplice. Tutto quello che devi fare è recuperare un record utilizzando il metodo get (), assegnare un nuovo valore all'attributo desiderato e quindi eseguire il commit delle modifiche utilizzando l'oggetto sessione. Di seguito cambiamo i voti di Juhi student a 100.

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

Eliminare un record è altrettanto facile, eliminando l'oggetto desiderato dalla sessione.

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