我决定使用和学习 Qt 原生的 QtSql 类。使用 QSqlQuery() 很简单,很像 SqlAlchemy。
我尝试使用 QTableView/Model 方法,但成功非常有限。
我的参考文档是“Rapid GUI Programming with Python and Qt”一本旧书,但仍然可用。
经过多次实验,我部分成功了,但我目前的问题有点令人困惑,我目前的网络搜索没有帮助(迄今为止)
该表单显示前两条记录的信息,但不显示后续记录(最后两条)的信息。数据库中有四条记录。
数据库的分解
主表“tblRecipe”包含密钥、配方名称、类别和描述支持表“tblIngrediants”包含配方的一对多成分:字段为:“ingrediantKey”、“ingrediantDescription”、“ingrediantRecipeKey”、“ingrediantQuantity”最终表到查找表以将“tblRecipe”中的类别整数更改为人类可读的文本。我还没有尝试合并这个表。
问题:为什么我得到前 2 条记录的正确信息,而不是后 2 条记录。
我已经包含了与我的问题相关的部分代码。
import os
import sys
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtSql import *
from PySide2.QtWidgets import *
import qrc_resources
RECIPEKEY, RECIPENAME, RECIPECATEGORY, RECIPEDESCRIPTION = range(4)
INGREDIANTKEY, INGREDIANTDESCRIPTION, INGREDIANTRECIPEKEY, INGREDIANTQUANTITY = range(4)
class RecipeDlg(QDialog):
FIRST, PREV, NEXT, LAST = range(4)
def __init__(self, parent=None):
super(RecipeDlg, self).__init__(parent)
catLabel = QLabel("Category:")
self.catEdit = QLineEdit()
catLabel.setBuddy(self.catEdit)
nameLabel = QLabel("Name:")
self.nameEdit = QLineEdit()
nameLabel.setBuddy(self.nameEdit)
IngrediantLabel = QLabel("Ingrediants:")
self.tvIngrediants = QTableView()
descriptionLabel = QLabel("Description:")
self.descriptionEdit = QTextEdit()
descriptionLabel.setBuddy(self.descriptionEdit)
firstButton = QPushButton()
firstButton.setIcon(QIcon(":/first.png"))
prevButton = QPushButton()
prevButton.setIcon(QIcon(":/prev.png"))
nextButton = QPushButton()
nextButton.setIcon(QIcon(":/next.png"))
lastButton = QPushButton()
lastButton.setIcon(QIcon(":/last.png"))
addButton = QPushButton("&Add")
addButton.setIcon(QIcon(":/add.png"))
deleteButton = QPushButton("&Delete")
deleteButton.setIcon(QIcon(":/delete.png"))
quitButton = QPushButton("&Quit")
quitButton.setIcon(QIcon(":/quit.png"))
addButton.setFocusPolicy(Qt.NoFocus)
deleteButton.setFocusPolicy(Qt.NoFocus)
fieldLayout = QGridLayout()
fieldLayout.addWidget(catLabel, 0, 0)
fieldLayout.addWidget(self.catEdit, 0, 1, 1, 3)
fieldLayout.addWidget(nameLabel, 1, 0)
fieldLayout.addWidget(self.nameEdit, 1, 1)
fieldLayout.addWidget(IngrediantLabel, 2, 0)
fieldLayout.addWidget(self.tvIngrediants, 2, 1, 1, 3)
fieldLayout.addWidget(descriptionLabel, 3, 0)
fieldLayout.addWidget(self.descriptionEdit, 3, 1, 1, 3)
navigationLayout = QHBoxLayout()
navigationLayout.addWidget(firstButton)
navigationLayout.addWidget(prevButton)
navigationLayout.addWidget(nextButton)
navigationLayout.addWidget(lastButton)
fieldLayout.addLayout(navigationLayout, 4, 0, 1, 2)
buttonLayout = QVBoxLayout()
buttonLayout.addWidget(addButton)
buttonLayout.addWidget(deleteButton)
buttonLayout.addStretch()
buttonLayout.addWidget(quitButton)
layout = QHBoxLayout()
layout.addLayout(fieldLayout)
layout.addLayout(buttonLayout)
self.setLayout(layout)
self.model = QSqlTableModel(self)
self.model.setTable("tblRecipe")
self.model.setSort(RECIPECATEGORY, Qt.AscendingOrder)
self.model.select()
self.ingredModel = QSqlRelationalTableModel(self)
self.ingredModel.setTable("tblIngrediants")
self.ingredModel.setRelation(INGREDIANTKEY,
QSqlRelation("tblRecipe", "recipeKey", "recipeName"))
self.ingredModel.setHeaderData(INGREDIANTKEY, Qt.Horizontal, "id")
self.ingredModel.setHeaderData(INGREDIANTDESCRIPTION, Qt.Horizontal,
"Description")
self.ingredModel.setHeaderData(INGREDIANTQUANTITY, Qt.Horizontal, "Quantity")
self.ingredModel.select()
self.tvIngrediants.setModel(self.ingredModel) # connect to the model
self.tvIngrediants.setSelectionMode(QTableView.SingleSelection)
self.tvIngrediants.setSelectionBehavior(QTableView.SelectRows)
self.tvIngrediants.setColumnHidden(INGREDIANTKEY, True)
self.tvIngrediants.setColumnHidden(2, True)
self.tvIngrediants.resizeColumnsToContents()
self.mapper = QDataWidgetMapper(self)
self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
self.mapper.setModel(self.model)
self.mapper.setItemDelegate(QSqlRelationalDelegate(self))
self.mapper.addMapping(self.catEdit, RECIPECATEGORY)
self.mapper.addMapping(self.nameEdit, RECIPENAME)
self.mapper.addMapping(self.descriptionEdit, RECIPEDESCRIPTION)
#relationModel = self.ingredModel.relationModel(INGREDIANTRECIPEKEY)
#self.tvIngrediants.setModel(relationModel)
self.mapper.addMapping(self.tvIngrediants, INGREDIANTRECIPEKEY)
self.mapper.toFirst()
self.displayIngred()
firstButton.clicked.connect(lambda: self.saveRecord(RecipeDlg.FIRST))
prevButton.clicked.connect(lambda: self.saveRecord(RecipeDlg.PREV))
nextButton.clicked.connect(lambda: self.saveRecord(RecipeDlg.NEXT))
lastButton.clicked.connect(lambda: self.saveRecord(RecipeDlg.LAST))
#addButton.clicked.connect(self.addRecord)
#deleteButton.clicked.connect(self.deleteRecord)
quitButton.clicked.connect(self.accept)
self.setWindowTitle("Recipes")
def displayIngred(self):
index = self.mapper.currentIndex()
record = self.model.record(index)
id = record.value("recipeKey")
self.ingredModel.setFilter("ingrediantRecipeKey = {}".format(id))
self.ingredModel.select()
self.tvIngrediants.horizontalHeader().setVisible(
self.ingredModel.rowCount() > 0)
def reject(self):
self.accept()
def accept(self):
self.mapper.submit()
QDialog.accept(self)
def addRecord(self):
pass
def deleteRecord(self):
pass
def saveRecord(self, where):
row = self.mapper.currentIndex()
self.mapper.submit()
if where == RecipeDlg.FIRST:
row = 0
elif where == RecipeDlg.PREV:
row = 0 if row <= 1 else row - 1
elif where == RecipeDlg.NEXT:
row += 1
if row >= self.model.rowCount():
row = self.model.rowCount() - 1
elif where == RecipeDlg.LAST:
row = self.model.rowCount() - 1
self.mapper.setCurrentIndex(row)
self.displayIngred()
def main():
app = QApplication(sys.argv)
filename = os.path.join(os.path.dirname(__file__), "Recipes.db")
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(filename)
if not db.open():
QMessageBox.warning(None, "Recipes",
"Database Error: {}".format(db.lastError().text()))
sys.exit(1)
form = RecipeDlg()
form.show()
sys.exit(app.exec_())
main()
结果图片:
记录 1
记录4但成分没有出现
由于 StackOverflow 似乎不允许文件传输,我将包含我的 SQL 文本文件的内容
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS `tblRecipe` (
`recipeKey` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`recipeName` TEXT NOT NULL,
`recipeCategory` INTEGER NOT NULL,
`recipeDescription` TEXT,
FOREIGN KEY(`recipeCategory`) REFERENCES `tblCategory`(`categoryKey`)
);
CREATE TABLE IF NOT EXISTS `tblIngrediants` (
`ingrediantKey` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`ingrediantDescription` TEXT NOT NULL,
`ingrediantRecipeKey` INTEGER NOT NULL,
`ingrediantQuantity` TEXT,
FOREIGN KEY(`ingrediantRecipeKey`) REFERENCES `tblRecipe`(`recipeKey`)
);
CREATE TABLE IF NOT EXISTS `tblCategory` (
`categoryKey` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`categoryName` TEXT NOT NULL
);
COMMIT;
我是在这个网站上发布的新手,对帮助中心的快速回顾并没有为我提供解决方案。