IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

Lire les données d'une table pour les récupérer dans une combobox [QtSql]


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti Avatar de FolDeDol
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Transports

    Informations forums :
    Inscription : Novembre 2013
    Messages : 32
    Par défaut Lire les données d'une table pour les récupérer dans une combobox
    Bonsoir à toutes et à tous,

    J'essaye de me familiariser avec PyQt et je rencontre quelques problèmes...
    J'ai conçu un petit script (ci-dessous) qui affiche les données d'une liste dans une combobox.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    import sys
    from Lecture_Consommable import *
     
    class Element(QtGui.QDialog):
        def __init__ (self, parent = None) :
            QtGui.QWidget.__init__(self, parent)
            self.ui = Ui_Dialog()
            self.ui.setupUi(self)
            self.liste =['Ordinateur Portable', 'Imprimante', 'Ecran Plat', 'Disque Dur']
            self.formulaire()
     
        def formulaire(self):
            for i in self.liste:
                self.ui.comboBox.addItem(i)
     
    if __name__=="__main__":
        app = QtGui.QApplication(sys.argv)
        myapp = Element()
        myapp.show()
        sys.exit(app.exec_())
    J'essaye d'étendre ce script pour lire les données d'une table, les ajouter dans une liste et les récupérer dans la combobox.

    J'ai du mal à aborder la documentation de PyQt mais je pense avoir réussi à établir la connexion avec la base de données. Je bloque toutefois sur la syntaxe pour exécuter la requête "SELECT nom_consommable FROM consommable" dans ma fonction Formulaire. Je n'arrive pas non plus à déterminer si je dois "créer" un curseur pour lire les données ou s'il existe une méthode déjà existante sous PyQt.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    import sys
    from Lecture_Consommable import *
    from PyQt4 import QtSql, QtGui
     
     
    def Connection():
        db = QtSql.QSqlDatabase.addDatabase('QPSQL')
        db.setHostName('localhost')
        db.setDatabaseName('*****')
        db.setUserName('postgres')
        db.setPassword('*****')
        db.open()
     
    class Element(QtGui.QDialog):
        def __init__ (self, parent = None) :
            QtGui.QWidget.__init__(self, parent)
            self.ui = Ui_Dialog()
            self.ui.setupUi(self)
            self.liste =['Ordinateur Portable', 'Imprimante', 'Ecran Plat', 'Disque Dur']
            self.formulaire()
     
        def formulaire(self):
            for i in self.liste:
                self.ui.comboBox.addItem(i)
     
    if __name__=="__main__":
        app = QtGui.QApplication(sys.argv)
        myapp = Element()
        myapp.show()
        sys.exit(app.exec_())
    Si quelqu'un peut me proposer une idée ou rectifier la mienne, je suis preneur.

    @+

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Voilà un petit code de principe en console (Python 3, PyQt4) qui extrait des données d'une base sous sqlite3:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 3, PyQt4
     
    import sys
     
    from PyQt4 import QtCore, QtSql
     
    #============================================================================
    # initialisation de la  bibliothèque graphique pour une application en console
    app = QtCore.QCoreApplication(sys.argv)
     
    #============================================================================
    # base de données sqlite3
    basesql = "mabase.db3"
     
    #============================================================================
    # tentative d'ouverture de la base avec le pilote de sqlite3
    cnx = QtSql.QSqlDatabase.addDatabase(u"QSQLITE")
    cnx.setDatabaseName(basesql)
    if not cnx.open():
        print("Erreur d'ouverture de la base de données")
        app.quit()
        sys.exit()
     
    #============================================================================
    # exécution d'une requête
     
    # obtention d'un curseur
    query = QtSql.QSqlQuery(cnx)
     
    # préparation de la requête d'extraction
    req = """
    SELECT nations.nation
    from nations
    """
    # tentative d'exécution de la requête
    ok = query.exec_(req)
    if not ok:
        print("Erreur d'exécution de la requête")
        app.quit()
        sys.exit()
     
    # récupération des données
    R = []
    while query.next():
        R.append([])  # nouvelle ligne
        j = 0
        while query.value(j):
            # ajout d'une donnée sur la ligne
            R[-1].append(query.value(j))
            j += 1
     
    # désactivation du curseur (effacement des données et libération ressources)
    query.clear()
     
    #============================================================================
    # fermeture de la base
    cnx.close()
     
    #============================================================================
    # affichage du résultat
    for ligne in R:
        print(ligne)
    A adapter à ton contexte!

    Pour des requêtes avec transactions, c'est un peu plus complexe, mais ça marche aussi.

    Pourtant, dans mes logiciels, je n'utilise le pilote de Qt4 que s'il y a du graphique (visualisation directe dans des widgets comme QTableView avec modèles). Dans tous les autres cas, comme le tien, j'utilise le pilote de Python, qui me semble plus pratique à utiliser. Je n'ai rencontré aucun inconvénient à utiliser les 2 pilotes Python et Qt4 dans un même programme, à condition qu'ils ne soient pas actifs en même temps.

  3. #3
    Rédacteur/Modérateur

    Avatar de Jiyuu
    Homme Profil pro
    Développeur amateur
    Inscrit en
    Janvier 2007
    Messages
    2 456
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur amateur
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 456
    Billets dans le blog
    15
    Par défaut


    La solution de Tyrtamos doit bien convenir à ton besoin, c'est d'ailleurs une solution similaire que j'utilisais avant d'être lassé de me demander systématiquement à quelle position dans la liste était l'information que je cherchais... Pour palier à ceci l'astuce consiste à passer par un dictionnaire qui sera, pour une ligne donnée, de la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dic = {"titre_col1":"val_col1", "titre_coln":"val_coln"}
    Pour cela tu as au moins deux façons de faire.

    Méthode 1 :
    Dans ton code tu ajoutes une liste qui correspondra à chaque champs de ta BDD et tu t'en sers pour créer ton dictionnaire.

    Méthode 2 :
    Tu passe par la fonction SQL PRAGMA qui te permettra de récupérer les entêtes des colonnes.
    J'ai un exemple ici . C'est du QML (Qt Déclaratif) mais la requête SQL devrait te guider.

    Il existe peut-être une chose similaire avec QSqlQuery, mais je n'en suis pas sûr.

    @+

    J
    Initiation à Qt Quick et QML : Partie 1 - Partie 2
    En cas de besoin, pensez à la
    Mon site et mes tutoriaux sur Developpez.com
    Pas de question technique par MP... Les forums sont là pour ça

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour Jiyuu,

    J'ai déjà utilisé cela, mais tant qu'à faire, il faut utiliser un dictionnaire ordonné (OrderedDict du module collections): en conservant l'ordre initial des champs, cela permet à tout moment de refabriquer une liste pour, par exemple, créer un fichier csv destiné à Excel.

  5. #5
    Membre averti Avatar de FolDeDol
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Transports

    Informations forums :
    Inscription : Novembre 2013
    Messages : 32
    Par défaut
    Bonjour,

    Merci pour vos réponses.

    @Tyrtamos : J'ai légèrement adapté ton code pour le tester. Celui-ci fonctionne mais... je me retrouve avec une erreur (voir ci-dessous). Je n'ai malheureusement pas encore eu trop le temps de chercher et approfondir cette erreur.
    D'après ce que j'en déduis, il va falloir que je trouve un moyen de compter le nombre de colonnes dans la table pour définir une limite dans la boucle Python. Peut-être que je me trompe ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    QPSQLResult::data: column 1 out of range
    ['Ordinateur Portable']
    ['Imprimante']
    ['Ecran Plat']
    ['Disque Dur']
    QPSQLResult::data: column 1 out of range
    QPSQLResult::data: column 1 out of range
    QPSQLResult::data: column 1 out of range
    @Jiyuu : merci pour les informations, il va me falloir un peu de temps pour les digérer
    Il me reste beaucoup de travail pour assimiler Python et PyQt... mais je ne désespère pas.

    @+

  6. #6
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    J'avais essayé mon code avant, et il fonctionnait sans erreur dans mon contexte (sqlite3). Cependant, en épluchant la doc, je m'aperçois que les différents SGBDR ne donnent pas forcément le même résultat aux mêmes requêtes.

    Voilà une astuce permettant de calculer le nombre de colonnes d'une table (cnx étant une connexion ouverte):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    table = "nomdelatable"
    query = QtSql.QSqlQuery("SELECT * FROM %s;" % (table,), cnx)
    rec = query.record()
    print(rec.count())
    Il n'y a apparemment aucun moyen de récupérer les noms des champs. Mais si on les a par ailleurs, on peut calculer leurs index avec query.record().indexOf("nomduchamp")

    Bizarrement, il est déconseillé d'utiliser un "SELECT * FROM table" parce que les champs renvoyés ne sont pas forcément dans le bon ordre.

    Dans le code que j'ai proposé, query.next() permet d'accéder à la ligne suivante de la table, et pour une même ligne, query.value(j) permet d'accéder au champ d'index j. Cet index j commence à 0 pour aller jusqu'à ce qu'il soit trop grand.

    Pour l'erreur que tu as trouvé, je te suggère de regarder ce que renvoie query.value(j) pour un index j qui dépasse le nombre de champ. Chez moi, ça renvoie None. Si c'est ça aussi chez toi, on peut essayer le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    R = []
    while query.next():
        R.append([])  # nouvelle ligne
        j = 0
        while True:
            val = query.value(j) # valeur du champ d'index j
            if val == None:
                break # l'index dépasse le nombre de champs demandés dans la requête 
            # ajout d'une donnée sur la ligne
            R[-1].append(val)
            j += 1
    Si chez toi query.value(j) pour j trop grand donne un autre résultat (une exception?), il faut modifier le code en conséquence.

    Attention: les index permis sont seulement ceux qui correspondent au résultat de la requête: si on demande 2 champs comme dans "SELECT nom, prenom FROM annuaire", les index permis sont seulement 0 et 1.

    Il y a peut-être encore d'autres subtilités à lire dans la doc et spécifiques à ton SGBDR!

    Sincèrement, ça me conforte dans ce que je fais: je n'utilise jamais ce code Qt s'il n'y a pas de graphique! Je préfère nettement le pilote Python.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Récupérer des noms de fichier dans une table pour les placer en masque du tfilelist
    Par charliplanete dans le forum Développement de jobs
    Réponses: 11
    Dernier message: 24/08/2011, 17h16
  2. Réponses: 62
    Dernier message: 16/04/2009, 10h09
  3. Réponses: 1
    Dernier message: 28/08/2008, 22h53
  4. Remplir une table avec les données d'autres tables
    Par Beltegeuse dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 09/04/2008, 12h00
  5. Réponses: 3
    Dernier message: 13/06/2007, 17h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo