Trwałość danych w języku Python - SQLAlchemy

Każda relacyjna baza danych przechowuje dane w tabelach. Struktura tabeli definiuje typ danych atrybutów, które są w zasadzie tylko głównymi typami danych, które są odwzorowywane na odpowiednie wbudowane typy danych Pythona. Jednak obiekty zdefiniowane przez użytkownika w Pythonie nie mogą być trwale przechowywane i pobierane do / z tabel SQL.

Jest to rozbieżność między typami SQL a językami programowania zorientowanymi obiektowo, takimi jak Python. SQL nie ma równoważnego typu danych dla innych, takich jak dict, tuple, list lub inna klasa zdefiniowana przez użytkownika.

Jeśli musisz przechowywać obiekt w relacyjnej bazie danych, przed wykonaniem zapytania INSERT należy najpierw zdekonstruować jego atrybuty instancji na typy danych SQL. Z drugiej strony dane pobrane z tabeli SQL są w typach podstawowych. Obiekt Pythona żądanego typu będzie musiał zostać skonstruowany przy użyciu do użycia w skrypcie Python. W tym miejscu przydatne są mapery relacyjne obiektów.

Mapowanie relacji obiektów (ORM)

Na Object Relation Mapper(ORM) to interfejs między klasą a tabelą SQL. Klasa Pythona jest mapowana na określoną tabelę w bazie danych, dzięki czemu konwersja między typami obiektowymi i SQL jest wykonywana automatycznie.

Klasa Students napisana w kodzie Pythona jest odwzorowywana na tabelę Students w bazie danych. W rezultacie wszystkie operacje CRUD są wykonywane przez wywołanie odpowiednich metod klasy. Eliminuje to konieczność wykonywania zakodowanych na stałe zapytań SQL w skrypcie Python.

Biblioteka ORM działa zatem jako warstwa abstrakcji nad surowymi zapytaniami SQL i może być pomocna w szybkim tworzeniu aplikacji. SQLAlchemyjest popularnym mapowaniem relacyjnym obiektów dla Pythona. Wszelkie manipulacje stanem obiektu modelu są synchronizowane z odpowiednim wierszem w tabeli bazy danych.

Biblioteka SQLALchemy zawiera ORM API i język wyrażeń SQL (SQLAlchemy Core). Język wyrażeń bezpośrednio wykonuje prymitywne konstrukcje relacyjnej bazy danych.

ORM to abstrakcyjny wzorzec użycia wysokiego poziomu, zbudowany na bazie języka wyrażeń SQL. Można powiedzieć, że ORM jest stosowanym zastosowaniem języka wyrażeń. W tym temacie omówimy SQLAlchemy ORM API i wykorzystamy bazę danych SQLite.

SQLAlchemy komunikuje się z różnymi typami baz danych za pośrednictwem odpowiednich implementacji DBAPI przy użyciu systemu dialektów. Wszystkie dialekty wymagają zainstalowania odpowiedniego sterownika DBAPI. Uwzględniono dialekty dla następujących typów baz danych -

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

Instalacja SQLAlchemy jest łatwa i prosta przy użyciu narzędzia pip.

pip install sqlalchemy

Aby sprawdzić, czy SQLalchemy jest poprawnie zainstalowany i jego wersję, wprowadź następujące polecenie w zachęcie Pythona -

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

Interakcje z bazą danych odbywają się za pośrednictwem obiektu Engine otrzymanego jako wartość zwracana create_engine() funkcjonować.

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

SQLite umożliwia tworzenie bazy danych w pamięci. Silnik SQLAlchemy dla bazy danych w pamięci jest tworzony w następujący sposób -

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

Jeśli zamiast tego zamierzasz używać bazy danych MySQL, użyj jej modułu DB-API - pymysql i odpowiedniego sterownika dialektu.

engine = create_engine('mysql+pymydsql://root@localhost/mydb')

Create_engine ma opcjonalny argument echo. Jeśli ma wartość true, zapytania SQL generowane przez silnik będą wyświetlane na terminalu.

SQLAlchemy zawiera declarative baseklasa. Działa jako katalog klas modeli i mapowanych tabel.

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

Następnym krokiem jest zdefiniowanie klasy modelu. Musi być wyprowadzony z obiektu bazowego klasy declarative_base jak wyżej.

Ustaw __tablename__ na nazwę tabeli, którą chcesz utworzyć w bazie danych. Inne atrybuty odpowiadają polom. Każdy z nich jest obiektem Column w SQLAlchemy, a jego typ danych pochodzi z jednej z poniższych list -

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

Poniższy kod to klasa modelu o nazwie Student, która jest zamapowana na tabelę Students.

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

Aby utworzyć tabelę Students, która ma odpowiednią strukturę, wykonaj metodę create_all () zdefiniowaną dla klasy bazowej.

base.metadata.create_all(engine)

Teraz musimy zadeklarować obiekt naszej klasy Student. Wszystkie transakcje bazy danych, takie jak dodawanie, usuwanie lub pobieranie danych z bazy danych itp., Są obsługiwane przez obiekt Session.

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

Dane przechowywane w obiekcie Studenta są fizycznie dodawane do tabeli bazowej za pomocą metody add () sesji.

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

Tutaj jest cały kod dodawania rekordu w tabeli uczniów. W trakcie wykonywania odpowiedni dziennik instrukcji SQL jest wyświetlany na konsoli.

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

Wyjście konsoli

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

Plik session obiekt udostępnia również metodę add_all () do wstawiania więcej niż jednego obiektu w jednej transakcji.

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

Teraz, gdy rekordy zostały dodane do tabeli, chcielibyśmy je z niej pobrać, tak jak robi to zapytanie SELECT. Obiekt sesji ma metodę query () do wykonania zadania. Obiekt zapytania jest zwracany przez metodę query () w naszym modelu Studenta.

qry=seesionobj.query(Student)

Użyj metody get () tego obiektu Query, aby pobrać obiekt odpowiadający podanemu kluczowi głównemu.

S1=qry.get(1)

Podczas wykonywania tej instrukcji odpowiadająca jej instrukcja SQL wyświetlana na konsoli będzie wyglądać następująco:

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

Metoda query.all () zwraca listę wszystkich obiektów, po których można przejść za pomocą pętli.

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)

Aktualizacja rekordu w zmapowanej tabeli jest bardzo łatwa. Wystarczy pobrać rekord za pomocą metody get (), przypisać nową wartość do żądanego atrybutu, a następnie zatwierdzić zmiany za pomocą obiektu sesji. Poniżej zmieniamy oceny ucznia Juhi na 100.

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

Usunięcie rekordu jest równie łatwe, poprzez usunięcie żądanego obiektu z sesji.

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