2017-10-04 109 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