Daten aus Schleifen speichern und weiterverarbeiten

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
ginod
User
Beiträge: 1
Registriert: Dienstag 10. Dezember 2024, 07:56

Hallo,

ich bin ziemlich neu in Python. Habe früher ein bisschen PHP programmiert.

Ich habe jetzt schon einiges hinbekommen. Formulare, welche Informationen in die Datenbank speichern, einige Abfragen und Darstellungen, Listen etc.

Was ich jetzt aber benötige bringt mich an den Rand der Verzweiflung.

Ziel:. Ich will, dass er mir eine Liste mit Personendaten einer SQL Datenbank ausgibt. Weiterhin soll er ein Eingabefeld hinzufügen, wo ich einen Wert eingeben kann (Stückzahl). Nachdem ich diese eingegeben habe, soll unten ein weiteres Formular sein, wo ich eine kurze Beschreibung, ein Datum und ein Update Button habe, wo er mir die Informationen in eine !NEUE! Tabelle der Datenbank speichert und die ID der jeweiligen Person in eine Spalte der neuen Tabelle ebenfalls einträgt.

Ich habe versucht das ganze mit for oder while Schleifen zu lösen. Mein großes Problem ist eigentlich, dass ich es nicht hinbekomme, dass ich die Informationen "innerhalb" der einen Schleife in eine andere Schleife zum updaten bekomme. Beim erneuten ausführen der Schleife, löscht er mir ja wieder meine Eingabefelder. In diesem katuellen Stand zeigt er mir eine Fehlermeldung an, weil ~~~~~^^^
IndexError: string index out of range - weil ich gerade mit der Funktion "append" Methode experimentiert habe und irgendwie gedacht habe, ich könnte vielleicht die Infos in einer Variablen Liste mit append speichern - aber da komm ich nicht weiter

Code: Alles auswählen

# Connect to the database
conn = sqlite3.connect('data.db')
cursor=conn.cursor()
cursor2=conn.cursor()
# Execute the query to fetch first names and last names
cursor.execute("SELECT rowid, vorname, nachname, modul, zahler_id FROM piece_data WHERE meal=1")

# Fetch all entries
entries = cursor.fetchall()

# Initialize index
frame = tkinter.LabelFrame(mittagessen, text="Stück erhalten")
frame.config(bg="#F9EBB1")
frame.grid(row= 0, column=0)

frame2 = tkinter.LabelFrame(mittagessen, text="Eingaben bestätigen")
frame2.config(bg="#F9EBB1")
frame2.grid(row= 1, column=0)

entries1=[]
entries2=[]
# While loop to display all entries
def while_start():
    index = 0
    counter_rows=0
    while index < len(entries):
        rowid, firstname, lastname, modul, zahler_id = entries[index]
           
        meal_entry_var=tk.StringVar()
        meal_entry=tk.Entry(frame, width=5, textvariable=meal_entry_var)
        meal_entry.grid(row=counter_rows, column=0)
        meal_result= meal_entry.get()
        
        entries2.append(meal_result)
        entries1.append(zahler_id)
        
        id_label=tk.Label(frame, text=f"{rowid}")
        id_label.grid(row=counter_rows, column=1)
    
        firstname_label=tk.Label(frame, text=f"{firstname}")
        firstname_label.grid(row=counter_rows, column=2)
    
        lastname_label=tk.Label(frame, text=f"{lastname}")
        lastname_label.grid(row=counter_rows, column=3)
    
        id_label=tk.Label(frame, text=f"{modul}")
        id_label.grid(row=counter_rows, column=4)

    
        
        counter_rows += 1
        index += 1
while_start()
def update():
    for entry in entries2:
         
        zahler_id=entry[4].get()
        meal_amount=entry[0].get()
        preis_result= preis_entry.get()
        date_entry2=date_entry.get()
        grund_entry2=grund_entry.get()
        meal_amount *= preis_result
        cursor.execute('''INSERT INTO Soll (grund, betrag, datum, zahler_id) VALUES 
                         (?, ?, ?, ?)''', (grund_entry2, meal_amount, date_entry2, zahler_id))

#Check
check = tkinter.Label(frame2, text="Werte bestätigen!", bg="green", fg="white")
check.grid(row=1, column=0)
check_box = tkinter.Checkbutton(frame2)
checkboxvar = tk.BooleanVar()
checkboxvar.set(False)
check_box["variable"] = checkboxvar
check_box.grid(row=2, column=0) 

date_label=tkinter.Label(frame2, text="Datum der Berechnung")
date_label.grid(row=3, column=0)
date_entry_var=tk.StringVar()
date_entry=tk.Entry(frame2, textvariable=date_entry_var)
date_entry.grid(row=4, column=0)

date_label=tkinter.Label(frame2, text="Datum der Berechnung")
date_label.grid(row=3, column=0)
date_entry_var=tk.StringVar()
date_entry_var.set("DD.MM.YYYY")
date_entry=tk.Entry(frame2, textvariable=date_entry_var)
date_entry.grid(row=4, column=0)

grund_label=tkinter.Label(frame2, text="Abrechnungsbeschreibung")
grund_label.grid(row=5, column=0)
grund_entry_var=tk.StringVar()
grund_entry_var.set("01/2029")
grund_entry=tk.Entry(frame2, textvariable=grund_entry_var)
grund_entry.grid(row=6, column=0)

