使用PySide2.QtSql.QSqlRelationalTableModel()

问题描述 投票:0回答:1

我决定使用和学习Qt本机QtSql类。使用QSqlQuery()很简单,很像SqlAlchemy。

我尝试使用QTableView / Model方法,但是成功非常有限。

我的参考文档是“使用Python和Qt进行快速GUI编程”,但仍然可用。

经过大量的实验,我部分成功了,但是我当前的问题有点困惑,并且我当前的Web搜索没有帮助(到目前为止)

该表单显示前两个记录所请求的信息,但不显示随后的记录(后两个)的信息。数据库中有四个记录。

数据库故障

主表“ tblRecipe”包含键,配方名称,类别和说明支持表“ tblIngrediants”包含一种到多种配方成分:字段为:“ ingrediantKey”,“ ingrediantDescription”,“ ingrediantRecipeKey”,“ ingrediantQuantity”查找表的最终表将“ tblRecipe”中的类别整数更改为人类可读的文本。我尚未尝试合并此表。

问题:为什么我要获得前2条记录的正确信息而不是后2条的正确信息。

我已经包含了与我的问题有关的部分代码。声明我的小部件的代码

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)

声明模型和视图的代码

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()

该函数的代码:self.displayIngred()

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 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, "Phone Log",
                        "Database Error: {}".format(db.lastError().text()))
    sys.exit(1)

form = RecipeDlg()
form.show()
sys.exit(app.exec_())

结果图像:

记录1

“”

记录4,但没有出现成分

“”


最小的可复制示例:应用程序有204行,将消除布局定义,并且不重要的函数将仅具有Pass占位符。

import os


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()
    ... eliminated
    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()
python pyside2 qsqlrelationaltablemodel
1个回答
0
投票

最小的可复制示例:应用程序有204行,将消除布局定义,并且不重要的函数将仅具有Pass占位符。

import os


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()
    ... eliminated
    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()
© www.soinside.com 2019 - 2024. All rights reserved.