Search
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 QSqlDatabase, pro manipulaci s daty slouží třída QSqlQuery.
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ř. 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 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:
seznam
int
varchar
Pro vytvoření a naplnění tabulky využijeme metodu 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')")
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 - 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í:
submitAll()
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()