Abfrage aus 2 Tabellen in eine Treeview-Ansicht

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Kayd
User
Beiträge: 2
Registriert: Sonntag 30. April 2023, 14:15

Hey zusammen!
Ich befasse mich seit kurzem mit der Python-Programmierung und habe mein erstes Projekt angefangen :)
Leider hapert es daran, dass ich wirklich scheinbar einfach auf dem Schlauch stehe die Daten korrekt in einer Treeview-Ansicht anzuzeigen.
Es müssen Daten aus 2 verschiedenen Tabellen angerufen und gesetzt werden.

Mein aktueller Code (aus einem YT-Tutorial :D)

Code: Alles auswählen

def load_patient():
    print("LoadPatient")
    if varstation == 1:
        print("Station == 1")
        query = 'select *from fall where StationID ="1"'
        mycursor.execute(query)
    elif varstation == 2:
        query = 'select *from fall where StationID ="2"'
        mycursor.execute(query)
    elif varstation == 3:
        query = 'select *from fall where StationID ="3"'
        mycursor.execute(query)
    fetched_data=mycursor.fetchall()
    patientTable.delete(*patientTable.get_children())
    for data in fetched_data:
        datalist=list(data)
        patientTable.insert('',END,values=datalist)
Die Ansicht sieht wie folgt aus:

Code: Alles auswählen

patientTable = ttk.Treeview(rightFrame,columns=('FallNr','Vorname','Name','Geburtsdatum','Geschlecht','Diagnose','Nebendiagnosen','Aufgenommen am',
                                                'Aufgenommen um'), xscrollcommand=scrollBarX.set, yscrollcommand=scrollBarY.set)
scrollBarX.config(command=patientTable.xview)
scrollBarY.config(command=patientTable.yview)

scrollBarX.pack(side=BOTTOM, fill=X)
scrollBarY.pack(side=RIGHT, fill=Y)
patientTable.pack(fill=BOTH, expand=1)

patientTable.heading('FallNr',text='FallNr')
patientTable.heading('Vorname',text='Vorname')
patientTable.heading('Name',text='Name')
patientTable.heading('Geburtsdatum',text='Geburtsdatum')
patientTable.heading('Geschlecht',text='Geschlecht')
patientTable.heading('Diagnose',text='Diagnose')
patientTable.heading('Nebendiagnosen',text='Nebendiagnosen')
patientTable.heading('Aufgenommen am',text='Aufgenommen am')
patientTable.heading('Aufgenommen um',text='Aufgenommen um')
Hoffe ihr könnt mir da einen guten Anhaltspunkt geben :)

Danke schon einmal :)
Kayd
User
Beiträge: 2
Registriert: Sonntag 30. April 2023, 14:15

Es sind 2 Tabellen (fall, patienten) -- In Fall muss zB die PatientenID mit angegeben werden, damit möchte ich in der patienten-tabelle die restlichen Daten wie Name, Vorname, Geburtstag usw abrufen.
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kayd: Du solltest vor GUI (und Datenbank) besser noch einmal einen Schritt zurück machen und erst einmal Python lernen. Also schön der Reihe nach, mit Anweisungen, Programmfluss, Funktionen, und dann Klassen. Bevor Du etwas machst wofür man das Wissen von diesen ganzen Themen bereits braucht.

Die eigentliche Frage hier ist auch gar keine Python-Frage und hat auch nichts mit der GUI zu tun, sondern ist eine Frage zu relationalen Datenbanken und SQL. Tabellen in einer Abfrage verknüpfen sind SQL-Grundlagen.

Anmerkungen zum Quelltext:

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Daraus folgt das alles was Funktionen (und Methoden) ausser Konstanten benötigen, als Argument(e) übergeben werden muss. `load_patient()` braucht also `varstation`, `mycursor`, und `patientTable` als Argumente.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Namen sollten keine Abkürzungen enthalten und keine unnötigen Anhängsel wie `my`.

Bei den ``if``/``elif``-Zweigen ist die zweite und letzte Codezeile überall gleich. So etwas gehört dann *einmal* *hinter* dieses Konstrukt.

Es fehlt ein ``else``-Zweig, denn im Moment ist mehr oder weniger undefiniert was passiert wenn `varstation` einen anderen als die getesteten Werte hat.

Wobei das gesamte Konstrukt auch etwas fragwürdig ist, denn offenbar ist `varstation` die ID die in der Abfrage verwendet werden sollte. Statt da also jeden Fall explizit mit einer festen Abfrage hin zu schreiben, würde man einfach die Variable in die Abfrage einsetzen lassen. Von der Datenbankanbindung! *Nicht* selbst als Zeichenkette hinein formatieren.

Grunddatentypen haben nichts in Namen verloren. Den Typen ändert man gar nicht so selten mal während der Programmentwicklung und dann muss man überall im Programm die betroffenen Namen ändern, oder man hat falsche, irreführende Namen im Quelltext.

Bei SQL-Abfragen sollte man explizit die Spalten schreiben, statt einfach nur ein *. Dann weiss der Leser vom Quelltext wie viele Spalten das sind und anhand sinnvoller Namen auch was sie bedeuten, und das ganze ist robust(er) gegen Änderungen am Datenbankschema was Spaltenanzahl und Reihenfolge angeht.

Schlüsselworte und Bezeichner sind in SQL „case insensitive“, weshalb man damit rechnen muss, dass Bezeichner in Fehlermeldungen komplett gross oder komplett klein ausgegeben werden, auch wenn man die im SQL anders geschrieben hat. Darum ist es ungünstig Worte nicht mit Unterstrichen zu trennen, denn in einer Fehlermeldung sieht man die Trennstellen sonst nicht.

Die Funktion könnte dann so aussehen:

Code: Alles auswählen

def load_patient(cursor, station_id, patient_table):
    #
    # TODO Use column names instead of ``*``.
    #
    cursor.execute("SELECT * FROM fall WHERE station_id = ?", station_id)
    patient_table.delete(*patient_table.get_children())
    for row in map(list, cursor.fetchall()):
        patient_table.insert("", END, values=row)
Wobei das mit dem Cursor für meinen Geschmack nicht so gut ist, weil Cursor eigentlich etwas eher kurzlebiges sind. Man würde da eher die Datenbankverbindung übergeben und in der Funktion für die Abfrage einen Cursor erstellen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten