2017-10-04 110 views
1

使用PySide/Qt的QSqlTableModel是否有一种将数据库列转换为Python列表的快捷方式?例如,在R中,这将是一行简短的代码。现在,我手动遍历行Python中,这似乎是一种高级语言累赘:使用PySide将数据库列转换为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 

回答

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())]) 
+0

谢谢。只有绑定到GUI元素时才使用模型? – davideps

+0

@davideps。不,但它不像查询那么轻,所以每次调用函数时创建一个似乎效率低下。如果我打算使用模型进行查询,我会继承'QSqlTableModel'并添加一些方法(比如添加到我的答案中的通用'fetchall')。 – ekhumoro

+0

@davideps。我添加了一个使用模型进行查询的例子,以及列表理解来提取列值。有可能有很多方法来剥皮这个特殊的猫... – ekhumoro

1

的PySide对于C++中的所有Qt方法,层对于接近1比1。下面给出一些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"]) 

希望有所帮助。

+0

使用query.next()的例子很有帮助。谢谢。 – davideps