QDataWidgetMapper-在pyqt中查找sqlite数据库行的索引
Posted
技术标签:
【中文标题】QDataWidgetMapper-在pyqt中查找sqlite数据库行的索引【英文标题】:QDataWidgetMapper-find index for sqlite database row in pyqt 【发布时间】:2016-05-25 03:45:16 【问题描述】:我想使用 QDataWidgetMapper 将小部件与 sqlite 表中的数据链接起来。我找到的用于指定数据行的方法似乎只有在一次一个地依次遍历行时才有效:setCurrentIndex、toFirst、toLast、toNext、toPrevious。我希望能够直接跳转到包含所需数据的行,并检索该行的句柄,然后传递给映射器。
表的主键是一个自增的整数,但是由于可以删除行,因此不能保证使用该键可以猜到索引。
-------------------------
| item_info |
|-----------------------|
|item_id | item_desc |
|---------|-------------|
|1 | item 1 |
|2 | item 2 |
|7 | blue item |
|15 | pink item | #ordered index is 3
-------------------------
我曾短暂希望能够使用 rowid 来返回表行的有序索引,但看起来它只返回主键,与行在表中的位置的概念无关。
我可以使用计数器遍历每一行,直到找到正确的行,然后使用生成的计数器值作为 setCurrentIndex 的参数,但这似乎是一个糟糕的解决方案。这是一个示例,显示 item_id 为 15 的行中的 item_desc:
import sys
from PyQt5 import Qt,QtWidgets,QtSql
class Form(QtWidgets.QWidget):
def __init__(self,parent=None):
QtWidgets.QWidget.__init__(self,parent)
self.line_edit=QtWidgets.QLineEdit()
layout=QtWidgets.QVBoxLayout()
layout.addWidget(self.line_edit)
self.setLayout(layout)
db=QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("populated_db.db")
db.open()
self.item_info_model = QtSql.QSqlTableModel(self)
self.item_info_model.setTable("item_info")
self.item_info_model.select()
self.item_info_mapper = Qt.QDataWidgetMapper(self)
self.item_info_mapper.setSubmitPolicy(Qt.QDataWidgetMapper.ManualSubmit)
self.item_info_mapper.setModel(self.item_info_model)
self.item_info_mapper.addMapping(self.line_edit, 1) #establishes mapping between line edit and the second column of data
self.show_description(15)
def show_description(self,desired_item_id):
###### NOW HERE IS AN UGLY TECHNIQUE TO SEARCH ONE BY ONE UNTIL DESIRED ROW IS DISCOVERED ######
i=0 #start counter
success=False
query=QtSql.QSqlQuery()
query.exec("SELECT item_id FROM item_info")
query.first()
while not success:
if query.value(0)==desired_item_id:
success=True
self.item_info_mapper.setCurrentIndex(i)
else:
i+=1
query.next()
a=QtWidgets.QApplication(sys.argv)
form=Form()
form.show()
a.exec_()
这完成了任务,但似乎应该有一种更好的方法来有效地使用数据库,用一些直接的方法来设置映射而不是数字索引。如果是这样的话,到目前为止我一直找不到它。
【问题讨论】:
【参考方案1】:您可以使用模型的record()
方法:
def show_description(self,desired_item_id):
for i in range(self.item_info_model.rowCount()):
if self.item_info_model.record(i).value(0) == desired_item_id: # the field can be defined by position or by name
self.item_info_mapper.setCurrentIndex(i)
break
您也可以为模型设置过滤器:
def show_description(self,desired_item_id):
self.item_info_model.setFilter('item_id = '.format(desired_item_id))
self.item_info_mapper.toFirst()
您的模型已被填充(由class Form()
中的self.item_info_model.select()
填充,因此将自动重新选择see documentation
【讨论】:
感谢您的回复。 record 方法删除了 SQL,但我真正的目标是能够使用单个语句选择所需的特定记录,返回的结果包含可以直接传递给映射器的信息。我希望完全避免使用计数器循环。在我看来,对于大型数据库而言,每次逐行爬行的循环会非常慢。 setFilter 看起来可能有一些承诺,我会尽快尝试。 从我目前看到的情况来看,setFilter 方法的执行与我希望的一样。使用记录方法看起来也比使用 SQL 查询更简洁,所以这是您添加到底池中的一个不错的奖励。非常感谢!以上是关于QDataWidgetMapper-在pyqt中查找sqlite数据库行的索引的主要内容,如果未能解决你的问题,请参考以下文章
QDataWidgetMapper 将多列映射到单个自定义小部件的多个属性