QTableView和自定义ORM

时间:2011-11-29 17:35:51

标签: qt qt4 pyqt pyqt4

您是否有任何想法,示例如何将QTableView与使用Python编写的自定义ORM(例如Web2Py DAL)一起使用。

所以我有一个查询结果和描述该结果中列的属性的字段:

ID (int)  Name (str)
1         Lisa
2         Maria

我想创建一个可以绑定到ResultSetModel的课程QTableView。我可以拥有这个类的许多对象,每个对象都有自己的查询 - 比如QSqlQueryModel。但QSqlQueryModel处理Qt中的SQL基础结构,但我有自己的ORM来处理数据库。

谢谢

更新:

假设我有一张包含很多行的表格。我不想要求所有这些并将它们保存在模型中。当用户向下或向上滚动视图时,我需要一个与QTableView一起工作的模型,用于请求下一个或上一个记录。

QAbstractItemModel.fetchMore很有趣,但没有做我想要的。

您可以在examples/itemviews/fetchmore.py中看到“获取更多”示例。向下滚动到最后,它会请求额外的数据部分,但也会保留旧记录。滚动时它不会这样做。

想象一下,我在人员表中有数百万人。我想请求并在模型/内存中保留视图中显示的记录。

我想要实现的目标如下所示:http://www.youtube.com/watch?v=hQlE0rrr7wI

即。一旦显示视图,底层模型就会根据需要在屏幕上显示尽可能多的行。向下/向上滚动时 - 从DB逐步请求其他行。

1 个答案:

答案 0 :(得分:1)

这是一个使用elixir和pyside的工作示例。某处应该有session.commit()(点击“保存”按钮或类似的东西)。除此之外,它功能齐全

from elixir import *
from PySide import QtGui, QtCore
import operator, sys

class ColumnDescriptor(object):
    #This holds properties, controlling how each field looks/behaves in GUI"""
    def __init__(self, field_id):
        self.id = field_id
        self.verbose_name = self.id.capitalize().replace('_', ' ')
        self.comment = None

class Person(Entity): #ORM entity class
    #ORM entity fields
    id_number = Field(Integer)
    name = Field(Unicode(50))

    def __init__(self, name, id_number):
        self.name = name
        self.id_number = id_number

class PersonView():

    columns = []

    col = ColumnDescriptor('id_number')
    col.comment = "Person's identification code"
    columns.append(col)

    col = ColumnDescriptor('name')
    col.verbose_name = 'Full name'
    col.comment = "Person's full name"
    columns.append(col)

    def __init__(self):
        self.total_records = Person.query.count()

    def get_items(self, limit, offset = 0):
        return Person.query.offset(offset).limit(limit).all()


class TableModel(QtCore.QAbstractTableModel):

    #A one-size-fits-all model based on a view descriptor

    numberPopulated = QtCore.Signal(int)

    def __init__(self, view, editable = False, limit = 50):
        super(TableModel, self).__init__()
        self.view = view
        self.editable = editable
        self.current_page = 1
        self.items_per_page = limit
        self.items = view.get_items(self.items_per_page)

    def columnCount(self, index):
        return len(self.view.columns)

    def rowCount(self, index):
        return len(self.items)

    def loadPage(self):

        self.beginResetModel()
        self.items = []
        self.endResetModel()

        self.items = self.view.get_items(self.items_per_page,
            self.current_page * self.items_per_page)

        self.beginInsertRows(QtCore.QModelIndex(), 0, len(self.items))
        self.endInsertRows()
        self.numberPopulated.emit(len(self.items))

    def prevPage(self):
        self.current_page = self.current_page - 1
        self.loadPage()

    def nextPage(self):
        self.current_page = self.current_page + 1
        self.loadPage()

    def headerData(self, column, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return self.view.columns[column].verbose_name

    def data(self, index, role):
        if index.isValid():
            if (role == QtCore.Qt.DisplayRole) or (role == QtCore.Qt.EditRole):
                field_name = self.view.columns[index.column()].id
                value = self.items[index.row()].__getattribute__(field_name)
                if value:
                    return unicode(value)
                else:
                    return ''

    def flags(self, index):
        if not index.isValid():
            return QtCore.Qt.ItemIsEnabled
        else:
            if self.editable:
                return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
            else:
                return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

class MyWindow(QtGui.QWidget):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.layout = QtGui.QVBoxLayout(self)

        self.grid = QtGui.QTableView(self)
        self.grid.setModel(TableModel(PersonView(), True))

        self.layout.addWidget(self.grid)
        self.layoutButtons = QtGui.QHBoxLayout(self)
        self.layout.addLayout(self.layoutButtons)

        self.btnPrevious = QtGui.QPushButton("Previous", self)
        self.btnNext = QtGui.QPushButton("Next",self)
        self.layoutButtons.addWidget(self.btnPrevious)
        self.layoutButtons.addWidget(self.btnNext)

        self.btnPrevious.clicked.connect(self.grid.model().prevPage)
        self.btnNext.clicked.connect(self.grid.model().nextPage)


if __name__ == "__main__":

    metadata.bind = "sqlite:///persons.sqlite"
    setup_all(True)

    #fill the table up, if empty
    if not Person.query.all():
        for n in range(1,1000):
            p = Person(u'Person', n)

        session.commit()

    app = QtGui.QApplication(sys.argv)
    win = MyWindow()
    win.show()
    app.exec_()