john8585 | Bonjour, dans le cadre de mes etudes en IUT infi a la rochelle, nous avons a elaborer un projet en Python + Glade , seulement k'ai un problème, une structure nous a été fournie par le professeur pour faciliter la partie Base de Données mais j'ai un problème avec celle çi.
E, fait je peut ajouter des eleves mais lorsque je souhaite en supprimer un j'ai le droit à cette erreur :
Code :
- Traceback (most recent call last):
- File "inscription.py", line 172, in on_Valider_clicked
- self.controleur.suppression()
- File "inscription.py", line 66, in suppression
- self.supprimerEleve(self.fenetreSuppr.saisieIdent.get_text())
- File "inscription.py", line 122, in supprimerEleve
- lib.remove(EleveAVirer)
- File "lib.py", line 137, in remove
- raise 'panic : object "%s" can not be removed' % repr(obj)
- panic : object "('Jonathan Blanchet', '01/10/1985', '0251976039', '24 rue de Gaulle', 'jblanche')" can not be removed
|
Voila maintenant le code : Structures fournies :
entites.py :
Code :
- import lib
- class Eleve(lib.Entity) :
- def __init__(self, ident , nom, date, tel, adr) :
- lib.Entity.__init__(self)
- self.ident = ident
- self.nom = nom
- self.date = date
- self.tel = tel
- self.adr = adr
|
lib.py :
Code :
- # -*- coding: latin-1 -*-
- # Cette version de lib est prévue pour python 2.3
- # et gtk 2
- # Mini bibliothèque pour de petits prototypes dans le style de OOSE.
- # -----------------------------------------------------------------
- #
- # G.Louis - I.U.T. de La Rochelle - 2002, 2003, 2004
- #
- # (C) G. LOUIS - 2002, 2003, 2004
- #
- # Cette bibliothèque fournit des objets persistents pour les entités UML
- # (entités au sens de OOSE de Jacobson).
- # Cette bibliothèque fournit une super-classe pour les controleurs et les interfaces
- # au sens de OOSE.
- # Les fenêtres sont définies par glade, et implantées par libglade.
- # La connexion automatique des "handlers" aux "signals" est assurée.
- #
- # PERSISTENCE
- # -----------
- # Il faut initialiser la connexion à la "base de données" par
- # lib.connect(<nom-du-fichier> ).
- #
- # A la fin du programme, il faut fermer la connexion par lib.commit() pour
- # assurer la persistence.
- #
- # Toutes les classes qui correspondent à des entités doivent :
- # 1. Etre des sous classes de Entity
- # 2. Invoquer le constructeur de cette classe : lib.Entity.__init__(self)
- #
- # Toutes les entités ont un "oid" accessible par l'attribut _oid, qu'il ne faut
- # évidemment jamais modifier.
- #
- # lib.instances(P) fournit la liste des instances de la classe P (à condition qu'il
- # s'agisse bien d'une classe qui respecte les règles ci-dessus).
- #
- # lib.remove(p) supprime l'objet persistent p de la base de données proprement dite.
- # p n'est plus accessible grâce à lib.instances(P) (où P est la classe de P), mais
- # peut rester accessible à partir d'autres objets persistents. Une exception est levée
- # si l'objet n'est pas dans la base.
- #
- #
- # CONTROLEURS.
- # -----------
- #
- # Les sous-classes de Controller doivent appeler le constructeur de la classe :
- # lib.Controller.__init__(self, <nom du fichier glade> )
- #
- # Le controleur possède un attribut pour chaque Interface qui a été construite
- # pour lui (qui lui a été attachée). Voir ci-dessous, la documentation des Interfaces.
- #
- #
- # INTERFACES.
- # ----------
- #
- # Les sous-classes de Interface doivent appeler le constructeur de la classe :
- # lib.Interface.__init__(self, nom_fenetre, contrôleur)
- # où nom_fenetre est le nom de la fenêtre, tel qu'on l'a fixé dans glade.
- #
- # Donc, chaque Interface (plus précisément chaque instance d'une sous-classe d'interface)
- # correspond à une fenêtre créée avec glade.
- #
- # Pour chacun des widgets de la fenêtre -- y compris la fenêtre elle même -- l'interface
- # possède un attribut. Le nom de cet attribut est le nom du widget dans glade. La
- # valeur de cet attribut est un objet gtk, auquel on peut envoyer les messages
- # définis par le module gtk.
- #
- # Une interface doit posséder une méthode pour chaque "signal handler" défini par glade,
- # pour sa fenêtre et pour les widgets que contient cette fenêtre. Par exemple
- # def on_accept-clicked(self, widget) : ...
- # Toutefois, en l'absence de cette méthode, on connecte un "handler" par défaut,
- # qui imprime un message de rappel. Ceci permet un dévelopement incrémental du code.
- #
- # Chaque interface est "attachée" au controleur pour lequel elle a été construite.
- # L'interface possède l'attribut "controleur", pour enregistrer ce controleur.
- # A son tour, le contrôleur possédera un attribut qui porte le nom de la fenêtre glade
- # et qui enregistre l'interface créée pour cette fenêtre.
- #
- # Donc, si un controleur doit faire apparaître la fenêtre win2 à l'écran, on écrira :
- # self.win2.win2.show()
- # dans une méthode du contrôleur. Car dans le contrôleur, self.win2 désigne l'interface
- # attachée au contrôleur pour gérer la fenêtre win2. Dans cette interface, win2 désigne
- # l'objet fenêtre gtk lui-même.
- #
- import pickle
- import os
- __trace__ = 4
- __DBRoot__ = None
- def connect(filePath) :
- global __DBRoot__, __filePath__, statusMsg
- __filePath__ = filePath
- if os.path.isfile(filePath) and os.access(filePath, os.R_OK) :
- file = open(filePath)
- __DBRoot__ = pickle.load(file)
- file.close()
- statusMsg = "existing database %s open." % filePath
- else : # file will be opened for writing by "commit"
- __DBRoot__ = { }
- statusMsg = "new database %s open." % filePath
- def commit() :
- if __DBRoot__ == None :
- raise "panic : no file opened"
- file = open(__filePath__, "w" )
- pickle.dump(__DBRoot__, file)
- file.close()
- statusMsg = "database %s committed." % __filePath__
- class Entity :
- # Les sous-classes d'entity DOIVENT appeler Entity.__init__(self)
- def __init__(self) :
- # A database must be open
- if __DBRoot__ == None :
- raise "panic : no database opened."
- k = self.__class__.__name__
- if not __DBRoot__.has_key(k) : __DBRoot__[k] = [ 0 ]
- self._oid = k + "#" + repr(__DBRoot__[k][0])
- __DBRoot__[k][0] = __DBRoot__[k][0] + 1
- __DBRoot__[k].append(self)
- def instances(_class) : # méthode qui rend la liste des instances
- if __DBRoot__.has_key(_class.__name__) :
- return __DBRoot__[_class.__name__][1:]
- else :
- return [ ] # no instances yet or user error ?
- def remove(obj) :
- if __DBRoot__.has_key(obj.__class__.__name__) \
- and obj in __DBRoot__[obj.__class__.__name__] :
- __DBRoot__[obj.__class__.__name__].remove(obj)
- elif __DBRoot__.has_key(obj.__class__.__name__) :
- raise 'panic : object with oid "%s" can not be found to be removed' % obj._oid
- else :
- raise 'panic : object "%s" can not be removed' % repr(obj)
- #
- # CONTROLEURS.
- # -----------
- #
- import xml.parsers.expat
- # Constants for the states on the stack for the SAX parser.
- neutral = "neutral"
- window = "window"
- # The stack items are 3-uples.
- # The first element of these tuples are one of the constants above.
- # The second element is a dictionnary where widgets should be added
- # The third element is a dictionary where signals should be added
- # (or None, if no window has been encounered, yet)
- # (See below, the structure of sig_dico)
- class DefaultHandler : # A default handler that prints a warning message
- def __init__(self, win_name, handler_name) :
- self.win_name = win_name
- self.handler_name = handler_name
- def handler(self, widget, * rest) :
- print "WARNING : %s should define handler %s(self, widget)."\
- % (self.win_name, self.handler_name)
- class Controller :
- def __init__(self, gladefilename) :
- self.gladefilename = gladefilename
- ifile = open(gladefilename)
- # sig_dico is a 3 level deep tree of dictionaries
- # The first level associates each window name to a dictionary, which
- # at the second level associates each widget name to a dictionary which
- # at the third level associates each signal name to a handler name.
- # See also method "tree" above.
- self.sig_dico = { }
- # stack of states to handle elements'nesting
- self.states = [ ] ; self.states.append( (neutral, self.sig_dico, None) )
- p = xml.parsers.expat.ParserCreate("ISO-8859-1" ) # "ISO-8859-1" ?
- p.StartElementHandler = self.start_element
- p.EndElementHandler = self.end_element
- # p.CharacterDataHandler = self.char_data
- p.ParseFile(ifile)
- ifile.close()
- if __trace__ >= 3 : self.tree()
- # Dynamic attributes for windows. Will get an interface on attachment.
- for w in self.sig_dico.keys() :
- self.__dict__[w] = None # Dynamic attr definition
- def tree(self) : # trace of the tree in self.sig_dico
- for win in self.sig_dico.keys() :
- print "Window", win
- for wid in self.sig_dico[win].keys() :
- print " Widget", wid
- for s in self.sig_dico[win][wid].keys() :
- print " Signal", s, "-> method", self.sig_dico[win][wid][s]
- def start_element(self, xml_elt, attrs) :
- if __trace__ >= 5 : print 'Start element:', xml_elt, attrs
- state, widgets, signals = self.states[ -1 ]
- if state == neutral and xml_elt == u"widget" :
- if attrs[u"class"] == u"GtkWindow" :
- winName = attrs[u"id"].encode()
- widgets[winName] = { } # For the widgets
- widgets[winName][winName] = { } # For the signals of the window itself
- self.states.append( (window, widgets[winName], widgets[winName][winName]) )
- if __trace__ >= 4 : print "push :", repr(xml_elt), repr(attrs[u"id"]), len(self.states)
- else :
- raise "Panic : Non-window widget %s at top-level of glade file" \
- % (attrs[u"id"].encode() , )
- elif state == window and xml_elt == u"widget" :
- widName = attrs[u"id"].encode()
- if widName in widgets.keys() :
- print " *** Panic : 2 widgets nommés <<%s>> dans la fenetre" % ( widName, )
- import sys
- sys.exit(1)
- widgets[widName] = { } # For the signals of the widget
- self.states.append( (window, widgets, widgets[widName]) )
- if __trace__ >= 4 : print "push :", repr(xml_elt), repr(attrs[u"id"]), len(self.states)
- elif state == window and xml_elt == u"signal" :
- signals[ attrs[u"name"].encode() ] = attrs[u"handler"].encode()
- if __trace__ >= 5 : print " >state :", self.states[-1]
- def end_element(self, xml_elt) :
- if __trace__ >= 5 : print "End element", repr(xml_elt)
- if xml_elt == u"widget" :
- self.states.pop()
- if __trace__ >= 4 : print "pop :", repr(xml_elt), len(self.states)
- if __trace__ >= 5 :
- if len(self.states) > 0 :
- print " < state :", self.states[-1]
- else :
- print " ** Stack empty."
- def attach(self, itrf, win_name, glade_win) :
- # self.tree()
- # print self.sig_dico.keys()
- if __trace__ >= 2 : print "Attaching :", win_name
- if not self.sig_dico.has_key(win_name) :
- raise "panic : controller has no %s window (%s)." \
- % (win_name, repr(self.sig_dico.keys()))
- win_dico = self.sig_dico[win_name]
- self.__dict__[win_name] = itrf # Dynamic attr definition
- for widget in win_dico.keys() :
- if __trace__ >= 2 : print " Defining :", widget
- itrf.__dict__[widget] = glade_win.get_widget(widget) # Again
- h_dico = win_dico[widget]
- for signal_name in h_dico.keys() :
- handler_name = h_dico[signal_name]
- if __trace__ >= 2 : print " handler for", signal_name, "is", handler_name,
- if hasattr(itrf, handler_name) :
- method = eval("itrf." + handler_name)
- if __trace__ >= 2 : print ". It was connected."
- else :
- method = DefaultHandler(win_name, handler_name).handler
- if __trace__ >= 2 : print ". A dummy handler was created."
- # print handler_name, '->', method
- glade_win.signal_connect(handler_name, method)
- #
- # INTERFACES.
- # ----------
- #
- import gtk
- import gtk.glade
- class Interface :
- def __init__(self, window_name, controleur) :
- self.controleur = controleur
- self.glade_win = gtk.glade.XML(controleur.gladefilename, window_name)
- controleur.attach(self, window_name, self.glade_win)
- # print dir(self)
- def gtk_main_quit(self, widget) :
- if __trace__ >= 3 : print "Std gtk_main_quit was called."
- gtk.mainquit()
|
De nous : inscription.py
Code :
- import lib
- import gtk
- import entites
- class Controleur(lib.Controller):
- def __init__(self):
- lib.Controller.__init__(self, "ecole_de_music.glade" )
- self.execute()
- def execute(self):
- lib.connect("bdEleves" )
- self.fenetreMenu = ItrfMenu(self)
- gtk.mainloop()
- lib.commit()
- print "Bye..."
- def afficherErreur(self, typeErreur, champVide):
- self.uneErreur = ItrfErreur(self,typeErreur, champVide)
- def fermerErreur(self):
- self.erreur.erreur.hide()
- def verifierChamps(self):
- global typeErreur
- global champVide
- if (self.fenetreInscription.entry1.get_text() == "" ) :
- typeErreur = "Veuillez remplir le champ : "
- champVide = "Nom et prenom"
- self.afficherErreur(typeErreur, champVide)
- elif (self.fenetreInscription.entry2.get_text() == "" ):
- typeErreur = "Veuillez remplir le champ : "
- champVide = "Date de naissance"
- self.afficherErreur(typeErreur, champVide)
- elif (self.fenetreInscription.entry3.get_text() == "" ):
- typeErreur = "Veuillez remplir le champ : "
- champVide = "Numero de telephone"
- self.afficherErreur(typeErreur, champVide)
- elif (self.fenetreInscription.entry4.get_text() == "" ):
- typeErreur = "Veuillez remplir le champ : "
- champVide = "Adresse"
- self.afficherErreur(typeErreur, champVide)
- elif (self.fenetreInscription.entry5.get_text() == "" ):
- typeErreur = "Veuillez remplir le champ : "
- champVide = "Identifiant"
- self.afficherErreur(typeErreur, champVide)
- else :
- print("Ca marche" )
- self.ajouterEleve(self.fenetreInscription.entry1.get_text(),\
- self.fenetreInscription.entry2.get_text(),\
- self.fenetreInscription.entry3.get_text(),\
- self.fenetreInscription.entry4.get_text(),\
- self.fenetreInscription.entry5.get_text())
- def suppression(self) :
- if(self.fenetreSuppr.saisieIdent.get_text() == "" ) :
- typeErreur = "Veuillez remplir le champ : "
- champVide = "Identifiant"
- self.afficherErreur(typeErreur, champVide)
- else :
- self.supprimerEleve(self.fenetreSuppr.saisieIdent.get_text())
- def retourMenu(self, str):
- if (str == "suppr" ):
- self.fenetreSuppr.fenetreSuppr.hide()
- elif (str == "insc" ) :
- self.fenetreInscription.fenetreInscription.hide()
- elif (str == "modif" ) :
- self.fenetreModif.fenetreModif.hide()
- self.menu.menu.show()
- def ajout(self):
- self.fenetreInscription = ItrfInscription(self)
- def modif(self):
- self.fenetreModif = ItrfModif(self)
- def suppr(self):
- self.fenetreSuppr = ItrfSuppr(self)
- def ajouterEleve(self, nom, date, tel, adr, ident):
- Eleves = map(lambda e : e.ident, lib.instances(entites.Eleve))
- if ident in Eleves :
- typeErreur = "L'identifiant "+ident
- champVide = "existe deja"
- self.afficherErreur(typeErreur, champVide)
- self.fenetreInscription.entry5.set_text("" )
- else :
- entites.Eleve(nom, date, tel, adr, ident)
- typeErreur = "L'identifiant "+ident
- champVide = "a ete ajoute."
- self.afficherErreur(typeErreur, champVide)
- self.fenetreInscription.entry1.set_text("" )
- self.fenetreInscription.entry2.set_text("" )
- self.fenetreInscription.entry3.set_text("" )
- self.fenetreInscription.entry4.set_text("" )
- self.fenetreInscription.entry5.set_text("" )
- def supprimerEleve(self , identifiant ):
- Eleves = map(lambda e : [e.nom, e.date ,e.tel ,e.adr, e.ident], lib.instances(entites.Eleve))
- print Eleves
- i = 0
- a=0
- while i < len(Eleves):
- idEleve = Eleves[i]
- identElevASupr = idEleve [4]
- if (identElevASupr == identifiant ):
- print "je rentre dans le while"
- nomElevASupr = idEleve [0]
- dateElevASupr = idEleve [1]
- telElevASupr = idEleve [2]
- adrElevASupr = idEleve [3]
- identElevASupr = idEleve [4]
- EleveAVirer = (nomElevASupr,dateElevASupr,telElevASupr,adrElevASupr,identElevASupr)
- lib.remove(EleveAVirer)
- typeErreur = "L'identifiant : " + identifiant
- champVide = "a ete supprime "
- self.afficherErreur(typeErreur, champVide)
- a=1
- i+=1
- if a == 0 :
- typeErreur = "L'identifiant : " + identifiant
- champVide = "n'existe pas "
- self.afficherErreur(typeErreur, champVide)
- class ItrfMenu(lib.Interface):
- def __init__(self, ctrl):
- lib.Interface.__init__(self, "menu", ctrl)
- def on_Ajout_clicked(self, widget):
- self.controleur.ajout()
- def on_Modif_clicked(self, widget):
- self.controleur.modif()
- def on_Suppr_clicked(self, widget):
- self.controleur.suppr()
- class ItrfInscription(lib.Interface):
- def __init__(self, ctrl):
- lib.Interface.__init__(self, "fenetreInscription", ctrl)
- def boutonValider_clicked(self, widget):
- self.controleur.verifierChamps()
- def boutonPrecedent_clicked(self, widget):
- self.controleur.retourMenu("insc" )
- def fenetreInscriptionDestroy(self, widget) :
- gtk.mainquit()
- class ItrfModif(lib.Interface):
- def __init__(self, ctrl):
- lib.Interface.__init__(self, "fenetreModif", ctrl)
- class ItrfSuppr(lib.Interface):
- def __init__(self, ctrl):
- lib.Interface.__init__(self, "fenetreSuppr", ctrl)
- def on_Valider_clicked(self, widget):
- self.controleur.suppression()
- def on_Precedent_clicked(self, widget):
- self.controleur.retourMenu("suppr" )
- def fenetreInscriptionDestroy(self, widget) :
- gtk.mainquit()
- class ItrfErreur(lib.Interface):
- def __init__(self, ctrl, typeErreur, champVide):
- lib.Interface.__init__(self, "erreur", ctrl)
- self.typeErreur.set_text(typeErreur)
- self.champVide.set_text(champVide)
- def fermerErreurClicked(self, widget):
- self.controleur.fermerErreur()
- def fenetreErreurDestroy(self) :
- self.controleur.fermerErreur()
- Controleur()
|
Mon problème : Dans la fonction supprimerEleve je recrée l'élève mais pas comme il faut apparement le type de l'objet ne correspond pas c'est ça non ?
Voila je compte sur vous pour regler ce problème et m'aider a poursuivre mon apprentissage Merci ! Message édité par john8585 le 05-06-2004 à 20:00:28
|