PyQt5 Quick Start PyQt5 Database Operation

Posted by dubrubru on Mon, 29 Jul 2019 01:11:47 +0200

Quick Start for PyQt5 (8) PyQt5 database operations

1. SQLite database

1. Introduction to SQLite

SQLite is a lightweight database that implements a self-contained, server-free, zero-configuration, transactional SQL database engine, mainly used as a database for mobile applications and small desktop applications.
Official website:
https://www.sqlite.org

2. Common SQLite operations

Create a database file and enter SQLite command line mode after creation.
sqlite3 DatabaseName.db
View existing database files and execute in SQLLite command line mode:
.databases
Open an existing database file and create it if it does not exist.
sqlite3 DatabaseName.db
View help information and execute in SQLLite command line mode:
.help
Create a table to execute in SQLLite command line mode:
create table person(id integer primary key, name text);
Insert data into table:
insert into person(id, name) values(1, "zhangsan");
Query operation:
select * from person;
Query table structure:
.schema person

3. SQLite Management Tools

SQLite has several open source and excellent DBMS s (database management systems) that provide an interface to manipulate the SQLite database.
SQLiteStudio is a very professional SQLite database management software, compact, powerful, Chinese-language support, installation-free.
SQLiteStudio Download:
https://sqlitestudio.pl/index.rvt?act=download

2. Connecting to a database

1. Database Driver Type

In PyQt, the QSqlDatabase class is used to connect to databases and can use database drivers to interact with different databases. A QSqlDatabase instance represents a database connection.The following types of database drivers are available:
QDB2 IBM DB2 Driver
QMYSQL MySQL Driver
QOCI Oracle Call Interface Driver
QODBC ODBC driver (including MS SQL Server)
QPSQL PostgreSQL Driver
QSQLITE SQLite3 Driver
QSQLITE2 SQLite2 Driver

2. Common methods of QSqlDatabase

Common QSqlDatabase methods are as follows:
addDataBase: Set the database driver type to connect to the database
setDatabaseName: Sets the name of the database to which you are connecting
setHostName: Sets the host name where the database is located
setUserName: Specifies the user name of the connection
setPassword: Sets the password for the connection object
commit: commits the transaction and returns True if the execution is successful.
Rollback: rollback database transaction
Close: close the database connection

3. Instances of database connection

import sys
from PyQt5.QtSql import QSqlDatabase
from PyQt5.QtCore import *

if __name__ == "__main__":
    app = QCoreApplication(sys.argv)
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("/home/user/test.db")
    if db.open():
        print("open DB success.")
    sys.exit(app.exec_())

3. Executing SQL Statements

QSqlQuery has the ability to execute and manipulate SQL statements, execute DDL and DML type SQL queries, and QSqlQuery.exec_() is used to execute SQL operations.

import sys
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
from PyQt5.QtCore import *

def createDB():
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("/home/user/test.db")
    if db.open():
        query = QSqlQuery()
        query.exec_("create table person(id int primary key, name varchar(20), address varchar(30))")
        query.exec_("insert into person values(1, 'Bauer', 'beijing')")
        query.exec_("insert into person values(2, 'Jack', 'shanghai')")
        query.exec_("insert into person values(3, 'Alex', 'chengdu')")

        db.close()

if __name__ == "__main__":
    app = QCoreApplication(sys.argv)
    createDB()
    sys.exit(app.exec_())

After executing the SQL statement, if there are no other database operations, you need to use db.close to close the database connection, because the database connection resources are limited, the database connection that is no longer used must be closed, or the database connection resources will eventually be exhausted, causing the program to connect to the database normally.
If you need to read and display data from the database in PyQt's window, you need to open the database when the window is initialized and close the database connection when the window is closed.

import sys
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("/home/user/test.db")
        self.db.open()

    def closeEvent(self, event):
        self.db.close()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

4. Database Model View

QSqlTableModel in Qt is an advanced interface that provides a readable and writable data model for reading and saving data in a single table and for displaying tables in a database in a QTableView.After connecting to the database, use seTable to set the table to query, setFilter function to set filter conditions, and select function to query.You can use the setEditerStrategy function to set editing policies, which are as follows:
QSqlTableModel.OnFieldChange: All changes are updated to the database in real time
QSqlTableModel.OnRowChange: Updates the current row when the user selects a different row
QSqlTableModel.OnManuallSubmit: Manual submission, not automatic submission

