====== Tvorba GUI pomocí PyQT 2/2 ======
===== 1. Databáze =====
Knihovna QT obsahuje rozhraní pro připojení k řadě databází. V následujícím příkladu si ukážeme, jak se připojit k databázi typu SQLite a trochu se seznámíme i s dotazovacím jazykem SQL. V PyQt5 se pro práci s databázemi na systémové úrovni používá třída [[https://doc.qt.io/qtforpython/PySide2/QtSql/QSqlDatabase.html|QSqlDatabase]], pro manipulaci s daty slouží třída [[https://doc.qt.io/qtforpython/PySide2/QtSql/QSqlQuery.html|QSqlQuery]].
==== SQLite ====
[[https://sqlite.org/index.html|SQLite]] je relační databázový systém, který není na rozdíl od větších systémů založen na architektuře server-klient, ale je tvořen jen jednoduchochou knihovnou (napsanou v C), které poskytuje rozhraní k lokálnímu datovému úložišti. Každá databáze je ukládána do samostatného souboru. Výhodou je snadná přenositelnost a to i mezi platformami, navíc existuje i řada desktopových aplikací, které umožňují práci s databázemi, např. [[https://sqlitestudio.pl|SQLiteStudio]].
Na rozdíl od jiných systémů není třeba datababázi explicitně vytvářet, pokud neexistuje, je vytvořena automaticky při otevření:
from PyQt5.QtSql import *
db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('studenti.db')
db.open()
Pro práci s databázemi slouží dotazovací jazyk [[https://cs.wikipedia.org/wiki/SQL|SQL]], resp. jeho podmnožina. Data jsou uložena v tabulkách, jejichž sloupce mají název a datový typ. V první fázi budeme pořebovat vytvořit tabulku, specifikovat její sloupce a naplnit ji daty. V příkladu vytvoříme záznam v podobě tabulky ''seznam'', naplněné daty studentů s náledujícími vlastnostmi:
* **id** - číslo záznamu, datový typ ''int'', v rámci tabulky automaticky přidělené a automaticky inkrementované
* **jmeno** - jméno studenta, datový typ ''varchar''
* **prijmeni** - příjmení studenta, datový typ ''varchar''
Pro vytvoření a naplnění tabulky využijeme metodu [[https://doc.qt.io/qtforpython/PySide2/QtSql/QSqlQuery.html#PySide2.QtSql.PySide2.QtSql.QSqlQuery.exec_|QSqlQuery.exec()]]
sql = QSqlQuery()
sql.exec("create table seznam (id int primary key, jmeno varchar(20), prijmeni varchar(20))")
sql.exec("insert into seznam values (1, 'Jan', 'Novak')")
sql.exec("insert into seznam values (2, 'Jana', 'Novakova')")
==== Manipulace s daty ====
S daty v databáze lze manipulovat různými způsoby
q = QSqlQuery("select * from seznam")
rec = q.record()
jmeno = rec.indexOf("jmeno") # index pole "jmeno"
while q.next():
print (q.value(jmeno)) # vypsani vsech jmen
Pokud je třeba ovlivňovat podobu SQL dotazu programem, nejjednodušší metodou je sestavení textového řetězce
jmeno = input("zadej jmeno: ")
prijmeni = input("zadej prijmeni: ")
q = QSqlQuery("insert into seznam values (1, {}, {}".format(jmeno, prijmeni))
q.exec()
Třída QSqlQuery obsahuje sofistikovanější nástoj - [[https://doc.qt.io/qtforpython/PySide2/QtSql/QSqlQuery.html#approaches-to-binding-values|binding]]
q = QSqlQuery()
q.prepare("INSERT INTO seznam (id, jmeno, prijmeni) VALUES (:id, :jmeno, :prijmeni)")
q.bindValue(":id", 1001)
q.bindValue(":jmeno", "Bart")
q.bindValue(":prijmeni", "Simpson")
q.exec()
Třída QSqlTableModel poskytuje vysokoúrovňový pohled na data uložená v tabulkách - poskytuje editovatelný model pro zápis a čtení jednotlivých záznamů v tabulce. Model je možné použít přímo v komponentě QTableView. Pro editaci je možné změnit některou z následujících strategií:
* QSqlTableModel.OnFieldChange - všechny změny modelu budou aplikovány ihned po editaci
* QSqlTableModel.OnRowChange - změny budou aplikovány ve chvíli kdy uživatel zvolí jiný řádek
* QSqlTableModel.OnManualSubmit - všechny změny modelu budou uloženy v mezipaměti, dokud nebude zavolána metoda ''submitAll()'' nebo ''revertAll()''
model = QtSql.QSqlTableModel()
model.setTable('seznam')
model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
model.select()
Model je pak použit v instanci třídy QTableView:
view = QTableView()
view.setModel(model)
view.setWindowTitle(title)
Kompletní příklad by pak mohl vypadat takto:
from PyQt5.QtWidgets import *
from PyQt5.QtSql import *
from PyQt5.QtCore import *
def initializeModel(model):
model.setTable('seznam')
model.setEditStrategy(QSqlTableModel.OnFieldChange)
model.select()
model.setHeaderData(0, Qt.Horizontal, "ID")
model.setHeaderData(1, Qt.Horizontal, "Jmeno")
model.setHeaderData(2, Qt.Horizontal, "Prijmeni")
def createView(title, model):
view = QTableView()
view.setModel(model)
view.setWindowTitle(title)
return view
def addrow():
ret = model.insertRows(model.rowCount(), 1)
def findrow(i):
delrow = i.row()
if __name__ == '__main__':
app = QApplication([])
db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('studenti.db')
model = QSqlTableModel()
delrow = -1
initializeModel(model)
view1 = createView("Table Model (View 1)", model)
view1.clicked.connect(findrow)
dlg = QDialog()
layout = QVBoxLayout()
layout.addWidget(view1)
button = QPushButton("Add a row")
button.clicked.connect(addrow)
layout.addWidget(button)
btn1 = QPushButton("del a row")
btn1.clicked.connect(lambda: model.removeRow(view1.currentIndex().row()))
layout.addWidget(btn1)
dlg.setLayout(layout)
dlg.setWindowTitle("Database Demo")
dlg.show()
app.exec()