2017-10-04 4 views
1

En utilisant QSqlTableModel de PySide/Qt, existe-t-il un moyen rapide et élégant de transformer une colonne de base de données en une liste Python? Dans R, par exemple, ce serait une ligne de code courte. En ce moment, je suis en boucle manuellement sur les lignes en Python, ce qui semble lourd pour un langage de haut niveau:Transformez la colonne de base de données en liste Python en utilisant PySide?

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 

Répondre

1

Il n'y a pas besoin de créer un modèle juste pour obtenir un ensemble de valeurs. Il est beaucoup plus simple et efficace d'utiliser une requête pour obtenir les valeurs. Cela ne vous donnera pas un one-liner - mais l'une des principales forces de Python est sa lisibilité, pas sa brièveté.

L'exemple ci-dessous pourrait facilement être adapté pour créer une fonction générique qui a une chaîne de requête et retourne une liste (ou iterator) des valeurs:

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())) 

EDIT:

Voici une fonction générique fetchall (semblable à cursor.fetchall dans le sqlite3 module de python). Ma mise en œuvre de cela prend soit une chaîne de requête ou un objet QSqlQuery actif, et retourne soit une liste de valeurs (pour une colonne) ou un tuple de valeurs (pour plusieurs colonnes):

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')) 

Cela pourrait également être mis en œuvre en tant que générateur, ce qui serait plus approprié pour de très grands ensembles de résultats.

EDIT2:

Si vous utilisez un modèle pour effectuer des requêtes puis, une fois les lignes ont été sélectionnées, vous pouvez utiliser une compréhension de la liste pour retirer les valeurs de la colonne:

model = QSqlTableModel() 
model.setTable('colors') 
model.select() 

# one liner ... 

print([model.index(i, 1).data() for i in range(model.rowCount())]) 
+0

Merci. Un modèle est-il utilisé uniquement lorsqu'il est lié à un élément de l'interface graphique? – davideps

+0

@davideps. Non. Mais ce n'est pas aussi léger qu'une requête, il semble donc inefficace d'en créer un chaque fois que vous appelez une fonction. Si j'allais utiliser un modèle pour interroger, je sous-classerais 'QSqlTableModel' et j'ajouterais quelques méthodes (comme le' fetchall 'générique que j'ai ajouté à ma réponse). – ekhumoro

+0

@davideps. J'ai ajouté un exemple qui utilise un modèle pour l'interrogation, et une compréhension de liste pour extraire les valeurs de la colonne. Il y a probablement des douzaines de manières d'habiller ce chat particulier ... – ekhumoro

1

Le PySide couche est presque 1 à 1 pour toutes les méthodes Qt en C++. Du code C++ est donné ci-dessous. Parce que la couche Qt Sql est abstraite pour le type de base de données backend, et orientée vers les interfaces Gui sur une boucle d'événement, elle n'a pas les mêmes liners disponibles que R ou d'autres langages peuvent avoir. Bien que vous pouvez le faire en quelques lignes.

De même, les méthodes de traitement des erreurs de Qt pour SQL consistent généralement à interroger la dernière erreur ou à rechercher le retour du exec ou de l'appel open. Les tuples ne sont pas natifs en C++, donc l'interface python n'utilise pas beaucoup de tuples.

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; 
} 

autre syntaxe spécifiant la requête

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); 
} 

La véritable puissance de l'interface Sql de Qt réside dans la facilité avec laquelle il est possible de créer une interface graphique pour représenter une base de données dans presque toutes les configurations auxquelles vous pouvez penser, et comment elle est extraite du moteur de base de données.

Même avec tout ce que dit sur la façon dont il gère Qt est appelle SQL ... il est toujours à égalité avec d'autres bibliothèques Python pour interagir avec des bases de données:

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"]) 

espoir qui aide.

+0

L'exemple using query.next() est utile. Je vous remercie. – davideps