import sys
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("/home/user/test.db")
        self.db.open()
        self.model = QSqlTableModel()
        self.initializedModel()

        self.tableView = QTableView()
        self.tableView.setModel(self.model)

        self.layout = QVBoxLayout()
        addButton = QPushButton("add")
        deleteButton = QPushButton("delete")
        hLayout = QHBoxLayout()
        hLayout.addWidget(addButton)
        hLayout.addWidget(deleteButton)
        self.layout.addWidget(self.tableView)
        self.layout.addLayout(hLayout)
        self.setLayout(self.layout)
        self.resize(600, 400)

        addButton.clicked.connect(self.onAddRow)
        deleteButton.clicked.connect(self.onDeleteRow)

    def initializedModel(self):
        self.model.setTable("person")
        self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
        self.model.select()
        self.model.setHeaderData(0, Qt.Horizontal, "ID")
        self.model.setHeaderData(1, Qt.Horizontal, "Name")
        self.model.setHeaderData(2, Qt.Horizontal, "Address")

    def onAddRow(self):
        self.model.insertRows(self.model.rowCount(), 1)
        self.model.submit()

    def onDeleteRow(self):
        self.model.removeRow(self.tableView.currentIndex().row())
        self.model.submit()
        self.model.select()

    def closeEvent(self, event):
        self.db.close()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

5. Paging Query

1. Data preparation

Paging uses data as a student table of student information, can be inserted using SQLite command line using SQL statement, or can be created and inserted using Python program.

db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("/home/user/test.db")
if not db.open():
    return False
query = QSqlQuery()
query.exec_("create table student(id int primary key, name varchar(20), sex varchar(8), age int);")

query.exec_("insert into student values(1, 'Bauer', 'Man', 25)")
query.exec_("insert into student values(2, 'Alex', 'Man', 24)")
query.exec_("insert into student values(3, 'Mary', 'Female', 23)")
query.exec_("insert into student values(4, 'Jack', 'Man', 25)")
query.exec_("insert into student values(5, 'xiaoming', 'Man', 24)")
query.exec_("insert into student values(6, 'xiaohong', 'Female', 23)")
query.exec_("insert into student values(7, 'xiaowang', 'Man', 25)")
query.exec_("insert into student values(8, 'xiaozhang', 'Man', 25)")
query.exec_("insert into student values(9, 'xiaoli', 'Man', 25)")
query.exec_("insert into student values(10, 'xiaohan', 'Man', 25)")

2. Paging window

Paging windows include labels, the previous page, the next page, jump buttons, and so on.

import sys
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel, QSqlQueryModel
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class DataGrid(QWidget):
    def __init__(self, parent=None):
        super(DataGrid, self).__init__(parent)
        # Database Connection
        self.db = None
        # Layout Manager
        self.layout = QVBoxLayout()
        # Query Model
        self.queryModel = QSqlQueryModel()
        # Table View
        self.tableView = QTableView()
        self.tableView.setModel(self.queryModel)
        #
        self.totalPageLabel = QLabel()
        self.currentPageLabel = QLabel()
        self.switchPageLineEdit = QLineEdit()
        self.prevButton = QPushButton("Prev")
        self.nextButton = QPushButton("Next")
        self.switchPageButton = QPushButton("Switch")
        self.currentPage = 0
        self.totalPage = 0
        self.totalRecordCount = 0
        self.pageRecordCount = 5

    def initUI(self):
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.layout.addWidget(self.tableView)

        hLayout = QHBoxLayout()
        hLayout.addWidget(self.prevButton)
        hLayout.addWidget(self.nextButton)
        hLayout.addWidget(QLabel("Jump To"))
        self.switchPageLineEdit.setFixedWidth(40)
        hLayout.addWidget(self.switchPageLineEdit)
        hLayout.addWidget(QLabel("page"))
        hLayout.addWidget(self.switchPageButton)
        hLayout.addWidget(QLabel("Current page:"))
        hLayout.addWidget(self.currentPageLabel)
        hLayout.addWidget(QLabel("Total pages:"))
        hLayout.addWidget(self.totalPageLabel)
        hLayout.addStretch(1)

        self.layout.addLayout(hLayout)
        self.setLayout(self.layout)

        self.setWindowTitle("DataGrid")
        self.resize(600, 300)

    def closeEvent(self, event):
        self.db.close()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = DataGrid()
    window.initUI()
    window.show()
    sys.exit(app.exec_())

3. Paging Query Implementation

Read the student table of the database to initialize the table data model.

import sys
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel, QSqlQueryModel
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import re

