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