【问题标题】:Turn database column into Python list using PySide?使用 PySide 将数据库列转换为 Python 列表?
【发布时间】:2017-10-04 13:44:32
【问题描述】:

使用 PySide/Qt 的 QSqlTableModel 是否有一种快速、优雅的方式将数据库列转换为 Python 列表?例如,在 R 中,这将是一个简短的代码行。现在,我在 Python 中手动循环遍历行,这对于高级语言来说似乎很麻烦:

def get_value_idx(value):
    model = QSqlTableModel()
    model.setTable("pvalues")
    model.setFilter("val = '%s'" % (value))
    model.select()
    count = model.rowCount()
    if count >= 1:
        l = list()
        for n in range(count):
            id = model.record(n).value('id')
            l.append(id)
        return l  # return id list
    if count == 0:
        return -1 # return id that shows error

【问题讨论】:

    标签: python qt pyside qsqltablemodel


    【解决方案1】:

    没有必要仅仅为了获取一组值而创建模型。使用查询来获取值更简单、更有效。这不会给你一个单一的线条 - 但 Python 的主要优势之一是它的可读性,而不是它的简洁性。

    下面的例子可以很容易地适应创建一个通用函数,它接受一个查询字符串并返回一个值列表(或迭代器):

    from PySide.QtSql import *
    
    db = QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName(':memory:')
    db.open()
    db.transaction()
    db.exec_('CREATE TABLE colors (id INTEGER PRIMARY KEY, color TEXT NOT NULL)')
    db.exec_("INSERT INTO colors VALUES(1, 'Red')")
    db.exec_("INSERT INTO colors VALUES(2, 'Blue')")
    db.exec_("INSERT INTO colors VALUES(3, 'Green')")
    db.exec_("INSERT INTO colors VALUES(4, 'Yellow')")
    db.commit()
    
    def list_colors():
        colors = []
        query = QSqlQuery('SELECT color FROM colors')
        while query.next():
            colors.append(query.value(0))
        return colors
    
    print(list_colors())    
    
    # or use a generator function:
    
    def generate_colors():
        query = QSqlQuery('SELECT color FROM colors')
        while query.next():
            yield query.value(0)
    
    print(list(generate_colors()))
    

    编辑

    这是一个通用的fetchall 函数(类似于python 的sqlite3 module 中的cursor.fetchall)。我的实现采用查询字符串或活动QSqlQuery 对象,并返回值列表(对于一列)或值元组(对于多列):

    def fetchall(query):
        if isinstance(query, str):
            query = QSqlQuery(query)
        result = []
        count = query.record().count()
        indexes = range(count)
        while query.next():
            if count == 1:
                result.append(query.value(0))
            else:
                result.append(tuple(query.value(i) for i in indexes))
        return result
    
    # one liner ...
    
    print(fetchall('SELECT color FROM colors'))
    

    这也可以实现为生成器,这将更适合非常大的结果集。

    EDIT2

    如果您使用模型进行查询,那么一旦选择了行,您就可以使用列表推导来提取列值:

    model = QSqlTableModel()
    model.setTable('colors')
    model.select()
    
    # one liner ...
    
    print([model.index(i, 1).data() for i in range(model.rowCount())])
    

    【讨论】:

    • 谢谢。模型是否仅在绑定到 GUI 元素时使用?
    • @davideps。不,但它不像查询那样轻量级,因此每次调用函数时都创建一个似乎效率低下。如果我要使用模型进行查询,我会继承 QSqlTableModel 并添加一些方法(比如我添加到我的答案中的通用 fetchall)。
    • @davideps。我添加了一个示例,该示例使用模型进行查询,并使用列表理解来提取列值。可能有几十种方法可以给这只猫剥皮……
    • 需要添加:while model.canFetchMore(): model.fetchMore() 来获取全表。
    【解决方案2】:

    对于 C++ 中的所有 Qt 方法,PySide 层几乎是一对一的。下面给出了一些 C++ 代码。

    因为 Qt Sql 层是针对后端数据库类型进行抽象的,并且面向事件循环上的 Gui 接口,所以它没有 R 或其他语言可能拥有的相同的可用衬里。虽然你可以在几行内完成。

    另外,Qt 对 SQL 的错误处理方法通常是通过查询最后一个错误或查看execopen 调用的返回。元组在 C++ 中不是原生的,因此 python 接口不会大量使用元组。

    http://doc.qt.io/qt-4.8/sql-sqlstatements.html

    http://doc.qt.io/qt-4.8/qsqltablemodel.html#details

     QSqlTableModel model;
     model.setTable("employee");
     model.setFilter("salary > 50000");
     model.setSort(2, Qt::DescendingOrder);
     model.select();
    
     for (int i = 0; i < model.rowCount(); ++i) {
         QString name = model.record(i).value("name").toString();
         int salary = model.record(i).value("salary").toInt();
         qDebug() << name << salary;
     }
    

    指定查询的替代语法

    QSqlQueryModel model;
    model.setQuery("SELECT * FROM employee");
    int salary = model.record(4).value("salary").toInt();
    

    http://doc.qt.io/qt-4.8/qsqlresult.html#size

    QSqlQuery query("SELECT country FROM artist");
    while (query.next()) {
        QString country = query.value(0).toString();
        doSomething(country);
    }
    

    Qt 的 Sql 接口的真正强大之处在于它可以很容易地制作一个 GUI 来以您能想到的几乎任何类型的配置来表示数据库,以及它是如何从数据库引擎中抽象出来的。

    即使说了这么多关于 Qt 如何处理它的 SQL 调用......它仍然与其他用于与数据库交互的 Python 库相提并论:

    How to retrieve SQL result column value using column name in Python?

    cursor = conn.cursor(MySQLdb.cursors.DictCursor)
    cursor.execute("SELECT name, category FROM animal")
    result_set = cursor.fetchall()
    for row in result_set:
        print "%s, %s" % (row["name"], row["category"])
    

    希望对您有所帮助。

    【讨论】:

    • 使用 query.next() 的示例很有帮助。谢谢。
    猜你喜欢
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    相关资源
    最近更新 更多