PyQt5 和带有 QtSql 的持久数据库
PyQt5 and persistent DB with QtSql
对 PyQt5 相当陌生,在设置示例应用程序时我 运行 遇到了 QtSql 的问题。我发现的所有示例都显示了使用数据库连接的单个 class,但 none 显示了如何在许多不同的 classes 上持续使用 QtSql classes数据库连接。我的应用程序中几乎所有的 MDI 子窗口都需要连接到数据库,但是当我设置连接时,我收到连接为 "duplicate" 的错误。我的问题是:
如果我的 MDI 应用程序包含多个需要数据库连接的对话框,我该如何永久设置数据库连接以便我的所有对话框都可以访问数据库?
如果您要连接到同一个数据库,则不必创建多个连接,只需创建一个连接,因为 qt 会全局管理这些连接,如 docs:
所示
QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const
QString &connectionName = QLatin1String(defaultConnection))
Adds a database to the list of database connections using the driver type and
the connection name connectionName. If there already exists a database
connection called connectionName, that connection is removed.
The database connection is referred to by connectionName. The newly
added database connection is returned.
If type is not available or could not be loaded, isValid() returns
false.
If connectionName is not specified, the new connection becomes the
default connection for the application, and subsequent calls to
database() without the connection name argument will return the
default connection. If a connectionName is provided here, use
database(connectionName) to retrieve the connection.
Warning: If you add a connection with the same name as an existing
connection, the new connection replaces the old one. If you call this
function more than once without specifying connectionName, the default
connection will be the one replaced.
示例:
.
├── connection.py
├── main.py
└── views.p
connection.py
from PyQt5 import QtWidgets, QtSql
def createConnection():
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(":memory:")
if not db.open():
QtWidgets.QMessageBox.critical(None, "Cannot open database",
"Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information how "
"to build it.\n\n"
"Click Cancel to exit.", QtWidgets.QMessageBox.Cancel)
return False
query = QtSql.QSqlQuery()
query.exec_("""CREATE TABLE IF NOT EXISTS person (id int primary key,
firstname VARCHAR(20),
lastname VARCHAR(20))""")
query.exec_("insert into person values(101, 'Danny', 'Young')")
query.exec_("insert into person values(102, 'Christine', 'Holand')")
query.exec_("insert into person values(103, 'Lars', 'Gordon')")
query.exec_("insert into person values(104, 'Roberto', 'Robitaille')")
query.exec_("insert into person values(105, 'Maria', 'Papadopoulos')")
query.exec_("""CREATE TABLE IF NOT EXISTS items (id INT primary key,
imagefile INT,
itemtype varchar(20),
description varchar(100))""");
query.exec_("insert into items "
"values(0, 0, 'Qt',"
"'Qt is a full development framework with tools designed to "
"streamline the creation of stunning applications and "
"amazing user interfaces for desktop, embedded and mobile "
"platforms.')");
query.exec_("insert into items "
"values(1, 1, 'Qt Quick',"
"'Qt Quick is a collection of techniques designed to help "
"developers create intuitive, modern-looking, and fluid "
"user interfaces using a CSS & JavaScript like language.')");
query.exec_("insert into items "
"values(2, 2, 'Qt Creator',"
"'Qt Creator is a powerful cross-platform integrated "
"development environment (IDE), including UI design tools "
"and on-device debugging.')");
query.exec_("insert into items "
"values(3, 3, 'Qt Project',"
"'The Qt Project governs the open source development of Qt, "
"allowing anyone wanting to contribute to join the effort "
"through a meritocratic structure of approvers and "
"maintainers.')");
return True
views.py
from PyQt5 import QtWidgets, QtSql
class PersonWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(PersonWidget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
view = QtWidgets.QTableView()
lay.addWidget(view)
model = QtSql.QSqlTableModel(self)
model.setTable("person")
model.select()
view.setModel(model)
class ItemsWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ItemsWidget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
view = QtWidgets.QTableView()
lay.addWidget(view)
model = QtSql.QSqlTableModel(self)
model.setTable("items")
model.select()
view.setModel(model)
main.py
from PyQt5 import QtWidgets, QtSql
from connection import createConnection
from views import PersonWidget, ItemsWidget
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.mdiarea = QtWidgets.QMdiArea()
self.setCentralWidget(self.mdiarea)
sub1 = QtWidgets.QMdiSubWindow()
sub1.setWidget(PersonWidget())
self.mdiarea.addSubWindow(sub1)
sub1.show()
sub2 = QtWidgets.QMdiSubWindow()
sub2.setWidget(ItemsWidget())
self.mdiarea.addSubWindow(sub2)
sub2.show()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
if not createConnection():
sys.exit(-1)
w = MainWindow()
w.show()
sys.exit(app.exec_())
在前面的示例中,有 createConnection()
方法建立连接并在必要时创建表。而那些使用数据库的数据而没有指明连接的视图因此使用默认连接,即在createConnection()
.
中建立的连接。
对 PyQt5 相当陌生,在设置示例应用程序时我 运行 遇到了 QtSql 的问题。我发现的所有示例都显示了使用数据库连接的单个 class,但 none 显示了如何在许多不同的 classes 上持续使用 QtSql classes数据库连接。我的应用程序中几乎所有的 MDI 子窗口都需要连接到数据库,但是当我设置连接时,我收到连接为 "duplicate" 的错误。我的问题是:
如果我的 MDI 应用程序包含多个需要数据库连接的对话框,我该如何永久设置数据库连接以便我的所有对话框都可以访问数据库?
如果您要连接到同一个数据库,则不必创建多个连接,只需创建一个连接,因为 qt 会全局管理这些连接,如 docs:
所示QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String(defaultConnection))
Adds a database to the list of database connections using the driver type and the connection name connectionName. If there already exists a database connection called connectionName, that connection is removed.
The database connection is referred to by connectionName. The newly added database connection is returned.
If type is not available or could not be loaded, isValid() returns false.
If connectionName is not specified, the new connection becomes the default connection for the application, and subsequent calls to database() without the connection name argument will return the default connection. If a connectionName is provided here, use database(connectionName) to retrieve the connection.
Warning: If you add a connection with the same name as an existing connection, the new connection replaces the old one. If you call this function more than once without specifying connectionName, the default connection will be the one replaced.
示例:
.
├── connection.py
├── main.py
└── views.p
connection.py
from PyQt5 import QtWidgets, QtSql
def createConnection():
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(":memory:")
if not db.open():
QtWidgets.QMessageBox.critical(None, "Cannot open database",
"Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information how "
"to build it.\n\n"
"Click Cancel to exit.", QtWidgets.QMessageBox.Cancel)
return False
query = QtSql.QSqlQuery()
query.exec_("""CREATE TABLE IF NOT EXISTS person (id int primary key,
firstname VARCHAR(20),
lastname VARCHAR(20))""")
query.exec_("insert into person values(101, 'Danny', 'Young')")
query.exec_("insert into person values(102, 'Christine', 'Holand')")
query.exec_("insert into person values(103, 'Lars', 'Gordon')")
query.exec_("insert into person values(104, 'Roberto', 'Robitaille')")
query.exec_("insert into person values(105, 'Maria', 'Papadopoulos')")
query.exec_("""CREATE TABLE IF NOT EXISTS items (id INT primary key,
imagefile INT,
itemtype varchar(20),
description varchar(100))""");
query.exec_("insert into items "
"values(0, 0, 'Qt',"
"'Qt is a full development framework with tools designed to "
"streamline the creation of stunning applications and "
"amazing user interfaces for desktop, embedded and mobile "
"platforms.')");
query.exec_("insert into items "
"values(1, 1, 'Qt Quick',"
"'Qt Quick is a collection of techniques designed to help "
"developers create intuitive, modern-looking, and fluid "
"user interfaces using a CSS & JavaScript like language.')");
query.exec_("insert into items "
"values(2, 2, 'Qt Creator',"
"'Qt Creator is a powerful cross-platform integrated "
"development environment (IDE), including UI design tools "
"and on-device debugging.')");
query.exec_("insert into items "
"values(3, 3, 'Qt Project',"
"'The Qt Project governs the open source development of Qt, "
"allowing anyone wanting to contribute to join the effort "
"through a meritocratic structure of approvers and "
"maintainers.')");
return True
views.py
from PyQt5 import QtWidgets, QtSql
class PersonWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(PersonWidget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
view = QtWidgets.QTableView()
lay.addWidget(view)
model = QtSql.QSqlTableModel(self)
model.setTable("person")
model.select()
view.setModel(model)
class ItemsWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ItemsWidget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
view = QtWidgets.QTableView()
lay.addWidget(view)
model = QtSql.QSqlTableModel(self)
model.setTable("items")
model.select()
view.setModel(model)
main.py
from PyQt5 import QtWidgets, QtSql
from connection import createConnection
from views import PersonWidget, ItemsWidget
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.mdiarea = QtWidgets.QMdiArea()
self.setCentralWidget(self.mdiarea)
sub1 = QtWidgets.QMdiSubWindow()
sub1.setWidget(PersonWidget())
self.mdiarea.addSubWindow(sub1)
sub1.show()
sub2 = QtWidgets.QMdiSubWindow()
sub2.setWidget(ItemsWidget())
self.mdiarea.addSubWindow(sub2)
sub2.show()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
if not createConnection():
sys.exit(-1)
w = MainWindow()
w.show()
sys.exit(app.exec_())
在前面的示例中,有 createConnection()
方法建立连接并在必要时创建表。而那些使用数据库的数据而没有指明连接的视图因此使用默认连接,即在createConnection()
.