【问题标题】:PyQt application with sqlalchemy database带有 sqlalchemy 数据库的 PyQt 应用程序
【发布时间】:2016-01-28 08:05:07
【问题描述】:

我尝试创建一个 PyQt 应用程序,并将数据存储到数据库中。我想使用 sqlachemy 访问我的数据并在 PyQt 中使用模型显示数据。

在这个例子中,我使用了一个组合框来显示我的数据。

我的代码“工作”很糟糕,因为每次我点击我的组合框时,模型都会检查数据库数千次,使其非常滞后。

执行此操作的“规范方法”是什么?

我在 Windows 下使用 Python 3.4 和 PyQt 4。我的 Python-Sqlalchemy-PyQt-english 水平很低。

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 

import sys
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base

from PyQt4 import QtCore, QtGui, uic

# My base structure

base = declarative_base()

class User(base):
    __tablename__ = "users"
    id_ = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)

    name = sqlalchemy.Column(sqlalchemy.String(20))

    def __repr__(self):
        return "<User(id='%s', name='%s')>" % (self.id_, self.name)

# Creating my base and my session
engine = sqlalchemy.create_engine("sqlite:///my_db.db")
base.metadata.create_all(engine)

DBsession = sqlalchemy.orm.sessionmaker(bind=engine)
session = DBsession()

# My model, i just want to show data
class UserListModel(QtCore.QAbstractListModel):

    def __init__(self, session, parent = None):
        QtCore.QAbstractListModel.__init__(self, parent)
        self.session = session

    def rowCount(self, parent):
        return len(get_users(self.session))

    def data(self, index, role):
        users = get_users(self.session)

        # Only for debug
        print(users)

        if role == QtCore.Qt.DisplayRole:
            value = users[index.row()]
            return "%s : %s" % (value.id_, value.name)

def add_user(session, tmp_name):
    session.add(User(name=tmp_name))
    session.commit()

def get_users(session):
    users = session.query(User).all()
    return users

# Populating my db
session.add(User(name="edouard"))
session.add(User(name="jean"))
session.add(User(name="albert"))
session.commit()

# Creating my app
app = QtGui.QApplication(sys.argv)
mywindow = QtGui.QWidget()

# Combobox and his model
combobox = QtGui.QComboBox(mywindow)
combobox.setModel(UserListModel(session))

mywindow.show()
sys.exit(app.exec_())

【问题讨论】:

    标签: python sqlalchemy pyqt pyqt4


    【解决方案1】:

    我已经对您的代码进行了一些改进,但我对 PyQt 并不熟悉,所以我确信这可以进一步改进。无论如何,经常调用数据库的一个原因是,每当 PyQt 想要重绘列表时,都会调用 UserListModel.data()。发生这种情况,例如关于组合框内的鼠标移动,所以我们真的不想每次调用 data() 都访问数据库。

    通过填充__init__()中的用户列表,我们缓存了数据库结果,避免了频繁的查询。这只会带您到此为止,因为您还必须在修改数据库内容时更新此缓存。所以当你添加或删除用户时,你还需要调用UserListModel.refresh()

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*- 
    
    import sys
    import sqlalchemy
    from sqlalchemy.ext.declarative import declarative_base
    
    from PyQt4 import QtCore, QtGui, uic
    
    # My base structure
    
    base = declarative_base()
    
    class User(base):
        __tablename__ = "users"
        id_ = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
    
        name = sqlalchemy.Column(sqlalchemy.String(20))
    
        def __repr__(self):
            return "<User(id='%s', name='%s')>" % (self.id_, self.name)
    
    # Creating my base and my session
    engine = sqlalchemy.create_engine("sqlite:///my_db.db", echo='debug')
    base.metadata.create_all(engine)
    
    DBsession = sqlalchemy.orm.sessionmaker(bind=engine)
    session = DBsession()
    
    # My model, i just want to show data
    class UserListModel(QtCore.QAbstractListModel):
    
        def __init__(self, session, parent = None):
            QtCore.QAbstractListModel.__init__(self, parent)
            self.session = session
            self.refresh()
    
        def refresh(self):
            self.users = self.session.query(User).all()
    
        def rowCount(self, parent):
            return len(self.users)
    
        def data(self, index, role):
            if role == QtCore.Qt.DisplayRole:
                value = self.users[index.row()]
                return "%s : %s" % (value.id_, value.name)
    
    def add_user(session, tmp_name):
        session.add(User(name=tmp_name))
        session.commit()
    
    # Populating my db
    if not session.query(User).count():
        session.add(User(name="edouard"))
        session.add(User(name="jean"))
        session.add(User(name="albert"))
        session.commit()
    
    # Creating my app
    app = QtGui.QApplication(sys.argv)
    mywindow = QtGui.QWidget()
    
    # Combobox and his model
    combobox = QtGui.QComboBox(mywindow)
    combobox.setModel(UserListModel(session))
    
    mywindow.show()
    sys.exit(app.exec_())
    

    【讨论】:

    • 谢谢。这更清楚,例如this here
    • So when you add or remove a user, you also need to call UserListModel.refresh()。我这样做了,但在我的示例中,除非我重新启动我的应用程序,否则日期不会更新...
    猜你喜欢
    • 1970-01-01
    • 2017-12-12
    • 2014-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多