PyQt:为现有数据库制作CRUD UI的最简单方法?

dav*_*ave 5 qt pyqt pyside

在最少量的代码中,我应该如何枚举现有数据库表中的(数百个)列,并创建一个表格视图,该表格视图与表格单元格中适合类型的小部件耦合到数据库以修改数据?

由于Qt Designer的数据库连接向导,我明白过去这很简单,但它已经被弃用了.

fas*_*ked 7

据说最简单的方法是使用QSqlTableModel.我们假设我们想要:

  • 查看数据并在表之间切换
  • 使用适当的编辑器编辑数据,例如QSpinBox for integers
  • 插入行
  • 并删除行

好的,首先我们需要获取数据库中所有表的列表.这可以使用QSqlDatabase::tables方法实现.我还将QComboxBox用来显示表格:

 class MainWindow(QtWidgets.QFrame):
     def __init__(self, parent=None):
         QtWidgets.QFrame.__init__(self, parent)

         # Connect to database
         self.__database__ = QtSql.QSqlDatabase.addDatabase('QSQLITE')
         self.__database__.setDatabaseName('sqlite.db')
         self.__database__.open()

         # Create QComboBox to show tables
         self.__tableNames__ = QtWidgets.QComboBox(self)

         # Create QTableView to show table's data
         self.__tableGrid__ = QtWidgets.QTableView(self)

         # Create table model 
         self.__tableModel__ = QtSql.QSqlTableModel(self, self.__database__)
         self.__tableGrid__.setModel(self.__tableModel__)

         # Connect combobox signal to update model
         self.__tableNames__.currentIndexChanged[str].connect(self.__tableModel__.setTable)
         self.__tableNames__.currentIndexChanged[str].connect(self.__tableModel__.select)

         # Set the list of the tables to combobox
         self.__tableNames__.addItems(self.__database__.tables())
Run Code Online (Sandbox Code Playgroud)

现在我们已经可以在数据库表之间切换并编辑数据.但默认编辑器是QLineEdit.我们可以使用QItemDelegate课程为其他编辑提供.在createEditor函数中,我们可以从中获取列的类型QSqlField.有一个缺点,因为至少对于SQLite而言DATETIME它始终会返回string(但它是SQLite :)).可能你应该找到其他方式来获得类型.

 class SqlItemDelegate(QtWidgets.QStyledItemDelegate):
     def __init__(self, database, parent=None):
         QtWidgets.QStyledItemDelegate.__init__(self, parent)
         self.__table__ = ''
         self.__database__ = database

     def setTable(self, table):
         self.__table__ = table

     def createEditor(self, parent, option, index):
         record = self.__database__.record(self.__table__)
         column_type = record.field(record.fieldName(index.column())).type()

         print(record.fieldName(index.column()), column_type)
         if column_type == QtCore.QVariant.Double:
             return QtWidgets.QDoubleSpinBox(parent)
         if column_type == QtCore.QVariant.DateTime:
             return QtWidgets.QDateTimeEditor(parent)
         # etc.

         return QtWidgets.QStyledItemDelegate.createEditor(self, parent, option, index)
Run Code Online (Sandbox Code Playgroud)

同样在MainWindow中,我们应该使用combobox创建并连接委托以更新表名:

class MainWindow(QtWidgets.QFrame):def init(self,parent = None):#.....

     self.__delegate__ = SqlItemDelegate(self.__database__, self)
     self.__tableGrid__.setItemDelegate(self.__delegate__)

     self.__tableNames__.currentIndexChanged[str].connect(self.__delegate__.setTable)
Run Code Online (Sandbox Code Playgroud)

最后一步是实现insertdelete功能:

 class MainWindow(QtWidgets.QFrame):
     def __init__(self, parent=None):
         # .....

         self.__insertRow__ = QtWidgets.QPushButton('Insert', self)
         self.__insertRow__.clicked.connect(self.insertRow)
         self.__deleteRow__ = QtWidgets.QPushButton('Delete', self)
         self.__deleteRow__.clicked.connect(self.deleteRow)

     def deleteRow(self):
         index = self.__tableGrid__.currentIndex()
         self.__tableModel__.removeRows(index.row(), 1)

     def insertRow(self):
         self.__tableModel__.insertRows(0, 1)
Run Code Online (Sandbox Code Playgroud)