class DataGrid(QWidget):
    def __init__(self, parent=None):
        super(DataGrid, self).__init__(parent)
        # Declare Database Connections
        self.db = None
        # Layout Manager
        self.layout = QVBoxLayout()
        # Query Model
        self.queryModel = QSqlQueryModel()
        # Table View
        self.tableView = QTableView()
        self.tableView.setModel(self.queryModel)
        #
        self.totalPageLabel = QLabel()
        self.currentPageLabel = QLabel()
        self.switchPageLineEdit = QLineEdit()
        self.prevButton = QPushButton("Prev")
        self.nextButton = QPushButton("Next")
        self.switchPageButton = QPushButton("Switch")
        # Current Page
        self.currentPage = 1
        # PageCount
        self.totalPage = None
        # Total Records
        self.totalRecordCount = None
        # Number of records per page
        self.pageRecordCount = 4

        self.initUI()
        self.initializedModel()
        self.setUpConnect()
        self.updateStatus()

    def initUI(self):
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.layout.addWidget(self.tableView)

        hLayout = QHBoxLayout()
        hLayout.addWidget(self.prevButton)
        hLayout.addWidget(self.nextButton)
        hLayout.addWidget(QLabel("Jump To"))
        self.switchPageLineEdit.setFixedWidth(40)
        hLayout.addWidget(self.switchPageLineEdit)
        hLayout.addWidget(QLabel("page"))
        hLayout.addWidget(self.switchPageButton)
        hLayout.addWidget(QLabel("Current page:"))
        hLayout.addWidget(self.currentPageLabel)
        hLayout.addWidget(QLabel("Total pages:"))
        hLayout.addWidget(self.totalPageLabel)
        hLayout.addStretch(1)

        self.layout.addLayout(hLayout)
        self.setLayout(self.layout)

        self.setWindowTitle("DataGrid")
        self.resize(600, 300)

    def setUpConnect(self):
        self.prevButton.clicked.connect(self.onPrevPage)
        self.nextButton.clicked.connect(self.onNextPage)
        self.switchPageButton.clicked.connect(self.onSwitchPage)

    def initializedModel(self):
        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("/home/user/test.db")
        if not self.db.open():
            return False
        self.queryModel.setHeaderData(0, Qt.Horizontal, "ID")
        self.queryModel.setHeaderData(1, Qt.Horizontal, "Name")
        self.queryModel.setHeaderData(2, Qt.Horizontal, "Sex")
        self.queryModel.setHeaderData(3, Qt.Horizontal, "Age")
        # Get all the records of the table
        sql = "SELECT * FROM student"
        self.queryModel.setQuery(sql, self.db)
        self.totalRecordCount = self.queryModel.rowCount()
        if self.totalRecordCount % self.pageRecordCount == 0:
            self.totalPage = self.totalRecordCount / self.pageRecordCount
        else:
            self.totalPage = int(self.totalRecordCount / self.pageRecordCount) + 1
        # Show Page 1
        sql = "SELECT * FROM student limit %d,%d" % (0, self.pageRecordCount)
        self.queryModel.setQuery(sql, self.db)

    def onPrevPage(self):
        self.currentPage -= 1
        limitIndex = (self.currentPage - 1) * self.pageRecordCount
        self.queryRecord(limitIndex)
        self.updateStatus()

    def onNextPage(self):
        self.currentPage += 1
        limitIndex = (self.currentPage - 1) * self.pageRecordCount
        self.queryRecord(limitIndex)
        self.updateStatus()

    def onSwitchPage(self):
        szText = self.switchPageLineEdit.text()
        pattern = re.compile('^[0-9]+$')
        match = pattern.match(szText)
        if not match:
            QMessageBox.information(self, "Tips", "please enter a number.")
            return
        if szText == "":
            QMessageBox.information(self, "Tips", "Please enter a jump page.")
            return
        pageIndex = int(szText)
        if pageIndex > self.totalPage or pageIndex < 1:
            QMessageBox.information(self, "Tips", "No page specified, re-enter.")
            return

        limitIndex = (pageIndex - 1) * self.pageRecordCount
        self.queryRecord(limitIndex)
        self.currentPage = pageIndex
        self.updateStatus()

    # Query records based on paging
    def queryRecord(self, limitIndex):
        sql = "SELECT * FROM student limit %d,%d" % (limitIndex, self.pageRecordCount)
        self.queryModel.setQuery(sql)

    # Update Spatial Status
    def updateStatus(self):
        self.currentPageLabel.setText(str(self.currentPage))
        self.totalPageLabel.setText(str(self.totalPage))
        if self.currentPage <= 1:
            self.prevButton.setEnabled(False)
        else:
            self.prevButton.setEnabled(True)

        if self.currentPage >= self.totalPage:
            self.nextButton.setEnabled(False)
        else:
            self.nextButton.setEnabled(True)

    # Close database connection when interface is closed
    def closeEvent(self, event):
        self.db.close()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = DataGrid()
    window.show()
    sys.exit(app.exec_())

Topics: Python Database SQL SQLite Qt