PyQt: самый простой способ сделать CRUD UI для существующей базы данных?
В наименьшем количестве кода, как я должен перечислить (сотни) столбцов в существующей таблице базы данных и создать табличное представление, которое связано с базой данных с соответствующими типу виджетами в ячейках таблицы для изменения данных?
Я понимаю, что раньше это было очень просто, благодаря мастеру подключения к базе данных Qt Designer, но теперь он устарел.
1 ответ:
Самым простым способом, как было сказано, является использование
QSqlTableModel
. Предположим, что мы хотим:
- просмотр данных и переключение между таблицами
- редактирование данных с помощью соответствующих редакторов, например QSpinBox для целых чисел
- вставить строки
- и удалить строки
Хорошо, сначала нам нужно получить список всех таблиц в базе данных. Это может быть достигнуто с помощью метода
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())
Теперь мы уже можем переключаться между таблицы базы данных и редактировать данные. Но редактор по умолчанию -
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)
Также в главном окне мы должны создать и подключить делегат с combobox для обновления имени таблицы:
Класс Главное Окно (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)
И последний шаг-реализация функций
insert
иdelete
: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)