preis_label=tkinter.Label(frame2, text="Aktueller Preis")
preis_label.grid(row=7, column=0)
preis_entry_var=tk.StringVar()
preis_entry_var.set("4.50")
preis_entry=tk.Entry(frame2, textvariable=preis_entry_var)
preis_entry.grid(row=8, column=0)

button=tk.Button(frame2, text="Eintragen", command=update)
button.grid(row=9, column=0)   


# Close the database connection
conn.close()
mittagessen.mainloop()
Benutzeravatar
__blackjack__
User
Beiträge: 13764
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ginod: Anmerkungen zum Quelltext:

Da fehlen Importe. Es muss sowohl `tkinter` als `tkinter` als auch als `tk` importiert werden, das sollte einheitlich sein.

`mitagessen` ist ein schlechter Name für ein Fenster.

`conn` sollte `connection` heissen. Kryptische Abkürzungen sind schlecht.

Die Datenbankverbindung und die Cursor sollten auch wieder geschlossen werden. Es bietet sich an dafür die ``with``-Anweisung und `contextlib.closing()` dafür zu verwenden, um das sicherzustellen.

Cursor sollten nicht unnötig erstellt werden. `cursor2` wird nirgends verwendet.

Man nummeriert keine Namen. Entweder will man sich da bessere Namen überlegen, oder gar keine Einzelnamen und -Werte, sondern eine Datenstruktur. Oft eine Liste.

Wenn man Datenbankeinträge und `tkinter.Entry`-Objekte namentlich auseinader halten will, bietet es sich bei der Datenbank `rows` und `row` zu verwenden. Das ist bei relationalen Datenbanken auch der übliche Sprachgebrauch dafür.

Gibt es in der Tabellendefinition von `piece_data` tatsächlich eine explizite Spalte mit dem Namen `rowid` oder ist das die magische imlizite ”Spalte” von SQLite3? Letzteres sollte nicht sein, das ist kein Standard-SQL und nicht portabel.

Namen sollten in einer Sprache gehalten werden und nicht Deutsch und Englisch gemischt.

`while_start()` ist kein guter Name für eine Funktion. Die werden üblicherweise nach der Tätigkeit benannt die sie durchführen, damit der Leser weiss was die machen und damit man sie besser von eher passiven Werten unterscheiden kann.

Es macht auch keinen Sinn hier eine Funktion zu definieren, die genau einmal nach der Definition aufgerufen wird.

Die ``while``-Schleife in der Funktion zeigt, dass Du ganz dringend erst einmal das Grundlagentutorial aus der Python-Dokumentation durcharbeiten solltest. Einen Index in einer ``while``-Schleife selbst hochzählen um damit der Reihe nach auf alle Elemente einer Sequenz zuzugreifen ist maximal umständlich. Das ist eine ganz einfache ``for``-Schleife über die Elemente der Sequenz. Wenn man zusätzlich eine laufende Zahl benötigt, gibt es die `enumerate()`-Funktion.

In der Schleife zwei Zahlen manuell rauf zu zählen die immer genau den gleichen Wert haben ist auch ziemlich sinnfrei.

Eine Zeichenkette 1:1 in einer Zeichenkette zu formatieren, ohne das da weiterer Text drin steht, macht keinen Sinn. Da kommt doch nur wieder die Zeichenkette bei heraus, die man sowieso schon hat.

Direkt nach dem Erstellen eines `Entry`-Objekts den Wert dort auslesen, macht keinen Sinn. Da hatte der Benutzer ja noch gar keine Gelegenheit etwas in dieses Feld einzugeben.

Magische Indexzugriffe sollte man vermeiden. Das man Werte schon in der ``for``-Schleife an sprechende Namen binden kann, sieht man ja an anderer Stelle im Programm. Das sollte man überall machen.

Daten die in die Datenbank eingetragen werden, sollte man vorher in den passenden Typ umwandeln. Sonst kann der Benutzer da sonstwas eingeben, weil SQLite wirklich alles schluckt, was dann aber im späteren zu Problemen führt, weil man sich dann mit fehlerhaften Eingaben herumschlagen muss.

Das kann auch problematisch werden weil bestimmte Abfragen nicht mehr funktionieren wenn man beispielsweise Datumsangaben einfach als Zeichenkette im Format Tag.Monat.Jahr in die Datenbank steckt. Abfragen die Vergleiche mit ``<`` oder ``>`` oder Einschränkungen mit ``BETWEEN`` machen, liefern dann ohne Fehlermeldung falsche Ergebnisse!

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst, und Funktionen (und Methoden) bekommen alles was sie ausser Konstanten benötigen als Argument(e) übergeben.

Bei GUIs kommt man bei jeder nicht-trivialen Anwendung um objektorientierte Programmierung (OOP) nicht herum, also eigene Klassen schreiben können.

Kommentare sollen dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da bereits als Code, sondern warum er das macht. Sofern das nicht offensichtlich ist. Offensichtlich ist in aller Regel auch was in der Dokumentation von Python und den verwendeten Bibliotheken steht.
“The city's central computer told you? R2D2, you know better than to trust a strange computer!” — C3PO
Antworten