【问题标题】:PyQt5 and persistent DB with QtSqlPyQt5 和带有 QtSql 的持久数据库
【发布时间】:2018-12-20 17:54:51
【问题描述】:

PyQt5 相当新,在设置示例应用程序时,我遇到了 QtSql 的问题。我发现的所有示例都显示了使用数据库连接的单个类,但没有显示如何在需要数据库连接的许多不同类上持久使用 QtSql 类。我的应用程序中几乎所有的 MDI 子窗口都需要连接到数据库,但是当我设置连接时,我收到连接“重复”的错误。我的问题是:

如果我的 MDI 应用程序包含多个需要数据库连接的对话框,我如何永久设置数据库连接,以便我的所有对话框都可以访问数据库?

【问题讨论】:

  • 对话框是连接到多个数据库还是全部连接到同一个数据库?
  • 他们都连接到同一个数据库

标签: python python-3.x pyqt pyqt5 qtsql


【解决方案1】:

如果您要连接到同一个数据库,则不必创建多个连接,只需创建一个,因为 qt 会按照docs 的指示全局管理这些连接:

QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String(defaultConnection))

使用驱动程序类型将数据库添加到数据库连接列表中 连接名称connectionName。如果已经存在数据库 名为 connectionName 的连接,该连接被删除。

数据库连接由connectionName 引用。新的 返回添加的数据库连接。

如果类型不可用或无法加载,isValid() 返回 假的。

如果未指定 connectionName,则新连接将成为 应用程序的默认连接,以及随后的调用 没有连接名称参数的 database() 将返回 默认连接。如果此处提供了 connectionName,请使用 database(connectionName) 来检索连接。

警告:如果您添加与现有连接同名的连接 连接,新连接替换旧连接。如果你打电话给这个 函数不止一次,不指定connectionName,默认 连接将被替换。


例子:

.
├── 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)

ma​​in.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()中建立的那个。

【讨论】:

  • 我读过同样的东西;但是,我对实施一无所知。我是否创建了一个连接到数据库并返回数据库句柄的全局类,然后从每个对话框中调用该类?
  • @user1532602 不,没必要,一开始就创建,我举个例子。
  • 正是我想要的,谢谢@eyllanesc,你现在和过去都是一个很好的资源。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多