Problem funktion "find(Hersteller,Art.......)" in Teilekatalog

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

Sirius3 hat geschrieben:@dannyboy385: `database` ist eine Klasse und wird deshalb `Database` geschrieben. Eine Klasse sollte immer ein __init__ haben, wo alle Attribute angelegt werden und wo danach die Instanz benutzbar ist. Cursor sind eigentlich etwas kurzzeitiges, was man für jede Transaktion neu erstellt. Transaktion ist etwas, was einen Vorgang bezeichnet und per `COMMIT` abgeschlossen wird. So wie Du jetzt mit `savedata` und `donotsavedata` arbeiten Datenbanken nicht. Man sollte immer die Feldnamen angeben, und sich nicht darauf verlassen, dass die da schon in der richtigen Reihenfolge sind, bei INSERT oder SELECT. »createdb« macht ziemliches Chaos mit Dateinamen. Den Wahrheitswert explizit mit "is True" zu vergleichen, ist unnötig. Was soll der Rückgabewert hier? Die Datenbank zu schließen und gleich wieder zu öffnen, ist umständlich. »createtable« wiederholt nochmal »createdb«. Warum zweimal? Bei »editdata« macht man am besten ein UPDATE. Bei search benutzt Du LIKE wahrscheinlich ohne zu wissen warum. »all« ist ein komischer Methodenname, und um eine Tabelle zu leeren gibt es DELETE. Da muß man nicht gleich die ganze Tabelle löschen.

Der GUI-Code benutzt wieder über und über globale Variablen. Die Exceptions, die Du in `guisave` abfängst sind eher zufällig. Wo soll da ein TypeError auftreten? Einen AttributeError dafür zu verwenden, um eine nicht geöffnete Datei abzufragen ist schlechter Stil. Alle Attribute einer Klasse sollten schon in __init__ angelegt werden, so dass jeder AttributeError ein Programmierfehler ist.

In `guineu` erzeugst Du ein neues Tk-Exemplar, davon darf es aber nur eins im ganzen Programm geben. e1 bis e5 sind schlechte Variablennamen, und statt innerer Funktionen schreibt man besser Klassen.

Alles ab Zeile 66 sollte in eine Funktion wandern, so dass man erst gar nicht in versuchung gerät, globale Variablen zu benutzen.

Hier die überarbeitete Klasse Database():
Ich habe der Klasse ein Init hinzugefügt. Aber dar meines Wissens nach ein Init ja eig nur etwas für variablen bringt die sonst X mal übergeben werden müssten, sehe ich noch keinen Sinn die 5 spalten in Form von Variablen hier hinzuzufügen, denn diese ändern sich ständig und man müsste beim erstellen eines objectes einen Datensatz angeben oO was keinen Sinn ergibt.

savedata und donotsave wurden zu lassten von openbd und close DB geopfert sodass der Curser und die Datenbank verbindung temporäre geschichten sind. Desweiteren habe ich versucht die Zuordnung der Zellen klarer zu gestalten. Auf is True teste ich um zu wissen ob die Datei existiert und später ine möglichkeit zu haben zu Sagen " Halt stop existiert schon, soll es überschrieben werden"). Createdb und Createtable wurden ebenfalls geändert. Editdata macht doch updates... Es geht mit den IF anweisungen darum nur das zu ändern was wirklich geändert werden soll und nicht den ganzen Rest zu eliminieren. All wurde umbenannt undemptydb() wurde mit DELETE überarbeitet. Das ganze ist noch ungetestet. Dazu werde ih cheute auch leider nicht mehr kommen. Den GUI Code denke ich muss ich noch einmal von 0 aufrollen. Globale Variablen haben so einen faden beigeschmack.
Die Exceptions wurden mir beim testen geworfen, und als ich den fehler entdekt habe habe ich sie hinzugefügt. Frage bitte nicht wie ich einen TypeError zusammen gebracht habe... :D

Code: Alles auswählen

