Lekce 2 - SQLAlchemy - Session a základní práce s daty
V minulé lekci, SQLAlchemy - Úvod a instalace, jsme probrali základní informace a instalaci SQLAlchemy.
Jak jsme si slíbili, vrátíme se k deklarativnímu mapování a naší
třídě Base
Fyzická databáze
Spusťme databázový stroj, který provede potřebné akce. Stvoří databázi a v ní tabulky:
# Vytvoření databáze a tabulek v nich
Base.metadata.create_all(db)
Po spuštění dostaneme výstup podobný tomuto:
Konzolová aplikace
2022-03-03 17:28:34,390 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-03-03 17:28:34,390 INFO sqlalchemy.engine.Engine PRAGMA main.table_info("vat")
2022-03-03 17:28:34,390 INFO sqlalchemy.engine.Engine [raw sql] ()
2022-03-03 17:28:34,390 INFO sqlalchemy.engine.Engine PRAGMA temp.table_info("vat")
2022-03-03 17:28:34,390 INFO sqlalchemy.engine.Engine [raw sql] ()
2022-03-03 17:28:34,390 INFO sqlalchemy.engine.Engine
CREATE TABLE vat (
vat_id INTEGER NOT NULL,
rate FLOAT,
PRIMARY KEY (vat_id)
)
2022-03-03 17:28:34,390 INFO sqlalchemy.engine.Engine [no key 0.00006s] ()
2022-03-03 17:28:34,474 INFO sqlalchemy.engine.Engine COMMIT
Při vytváření databáze je dobrým zvykem se přesvědčit, že databáze skutečně existuje a obsahuje vše, co obsahovat má. V našem případě jednu prázdnou tabulku.
Nová data, instance třídy a Session
Třída Vat
je běžná třída, která obsahuje navíc několik
magických informací a jako s takovou s ní můžeme pracovat. Další
zajímavostí by mohla být skutečnost, že odvozením od Base
je
již vybavena inicializační metodou __init__()
a můžeme jí
předávat pojmenované argumenty. Pokud nějaký atribut vynecháme, bude
nastaven na None
:
vat_none = Vat(rate=0.0) print(vat_none.vat_id, vat_none.rate)
Výstup:
Konzolová aplikace
>>> None 0.0
Prozatím však nemá nic společného s databází, je to jen obyčejná
třída. Abychom mohli pracovat s daty na úrovni databáze, musíme vytvořit
session
, tedy lépe řečeno nejprve jakousi továrnu na ně a
poté aktuální relaci:
from sqlalchemy.orm import sessionmaker Session = sessionmaker(bind=db)
Pokud zatím nemáme databází definovanou (je například v jiném modulu), postačí to takto:
Session = sessionmaker()
Až to bude skutečně nutné, v místě připojení použijeme:
Session.configure(bind=db)
Továrnu máme, můžeme začít vkládat data. Z továrny uděláme menší pobočku pro aktuální použití:
session = Session()
session.add(vat_none)
print(session.new)
Atribut session.new
obsahuje novinky v sezení a vrací
identifikační mapu dat:
Konzolová aplikace
IdentitySet([<DPH : id=None; sazba=0.0>])
Od této chvíle máme data přichystaná k persistenci. Přichystaná je
podstatný pojem, protože uložena nejsou. Čekají na
příkaz flush
, či lépe na commit
. Na druhou stranu
už s nimi můžeme pracovat. No, vlastně ještě nemůžeme. V tabulce máme
totiž primární klíč, který bude do chvíle uložení nastaven na hodnotu
None
, což se nebude Alchemy líbit. Nutně potřebuje
legální hodnotu:
vat_none.vat_id = 0
Nyní už je to v pořádku, ale reálně do prvního dotazu na získání
dat neproběhl žádný příkaz INSERT
.
Dotazy na data
Pro dotazy na data nám slouží metoda filter_by()
, která
zastupuje klasické WHERE
:
my_vat = session.query(Vat).filter_by(rate='0').first() print(my_vat) print(type(my_vat)) print(my_vat is vat_none) my_vat.rate = 21.0 print(session.dirty) vat_none.rate = 10.0 print(session.dirty)
Výsledek jsme si uložili do další proměnné a budeme hledat údaj s
hodnotou sazby 0
. Poté si zobrazíme získaná data, typ dat, a
ještě malou ukázku, když je v session položka se shodnými daty. Totožná
reference na objekt. Atribut session.dirty
obsahuje provedené
změny, podobně jako session.new
novinky:
Konzolová aplikace
2022-03-04 11:49:50,281 INFO sqlalchemy.engine.Engine INSERT INTO vat (vat_id, rate) VALUES (?, ?)
2022-03-04 11:49:50,281 INFO sqlalchemy.engine.Engine [generated in 0.00010s] (0, 0.0)
2022-03-04 11:49:50,283 INFO sqlalchemy.engine.Engine SELECT vat.vat_id AS vat_vat_id, vat.rate AS vat_rate
FROM vat
WHERE vat.rate = ?
LIMIT ? OFFSET ?
2022-03-04 11:49:50,283 INFO sqlalchemy.engine.Engine [generated in 0.00014s] ('0', 1, 0)
<DPH : id=0; sazba=0.0>
<class '__main__.Vat'>
True
IdentitySet([<DPH : id=0; sazba=21.0>])
IdentitySet([<DPH : id=0; sazba=10.0>])
Dotazovací techniky si probereme v další lekci, teď si ještě musíme data fyzicky uložit:
vat_none.rate = 0 vat_low = Vat(vat_id=1, rate=10.0) # ID musíme zadat ručně. Tabulka nemá autoincrement!!! vat_high = Vat(vat_id=2, rate=21.0) session.add_all([ vat_low, vat_high ]) print(session.dirty) print(session.new)
Raději vrátíme položku bez daně zpět na hodnotu 0
a
přidáme další dvě sazby. Metoda session.add_all()
ukládá do
session více objektů ve formě pole. Zobrazíme si chystané změny:
Konzolová aplikace
IdentitySet([<DPH : id=0; sazba=0>])
IdentitySet([<DPH : id=1; sazba=10.0>, <DPH : id=2; sazba=21.0>])
a skutečně fyzicky vložíme do tabulky v souboru:
session.commit()
Výstup:
Konzolová aplikace
2022-03-04 12:10:54,773 INFO sqlalchemy.engine.Engine INSERT INTO vat (vat_id, rate) VALUES (?, ?)
2022-03-04 12:10:54,773 INFO sqlalchemy.engine.Engine [generated in 0.00008s] ((1, 10.0), (2, 21.0))
2022-03-04 12:10:54,773 INFO sqlalchemy.engine.Engine COMMIT
Máme za sebou tvorbu naší první tabulky včetně vložení dat 😎 Věřím, že jste vše zvládli bez problémů. Pokud se přeci jen nějaké nejasnosti či komplikace vyskytly, podívejte se do přiloženého souboru a porovnejte vzorový kód s vlastním. Případné dotazy můžete psát do diskuse pod článkem.
V sérii se budeme ještě věnovat ošetřování chyb, více možností
SELECT
, aktualizace, mazání... zkrátka celý
CRUD 🙂
Tímto bych se s vámi rozloučil.
V příští lekci, SQLAlchemy - Relace, si ukážeme vztahy mezi daty v tabulkách (relace), vytvoříme si jednoduchý sklad a uvedeme si evidenci zboží.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 25x (2.42 kB)
Aplikace je včetně zdrojových kódů v jazyce SQLAlchemy