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 :

Créer une barre de recherche en PyQt5 sur une base de données PostgreSQL


Sujet :

PyQt Python

  1. #1
    Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2021
    Messages : 8
    Par défaut Créer une barre de recherche en PyQt5 sur une base de données PostgreSQL
    Bonjour à tous!

    Cela fait quelques jours que je tente de créer une barre de recherche en PyQt5 sur une base de données PostgreSQL.
    Plus précisément, je suis sous Mac et j'ai installé Postgres.app ainsi que Python 3.9 avec le package PyQt5.

    J'ai donc souhaité dans un premier temps créer une table "tabletest": creatableqt.py
    NB : la fonction config() à laquelle le code fait référence se trouve dans ce fichier config.py et le fichier database.ini est de la forme :
    [postgresql]
    host=localhost
    database=nomdemabase
    user=nomdemonuser
    password=monmdp

    En exécutant mon fichier .py sur le terminal, tout se passe bien : je vois bien ma table "tabletest" remplie lorsque je me connecte à ma bdd Postgres et que je tape "SELECT * FROM tabletest". Cela m'indique que la connexion via les commandes PyQt5 ont bien marché.

    Dans un deuxième temps, je veux afficher cette tabletest dans une fenêtre. Après recherche sur Internet et grâce en particulier aux codes mis à disposition par @tyrtamos sur ce forum, j'ai vu qu'il fallait entre autres:
    - se connecter à la base PostgreSQL avec QSqlDatabase
    - créer un modèle QSqlRelationalTableModel et saisir les paramètres que l'on souhaite (setEditStrategy, setTable, etc)
    - créer la grille d'affichage QTableView et saisir les paramètres que l'on souhaite (setSortingEnabled, setModel, etc)
    - peupler le modèle avec les données de la table avec la méthode select()

    On peut trouver un script python qui marche bien sur cette discussion mais avec SQLite3: https://www.developpez.net/forums/d2...-base-donnees/

    J'ai donc téléchargé la base .zip et lancer le script. Tout s'est bien affiché donc j'ai voulu faire exactement la même chose mais avec PostgreSQL dans ce fichier : post.py

    Et là problème : lorsque j'exécute post.py j'obtiens une fenêtre blanche !

    Je n'arrive pas à voir d'où vient vient le problème car je n'ai modifié quasiment que la connexion à la bdd (de SQLite3 à PostgreSQL) en changeant le driver notamment et je sais que cela marche bien puisque je l'ai fait dans le fichier creatableqt.py qui fonctionne...

    Pourriez-vous m'aider s'il-vous-plaît?

    PS: Désolé pour le long message !
    PSS: C'est mon premier post sur le forum et je suis assez débutante en programmation avec PyQt5, je m'excuse d'avance si je pose des questions un peu "bêtes"

  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,

    Juste une idée: peut-être que postgresql renvoie des données qui ne sont pas compatibles avec ma classe MonSqlRelationalDelegate. J'avais écrit celle-ci pour faciliter l'édition des données de différents types, issues de sqlite3.

    Je suggère donc de remplacer la ligne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.vuetable.setItemDelegate(MonSqlRelationalDelegate(self.vuetable))
    Par la ligne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.vuetable.setItemDelegate(QtSql.QSqlRelationalDelegate(self.vuetable))
    Tu n'auras ainsi que le delegate par défaut.

    Essaie, et dis ce que ça fait.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Pimboli Voir le message
    Et là problème : lorsque j'exécute post.py j'obtiens une fenêtre blanche !

    Je n'arrive pas à voir d'où vient vient le problème car je n'ai modifié quasiment que la connexion à la bdd (de SQLite3 à PostgreSQL) en changeant le driver notamment et je sais que cela marche bien puisque je l'ai fait dans le fichier creatableqt.py qui fonctionne...

    Pourriez-vous m'aider s'il-vous-plaît?
    Une fenêtre blanche (ça m'est arrivé aussi) signifie que le programme plante à un moment dans un module Qt. Le module s'arrête donc et rien de ce qui se trouve en dessous (les affichages éventuels) n'est exécuté.
    Toutefois, la console Python, elle, indique le nom du module et la ligne qui fait planter. Sauf si tu as lancé ton source en double cliquant dessus, alors il n'y a pas de console Python.

    Donc
    1) tu ouvres une console de commandes (MsDos sous Windows, fenêtre shell sous Linux)
    2) tu vas à l'endroit où se trouve ton code
    3) tu l'exécutes via la commande "python programme.py" (ou "python3 programme.py"). Le code s'exécutera cette fois dans la console dans laquelle tu es et t'affichera tous les soucis qu'il rencontre
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2021
    Messages : 8
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Bonjour tyrtamos,

    Merci pour votre réponse ! Je viens de procéder à la modification mais malheureusement, rien n'a changé j'obtiens toujours une fenêtre blanche ...

    Citation Envoyé par Sve@r Voir le message
    Bonjour Sve@r,

    Je vous remercie pour votre réponse également ! J'ai en effet lancé mon programme depuis la console de mon Mac avec la commande "python3 pgrm.py" mais la console ne renvoie aucune erreur : le programme s'exécute "bien" mais la fenêtre en sortie est vide donc je n'ai aucune indication sur la provenance de l'erreur dans mon script ^^'

  5. #5
    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,

    Trois idées.

    1- avant d'incriminer le graphique, il faudrait peut-être vérifier que l'accès aux données de la base est ok. Pour ça, ce serait intéressant de faire un petit code qui récupère une données en dehors du QTableView (instruction SQL "SELECT") et l'affiche en console.


    2- ajouter des print pour pister le déroulement du lancement en affichant la valeur de certaines variables.


    3- De temps en temps, j'ai un programme PyQt5 en cours de mise au point qui plante sans aucun message d'erreur, et je déteste!

    Alors, j'ai trouvé une solution qui marche pas mal:

    - créer un petit module à importer. Je l'appelle msgerreur.py, qui contient:

    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
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    from PyQt5.QtCore import (QtDebugMsg, QtInfoMsg, QtWarningMsg, QtCriticalMsg, 
                        QtFatalMsg, QtSystemMsg)
    from PyQt5.QtWidgets import QMessageBox
     
    #############################################################################
    def messagederreur(typerr, contexte, msgerr):
        """Permet d'afficher et/ou de neutraliser les messages d'erreur.
           Pour les messages critiques: affiche dans une fenêtre graphique.
           Mise en place par: QtCore.qInstallMessageHandler(messagederreur)
        """
        if typerr==QtDebugMsg:
            # exemple de désactivation d'un message
            #if "QWindowsFileSystemWatcherEngine: unknown message" in msgerr:
            #    return 
            print("DEBUG:\n{}\n".format(msgerr))
     
        elif typerr==QtWarningMsg:
            # exemple de désactivation d'un message
            #if "QFont::setPixelSize: Pixel size <= 0 (0)" in msgerr:
            #    return
            print("WARNING:\n{}\n".format(msgerr))
     
        elif typerr in [QtCriticalMsg, QtFatalMsg, QtSystemMsg]:    
            print("ERREUR CRITIQUE:\n{}\n".format(msgerr))
            QMessageBox.critical(None, 
                "ERREUR CRITIQUE:",
                "{}\n".format(msgerr))
        else:
            # message retourné par QtCore.QtInfoMsg créé à partir de Qt 5.5
            print("INFO:\n{}\n".format(msgerr))
    - Le programme principal l'importe de la façon suivante, juste après le lancement de la bibliothèque PyQt5:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        app = QtWidgets.QApplication(sys.argv)
     
        from msgerreur import messagederreur  
        QtCore.qInstallMessageHandler(messagederreur)
     
        ...
    En cas d'erreur, même fatale, un petite fenêtre s'ouvre pour afficher le message d'erreur. En plus du même message pour la console (grâce aux "print").

    Ce n'est pas garanti, mais quand ça marche, ça diminue considérablement le temps de mise au point.

    Dans ton cas, ce n'est pas une erreur fatale, mais il y a peut-être un warning qui serait une piste de recherche.

    A noter que cette méthode permet aussi de supprimer certains warnings sans conséquence, afin d'éviter de perturber l'utilisateur pour rien.

    Essaie! et dis ce que ça fait.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Pimboli Voir le message
    Je vous remercie pour votre réponse également ! J'ai en effet lancé mon programme depuis la console de mon Mac avec la commande "python3 pgrm.py" mais la console ne renvoie aucune erreur : le programme s'exécute "bien" mais la fenêtre en sortie est vide donc je n'ai aucune indication sur la provenance de l'erreur dans mon script ^^'
    Alors il faut rajouter du print() dans le script aux endroits clés pour vérifier qu'il a bien les bonnes valeurs au bon moment. Ces affichages se feront ensuite dans ladite console.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2021
    Messages : 8
    Par défaut
    Bonjour tyrtamos,

    Merci pour votre message et toutes les pistes !

    1 - Comme vous me l'avez suggérer, j'ai testé l'accès aux données en ajoutant dans mon fichier creatableqt.py les lignes de code suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    query.exec_("select * from %s" % matable)
    rec = query.record()
     
    print "Number of columns: %d" % rec.count()
     
    motCol = rec.indexOf("mot")
    while query.next():
        print query.value(motCol)
    Lorsque j'exécute mon programme, j'ai bien la liste des mots qui s'affiche dans ma console, c'est déjà une bonne chose haha

    2 - J'ai ajouté quelques print() par exemple pour afficher le nom de ma table et être sûre que l'on parle bien du même objet et il ne me semble pas y avoir d'incohérence. Pareil pour la "variable" "db.open()". Auriez-vous d'autres variables à me suggérer d'afficher ? Car je ne vois pas bien ce que l'on peut "printer" lorsqu'on crée les modèles/grilles.

    3 - Merci pour le code ! Je viens de tester tout cela (création de msgerreur.py et implémentation dans le code principal) mais toujours le même problème : une fenêtre blanche et aucun message d'erreur pour m'aiguiller sur la provenance du problème ><

    Merci pour votre temps !

  8. #8
    Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2021
    Messages : 8
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Alors il faut rajouter du print() dans le script aux endroits clés pour vérifier qu'il a bien les bonnes valeurs au bon moment. Ces affichages se feront ensuite dans ladite console.
    Bonjour Sve@r,
    Vous avez raison, je vais essayer de faire cela. Par "endroits clés", avez-vous une idée de plus précise sur les variables à suivre ?
    Merci pour votre message en tout cas !

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Pimboli Voir le message
    Par "endroits clés", avez-vous une idée de plus précise sur les variables à suivre ?
    J'avais pas fait gaffe que tu avais donné un lien vers ton code dans ton premier post (généralement on préfère avoir le code directement intégré)

    Or je l'ai récupéré, l'ai adapté à ma bdd (modifié donc juste les paramètres de connexion et de table) et il est parfaitement fonctionnel. Chez-moi, il affiche bien ma table. Et je peux changer de bdd et de table, il fonctionne toujours aussi bien.

    Je pense donc que le souci vient plutôt de ta bdd. Déjà par exemple checker le contenu de "params" serait un bon point de départ (vérifier aussi si Postgres accepte une connexion avec les paramètres tels qu'ils sont stockés dans cette variable). Par exemple moi n'ayant pas le module "config" j'ai de mon côté rempli cette variable manuellement en lui mettant des paramètres que je savais adéquats par rapport à mon serveur bdd. Vérifier aussi (via Postgres cette fois) le contenu de la table "tabletest"...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2021
    Messages : 8
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    J'avais pas fait gaffe que tu avais donné un lien vers ton code dans ton premier post (généralement on préfère avoir le code directement intégré)

    Or je l'ai récupéré, l'ai adapté à ma bdd (modifié donc juste les paramètres de connexion et de table) et il est parfaitement fonctionnel. Chez-moi, il affiche bien ma table. Et je peux changer de bdd et de table, il fonctionne toujours aussi bien.

    Je pense donc que le souci vient plutôt de ta bdd. Déjà par exemple checker le contenu de "params" serait un bon point de départ (vérifier aussi si Postgres accepte une connexion avec les paramètres tels qu'ils sont stockés dans cette variable). Par exemple moi n'ayant pas le module "config" j'ai de mon côté rempli cette variable manuellement en lui mettant des paramètres que je savais adéquats par rapport à mon serveur bdd. Vérifier aussi (via Postgres cette fois) le contenu de la table "tabletest"...
    Bonjour Sve@r,

    Désolé pour le lien vers le code, c'est mon premier post et je ne savais pas que la balise CODE existait, je ferai attention la prochaine fois !

    Merci pour votre test, je me suis donc intéressée au contenu de ma bdd !

    Dans un premier temps, j'ai vérifié comme vous me l'avez suggéré le contenu de "params" en affichant dans la classe "Fenêtre" mes paramètres de connexions après ouverture de la base :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    self.conx = ouvrebaseqt()
    print(self.cnx.hostName())
    print(self.cnx.databaseName())
    print(self.cnx.userName())
    print(self.cnx.password())
    print(self.cnx.isOpen()) # Returns true if the database connection is currently open; otherwise returns false
    En sortie, j'obtiens les bons paramètres et la méthode "isOpen()" me renvoie bien True. De plus, j'arrive à faire des requêtes dessus (afficher la première colonne par exemple, ou modifier des valeurs depuis mon script Python après ouverture de la base, donc j'en ai conclu que la connexion avec la bdd fonctionne (?)

    Du coup, je suis également allée voir directement sur Postgres le contenu de ma tabletest via "SELECT * FROM tabletest" et elle est bien remplie...Peut-être y a-t-il un problème au niveau des formats ? Pour info, les valeurs de ma première colonne sont du type INTEGER et les 3 autres sont du type VARCHAR.

    Enfin, pourriez-vous me donner plus d'information sur votre test ? Par exemple, votre bdd est-elle sur PostgreSQL ? Quels sont les types de données que vous avez dans votre table ?

    Encore merci pour votre temps

  11. #11
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Pimboli Voir le message
    Enfin, pourriez-vous me donner plus d'information sur votre test ? Par exemple, votre bdd est-elle sur PostgreSQL ? Quels sont les types de données que vous avez dans votre table ?
    Oui elle est évidemment sous Postgres. Et les types j'en ai de toutes sortes (j'ai même un type totalement artificiel créé spécifiquement pour cette bdd). Et le truc l'affiche quand-même parfaitement.

    Le mieux, c'est de repartir à zéro. Voici script de mini-bdd Postgres (créé à partir d'une de mes bdd)
    Code sql : 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
    drop database if exists "essai";
    create database "essai"
    	template = "template0"
    	encoding = 'utf8';
    \connect "essai"
    set role "postgres";
     
    create table "_cat_titre" (
    	"id_titre" smallint not null check ("id_titre" > 0),
    	"sigle" character varying(10) not null check ("sigle" not similar to ' *'),
    	"libelle" character varying(20) not null check ("libelle" not similar to ' *'),
    	primary key("id_titre")
    ) with (oids=false);
    insert into "_cat_titre" values (1, 'M.', 'Monsieur');
    insert into "_cat_titre" values (2, 'Mme', 'Madame');
    insert into "_cat_titre" values (3, 'Mlle', 'Mademoiselle');
     
    create table "personne" (
    	"id_personne" integer not null check ("id_personne" > 0),
    	"nom" character varying(40) not null check ("nom" not similar to ' *'),
    	"prenom" character varying(30) not null check ("prenom" not similar to ' *'),
    	"tel1" character(10) default null check ("tel1" not similar to ' *'),
    	"tel2" character(10) default null check ("tel2" not similar to ' *'),
    	"adresse" character varying(100) default null check ("adresse" not similar to ' *'),
    	"cp" character(5) default null check ("cp" not similar to ' *'),
    	"ville" character varying(30) default null check ("ville" not similar to ' *'),
    	"comment" text default null check ("comment" not similar to ' *'),
    	"date_creation" date not null check ("date_creation" <= ('today'::text)::date) default ('today'::text)::date,
    	"id_titre" smallint not null,
    	constraint "fk_titre" foreign key ("id_titre")
    		references "_cat_titre" ("id_titre") match full
    		on update cascade on delete restrict,
    	primary key("id_personne")
    ) with (oids=false);
     
    insert into "personne" values (1, 'Moi nom', 'Moi prénom', '0123456789', '9876543210', '1 rue du chat perché', '01234', 'Moi ville', 'Super type', ('today'::text)::date, 1);
    insert into "personne" values (2, 'Toi nom', 'Toi prénom', '0123456789', '9876543210', '1 rue du chat perché', '01234', 'Toi ville', 'Super type', ('today'::text)::date, 1);
    insert into "personne" values (3, 'Lui nom', 'Lui prénom', '0123456789', '9876543210', '1 rue du chat perché', '01234', 'Lui ville', 'Super type', ('today'::text)::date, 1);

    Sous Linux, te suffit de copier ce script dans un fichier "essai.sql" et taper la commande cat essai.sql |psql -U postgres.

    Et voici le programme (ton programme) qui y accède parfaitement
    Code python : 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
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    import sys
     
    #from config import *
    from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
     
    #############################################################################
    class MonSqlRelationalDelegate(QtSql.QSqlRelationalDelegate):
     
    	#========================================================================
    	def __init__(self, parent=None):
    		super().__init__(parent)
     
    	#========================================================================
    	def createEditor(self, parent, option, index):
    		"""Crée et initialise le widget d'édition
                             aParent: type 'PyQt5.QtWidgets.QWidget'
                             option: type 'PyQt5.QtWidgets.QStyleOptionViewItem'
                             index: type 'PyQt5.QtCore.QModelIndex'
                       Retourne l'éditeur utilisé
                    """
    		if index.column() == 0: # => on est dans la colonne des entiers
    			# crée le widget d'édition des entiers
    			editor = QtWidgets.QSpinBox(parent)
    			editor.setRange(-1000000, +1000000)
    			# retourne le widget
    			return editor
     
    		else:
    			# cas d'une autre colonne: on repasse la main à l'ancêtre
    			return super().createEditor(parent, option, index)
     
    	#========================================================================
    	def setEditorData(self, editor, index):
    		"""Définit l'état du widget concerné à l'entrée du mode édition
                             editor: QtWidgets.QWidget
                             index: QtCore.QModelIndex
                       Retour: None
                    """
    		if index.column() == 0: # => on est dans la colonne des entiers
    			# récupère la valeur de la base de données
    			valeur = index.model().data(index, QtCore.Qt.EditRole)
    			# charge la valeur dans le widget avec le bon type
    			editor.setValue(int(valeur))
     
    		else:
    			# cas d'une autre colonne: on repasse la main à l'ancêtre
    			super().setEditorData(editor, index)
     
    	#========================================================================
    	def setModelData(self, editor, model, index):
    		""" Enregistre la valeur modifiée dans la base de données
                              editor: type 'QtWidgets.QWidget'
                              model: type 'QtCore.QAbstractItemModel'
                              index: type 'QtCore.QModelIndex'
                            Retour: None
                    """
    		if index.column() == 0: # => on est dans la colonne des entiers
    			#lit la valeur affichée dans le widget en fin d'édition
    			valeur = editor.value()
    			# enregistre dans le modèle la valeur affichée
    			model.setData(index, str(valeur), QtCore.Qt.EditRole)
    			return
     
    		else:
    			# traite les autres cas
    			super().setModelData(editor, model, index)
    			return
     
    #############################################################################
    def ouvrebaseqt():
    	"""ouvre la base avec le pilote "QPSQL" pour PostgreSQL, et
               renvoie la connexion (ou None si échec)
            """
    	params={
    		"host" : "localhost",
    		"database" : "essai",
    		"user" : "postgres",
    		"password" : "",
    	}
    	db = QtSql.QSqlDatabase.addDatabase("QPSQL")
    	db.setHostName(params['host'])
    	db.setDatabaseName(params['database'])
    	db.setUserName(params['user'])
    	db.setPassword(params['password'])
    	db.open()
    	if not db.open():
    		db = None
    	return db
     
    #############################################################################
    def fermebaseqt(cnx):
    	"""Ferme la base ouverte avec la connexion cnx de PyQt5
            """
    	if cnx!=None:
    		cnx.close()
     
    ##############################################################################
    class Fenetre(QtWidgets.QWidget):
     
    	#=========================================================================
    	def __init__(self, nomtable, parent=None):
    		super().__init__(parent)
     
    		self.setWindowTitle("Code test SQL")
    		self.resize(800, 600)
     
    		self.nomtable = nomtable # nom de la table à afficher
     
    		# ouvre la base de données
    		self.cnx = ouvrebaseqt()
    		if self.cnx==None:
    			QtWidgets.QMessageBox.critical(self,
    				"Ouverture de la base de données",
    				"Echec: base défaillante ou non trouvée")
    			self.close()
    			sys.exit()
     
    		# crée le modèle
    		self.model = QtSql.QSqlRelationalTableModel(self, self.cnx)
    		# pour afficher la table demandée
    		self.model.setTable(self.nomtable)
    		# pour mise à jour de la base à chaque modification d'une valeur
    		self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
     
    		# crée la grille d'affichage
    		self.vuetable = QtWidgets.QTableView(self)
    		# lien avec le modèle
    		self.vuetable.setModel(self.model)
    		# active la possibilité de tri
    		self.vuetable.setSortingEnabled(True)
    		# lien avec un delegate personnalisé pour l'édition
    		self.vuetable.setItemDelegate(MonSqlRelationalDelegate(self.vuetable))
     
    		# peuple le modèle avec les données de la table de la base de données
    		self.vuetable.model().select()
     
    		# tri si nécessaire selon la colonne 0
    		self.model.sort(0, QtCore.Qt.AscendingOrder) # ou DescendingOrder
     
    		# positionne la grille d'affichage dans la fenêtre
    		layout = QtWidgets.QGridLayout()
    		layout.addWidget(self.vuetable, 0, 0)
    		self.setLayout(layout)
     
    	#=========================================================================
    	def closeEvent(self, event):
     
    		if self.cnx!=None:
    			fermebaseqt(self.cnx)
    		event.accept()
     
    ##############################################################################
    if __name__ == '__main__':
     
    	app = QtWidgets.QApplication(sys.argv)
     
    	table = "personne"
     
    	fen = Fenetre(table)
    	fen.show()
     
    	sys.exit(app.exec_())
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  12. #12
    Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2021
    Messages : 8
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Le mieux, c'est de repartir à zéro. Voici script de mini-bdd Postgres (créé à partir d'une de mes bdd)
    Merci pour votre réponse ! Vous avez raison, j'ai recommencé grâce à vos codes pour avoir les idées plus claires.
    J'ai donc créé mon fichier essai.sql que j'ai exécuté en ligne de commande : en me connectant sur Postgres, on voit en effet les deux tables personne et _cat_titre remplies.
    En exécutant le code pour l'affichage de la fenêtre, j'ai toujours la fenêtre blanche mais cette fois-ci j'ai une erreur qui apparaît dans le terminal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    2021-07-06 16:11:35.955 CEST [5538] ERROR:  column pg_attrdef.adsrc does not exist at character 128
    2021-07-06 16:11:35.955 CEST [5538] STATEMENT:  SELECT pg_attribute.attname, pg_attribute.atttypid::int, pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, pg_attrdef.adsrc FROM pg_class, pg_attribute LEFT JOIN pg_attrdef ON (pg_attrdef.adrelid = pg_attribute.attrelid AND pg_attrdef.adnum = pg_attribute.attnum) WHERE pg_table_is_visible(pg_class.oid) AND pg_class.relname = '_cat_titre' AND pg_attribute.attnum > 0 AND pg_attribute.attrelid = pg_class.oid AND pg_attribute.attisdropped = false ORDER BY pg_attribute.attnum
    2021-07-06 16:11:35.956 CEST [5538] ERROR:  column pg_attrdef.adsrc does not exist at character 128
    2021-07-06 16:11:35.956 CEST [5538] STATEMENT:  SELECT pg_attribute.attname, pg_attribute.atttypid::int, pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, pg_attrdef.adsrc FROM pg_class, pg_attribute LEFT JOIN pg_attrdef ON (pg_attrdef.adrelid = pg_attribute.attrelid AND pg_attrdef.adnum = pg_attribute.attnum) WHERE pg_table_is_visible(pg_class.oid) AND pg_class.relname = '_cat_titre' AND pg_attribute.attnum > 0 AND pg_attribute.attrelid = pg_class.oid AND pg_attribute.attisdropped = false ORDER BY pg_attribute.attnum
    Au moins j'ai une idée d'où vient le problème ! Après quelques recherches sur internet (https://stackoverflow.com/questions/...does-not-exist), je crois qu'il s'agit d'une erreur liée à ma version de Posgres. Je vais donc continuer dans ce sens et vais chercher dans quel fichier remplacer "d.adsrc" par "pg_get_expr(d.adbin, d.adrelid)" (je ne trouve pas le fichier "pgsql.inc.php" mentionné dans le forum) !

  13. #13
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Pimboli Voir le message
    Après quelques recherches sur internet (https://stackoverflow.com/questions/...does-not-exist), je crois qu'il s'agit d'une erreur liée à ma version de Posgres.
    Effectivement, mes tests ont été faits sous Postgres11. Et en testant P12 j'obtiens aussi une page blanche. La cause est entendue, il semble que le module Postgres de Qt ne soit plus adapté aux versions 12 (et sûrement supérieures) de pg.

    Citation Envoyé par Pimboli Voir le message
    (je ne trouve pas le fichier "pgsql.inc.php" mentionné dans le forum) !
    C'est un fichier php qui n'a aucun rapport avec Python (là bas le souci se situait dans le module Postgres de php)...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  14. #14
    Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2021
    Messages : 8
    Par défaut
    Bonjour Sve@r,

    En effet, je viens de tout réinstaller et l'affichage marche à merveille !!

    Si ça peut aider quelqu'un dans le futur, voici les versions de mes logiciels et packages :
    • macOS Sierra 10.12.6
    • Python 3.7.0
    • pip 21.1.3
    • Postgres 11
    • PyQt5 5.13.0
    • (supplément utile pour mon projet mais non nécessaire pour faire fonctionner l'affichage dont il est question dans ce forum) psycopg2 2.7.7 et psycopg2-binary 2.7.7


    Je vous remercie grandement pour le temps que vous m'avez accordé et vous souhaite une excellente continuation !

    Je clos la discussion, le problème étant résolu

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 27/03/2014, 14h04
  2. Réponses: 5
    Dernier message: 25/03/2014, 10h35
  3. Créer une base de données SQL-Server sur un serveur distant
    Par algeriano.29 dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 30/01/2014, 15h24
  4. [PB 10.5] Créer une base de données sur Sybase
    Par brania dans le forum Powerbuilder
    Réponses: 0
    Dernier message: 03/04/2009, 10h02
  5. Créer une base de donnée sur un réseau
    Par mohamed2006 dans le forum Débuter
    Réponses: 3
    Dernier message: 07/03/2007, 23h09

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