SQLAlchemy je open-source knihovna v Pythonu, která dovoluje dotazování se relačních databází pomocí „SQLAlchemy Core“ a pracovat pomocí objektově relačního mapování (ORM) s databázemi. Knihovna dovoluje vývojáři pracovat s databázemi jako plnohodnotnými objekty v Pythonu.
Popis knihovny SQLAlchemy poskytuje databázová schémata pro jejich vytvoření, dotazování a objektově relační mapování. Hlavními součástmi knihovny jsou:
Komplexní zabudovaný doménově specifický jazyk pro SQL v Pythonu s názvem „SQLAlchemy Core“, který poskytuje prostředky pro vytváření a provádění dotazů SQL. Výkonný ORM, který umožňuje mapování tříd Pythonu na databázové tabulky. Knihovna podporuje migrace datových schémat. Knihovna je kompatibilní s různými databázovými backendy. Součástí knihovny jsou nástroje databázové propojení i transakční management.
Historie knihovny K první vydání knihovny došlo v únoru 2006. Vyvinul se tak, že nyní zahrnuje širokou škálu funkcí pro interakci s databázemi a získal si popularitu mezi vývojáři jazyka Python. Mezi významné verze patří:
Verze 0.1 (2006): Inicializační verze Verze 1.0 (2015): Významná vylepšení v ORM, a jazyce SQL výrazů Verze 1.4 (2021): Zavedení nového rozhraní ORM API
Příklad využití knihovny v Pythonu Následující příklad představuje n-k-1 vztah mezi filmy a jejich režiséry. Ukazuje se, jak uživatelsky definované třídy Pythonu vytvářejí odpovídající databázové tabulky, jak se instance s vztahy vytvářejí z obou stran vztahu a nakonec jak lze data dotazovat – ilustruje automaticky generované dotazy SQL pro lazy i eager loading.
Definice schématu Vytvoření dvou tříd Pythonu a odpovídajících databázových tabulek v DBMS: #import potřebných prvků z knihovny SQLAlchemy from sqlalchemy import * from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relation, sessionmaker
Base = declarative_base()
class Movie(Base): __tablename__ = "movies"
id = Column(Integer, primary_key=True) # primární klíč pro databázi Movie title = Column(String(255), nullable=False) year = Column(Integer) directed_by = Column(Integer, ForeignKey("directors.id")) # cizí klíč, který propojuje datábazi Movie s databází Director
director = relation("Director", backref="movies", lazy=False)
def __init__(self, title=None, year=None): self.title = title self.year = year
def __repr__(self): return f"Movie({self.title}, {self.year}, {self.director})"
class Director(Base): __tablename__ = "directors"
id = Column(Integer, primary_key=True) #ID režiséra, které slouží jako primární klíč pro databází Director a jako prvek, který propojuje obě databáze name = Column(String(50), nullable=False, unique=True)
def __init__(self, name=None): self.name = name
def __repr__(self): return f"Director({self.name})"
engine = create_engine("dbms://user:pwd@host/dbname") Base.metadata.create_all(engine)
Vložení dat do databáze pomocí knihovny Existuje více způsobu vložený jednotlivých záznamů do databází pomocí knihovny: Session = sessionmaker(bind=engine) session = Session()
# vložení jednotlivých objektů do databází m1 = Movie("Robocop", 1987) m1.director = Director("Paul Verhoeven")
# vložení objektů jako kolekce d2 = Director("George Lucas") # vložení nového režiséra d2.movies = [Movie("Star Wars", 1977), Movie("THX 1138", 1971)] # vložení dvou filmů, které se přiřadí k Lucasovi
try: session.add(m1) session.add(d2) session.commit() except: session.rollback() # navrací provedené změny, aby byla zajištěna integrita dat
Dotazování # Načítání všech záznamů typu Movie z databáze alldata = session.query(Movie).all() # Procházení všech načtených záznamů for somedata in alldata: # Tisk každého záznamu z databáze v konzoli print(somedata)
SQLAlchemy odešle následující dotaz do DBMS (bez aliasů): -- Načítá ID, název, rok a ID režiséra z tabulky Movies bez spojení s tabulkou Directors SELECT movies.id, movies.title, movies.year, movies.directed_by, directors.id, directors.name FROM movies LEFT OUTER JOIN directors ON directors.id = movies.directed_by
Výstupem je: Movie('Robocop', 1987L, Director('Paul Verhoeven')) Movie('Star Wars', 1977L, Director('George Lucas')) Movie('THX 1138', 1971L, Director('George Lucas'))
Nastavením hodnoty lazy=True (default) by SQLAlchemy nejprve vydalo dotaz na získání seznamu filmů a teprve v případě potřeby (lazy) by pro každého režiséra vydalo dotaz na získání jména příslušného režiséra: -- Načítá ID a jméno z tabulky Directors, ale vyhledává pouze režiséra podle specifického ID (ukázaného jako %s) SELECT movies.id, movies.title, movies.year, movies.directed_by FROM movies
-- Získává informace pouze o jednom konkrétním režisérovi SELECT directors.id, directors.name FROM directors WHERE directors.id = %s
Reference
Kategorie:Objektově relační mapování Kategorie:Knihovny Pythonu Kategorie:Software pod licencí MIT