0

我决定使用和学习 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;

我是在这个网站上发布的新手,对帮助中心的快速回顾并没有为我提供解决方案。

4

0 回答 0