class Database():
    def __init__(self,Pfad):
        self.Pfad=Pfad
        
    def opendb(self):
        self.connection = sqlite3.connect(self.Pfad)
        self.cursor = self.connection.cursor()
        
    def closedb(self):
        self.connection.commit()
        self.connection.close()

    def newdata(self,ArtNr,Herst,Artbez, PreisEK, gewinnfaktor=1.10, Mwst=1.19):
        opendb()
        PreisVK=round(PreisEK*gewinnfaktor*Mwst, 2)
        self.cursor.execute('INSERT INTO materialliste (Artikelnummer, Hersteller, Artikelbezeichnung, PreisEK, PreisVK) VALUES (?,?,?,?,?)', (ArtNr,Herst,Artbez,PreisEK,PreisVK))
        closedb()

    def deletedataset(self, artikelnummer):
        opendb()
        self.cursor.execute("DELETE FROM materialliste WHERE Artikelnummer = ?",(artikelnummer,))
        closedb()

    def createtable(self):
        sql_command = """
            CREATE TABLE IF NOT EXISTS materialliste (
            Artikelnummer INTEGER(15),
            Hersteller VARCHAR(20),
            Artikelbezeichnung VARCHAR(30),
            PreisEK REAL,
            PreisVK REAL
            );"""
        opendb()
        self.cursor.execute(sql_command)
        closedb()

    def createdb(self):
        if os.path.isfile(self.Pfad)is True:
            return
        else:
            createtable()
            

    def editdata(self,artikelnummer,Artikelbezeichnung=None,Hersteller=None,PreisEK=None,PreisVK=None):
        opendb()
        if Artikelbezeichnung != None:
             self.cursor.execute("UPDATE materialliste SET Artikelbezeichnung = ? WHERE Artikelnummer = ?", (Artikelbezeichnung,artikelnummer))
        if Hersteller != None:
            self.cursor.execute("UPDATE materialliste SET Hersteller = ? WHERE Artikelnummer = ?", (Hersteller,artikelnummer))
        if PreisEK != None:
            self.cursor.execute("UPDATE materialliste SET PreisEK = ? WHERE Artikelnummer = ?", (PreisEK,artikelnummer))
        if PreisVK != None:
            self.cursor.execute("UPDATE materialliste SET PreisVK = ? WHERE Artikelnummer = ?", (PreisVK,artikelnummer))
        closedb()
        
    def search(self,suchbegriff):
        opendb()
        self.cursor.execute("SELECT * FROM materialliste WHERE Artikelbezeichnung LIKE (?) OR Hersteller LIKE (?) OR Artikelnummer LIKE (?)", (suchbegriff,suchbegriff,suchbegriff))
        data= self.cursor.fetchall()
        closedb()
        return data
    
    def showall(self):
        opendb()
        self.cursor.execute("SELECT * FROM materialliste")
        data= self.cursor.fetchall()
        closedb()
        return data
        
    def emptydb(self):
        openbd()
        self.cursor.execute("DELETE * FROM materialliste")
        closedb()
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@dannyboy385: Konvention ist, Klasse mit großem Anfangsbuchstaben zu schreiben und alle Variablen und Funktionen komplett klein. So kann man gleich erkennen, um was es sich handelt. In `__init__` einer Klasse sollten alle Attribute gesetzt werden, die jemals von der Klasse benutzt werden, also insbesondere `connection`. `cursor` sollte gar kein Attribut sein, sondern für jede Transaktion neu erzeugt werden. Für jede Transaktion die Datenbank zu öffnen und wieder zu schließen ist übertrieben (also falsch).
Gegen das `if` habe ich ja gar nichts, nur ist `is True` überflüssig, sollte also `if os.path.isfile(self.path):` heißen.
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

Hi Sirius. Wie würdest du dies mit connection und cursor lösen? stehe gerade auf dem schlauch. connection und cursor werden durch opendb jedes mal neu erzeugt. und close db bestätigt änderungen mit .commit .
Antworten