Как связать редактируемый QComboBox с базой данных
Я использую Pyside для создания комбинированного списка, который рисует из базы данных sqlite. Пользователи могут выбрать один из существующих элементов или добавить новый элемент. Пользователи видят названия элементов (называемые "param"), но мне нужен доступ к идентификаторам элементов из базы данных. Итак, есть два шага:
ЧТЕНИЕ ЭЛЕМЕНТОВ: я могу читать из базы данных, но не могу отображать имена элементов при доступе к идентификаторам элементов за кулисами.
ДОБАВЛЕНИЕ ПУНКТОВ: Нужно ли обнаруживать изменение в выпадающем списке, а затем использовать команду вставки SQL или модель справляется с этим для меня?
Этот код читает из базы данных, но не отображается правильно:
param_model = QSqlQueryModel()
param_model.setQuery("select id, param from partable order by param")
param_model.setHeaderData(0, Qt.Horizontal,"id")
param_model.setHeaderData(1, Qt.Horizontal,"param")
param_view = QTableView()
param_view.setColumnHidden(0,True)
self.paramfield = QComboBox()
self.paramfield.adjustSize()
self.paramfield.setEditable(True)
self.paramfield.setModel(param_model)
self.paramfield.setView(param_view)
1 ответ
Есть несколько проблем с вашим кодом. Во-первых, вам нужно использовать QSqlTableModel
, который является редактируемым, а не QSqlQueryModel
, который только для чтения. Во-вторых, вам не нужно устанавливать заголовки или представление в поле со списком. В-третьих, вы должны установить правильный столбец модели в поле со списком, чтобы отобразить соответствующие значения.
На вопрос о добавлении пунктов: необходимо только внести изменения через модель. Однако также часто желательно найти идентификатор или индекс элемента, который был добавлен (например, для сброса текущего индекса). Это может быть немного сложнее, если модель отсортирована и / или допускает дублирование записей.
Демонстрационный скрипт ниже показывает вам, как справиться со всеми проблемами, упомянутыми выше:
import sys
from PySide import QtCore, QtGui, QtSql
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
self.db.setDatabaseName(':memory:')
self.db.open()
self.db.transaction()
self.db.exec_(
'CREATE TABLE partable'
'(id INTEGER PRIMARY KEY, param TEXT NOT NULL)'
)
self.db.exec_("INSERT INTO partable VALUES(1, 'Red')")
self.db.exec_("INSERT INTO partable VALUES(2, 'Blue')")
self.db.exec_("INSERT INTO partable VALUES(3, 'Green')")
self.db.exec_("INSERT INTO partable VALUES(4, 'Yellow')")
self.db.commit()
model = QtSql.QSqlTableModel(self)
model.setTable('partable')
column = model.fieldIndex('param')
model.setSort(column, QtCore.Qt.AscendingOrder)
model.select()
self.combo = QtGui.QComboBox(self)
self.combo.setEditable(True)
self.combo.setModel(model)
self.combo.setModelColumn(column)
self.combo.lineEdit().returnPressed.connect(self.handleComboEdit)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.combo)
def handleComboEdit(self):
if self.combo.lineEdit().isModified():
model = self.combo.model()
model.submitAll()
ID = model.query().lastInsertId()
if ID is not None:
index = model.match(
model.index(0, model.fieldIndex('id')),
QtCore.Qt.EditRole, ID, 1, QtCore.Qt.MatchExactly)[0]
self.combo.setCurrentIndex(index.row())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(800, 50, 200, 50)
window.show()
sys.exit(app.exec_())
PS: вот как получить id
из поля со списком, используя его текущий индекс:
model = self.combo.model()
index = self.combo.currentIndex()
ID = model.index(index, model.fieldIndex('id')).data()