Seite 1 von 1

tkinter.combobox und Foreign Key

Verfasst: Samstag 10. August 2024, 20:36
von guhamail
Hallo,

ich bin dabei ein wenig mit tkinter und sqlite rumzuspielen. Das Ganze erfüllt nur den Zweck des dazu lernens, also kein produktiver Einsatz.

Ich habe eine Datenbank mit den folgenden Tabellen angelegt:

Code: Alles auswählen

c.execute('''
CREATE TABLE IF NOT EXISTS genders (
    gender_id INTEGER PRIMARY KEY,
    gender_name TEXT NOT NULL
)
''')

c.execute('''
CREATE TABLE IF NOT EXISTS names (
    name_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    gender_id INTEGER,
    FOREIGN KEY (gender_id) REFERENCES genders (gender_id)
)
''')

c.execute("INSERT OR IGNORE INTO genders (gender_id, gender_name) VALUES (1, 'Male')")
c.execute("INSERT OR IGNORE INTO genders (gender_id, gender_name) VALUES (2, 'Female')")
c.execute("INSERT OR IGNORE INTO genders (gender_id, gender_name) VALUES (3, 'Other')")

Jetzt möchte ich mit tkinter ein Formular bauen, um die Tabelle names mit Daten zu befüllen. Für gender möchte ich eine Combobox verwenden, welche die Werte gender_name aus der Tabelle genders enthält. Wenn ich einen neuen Datensatz in names speichern möchte, benötige ich allerdings die gender_id und nicht gender_name.

Mir fehlt grad eine Idee, wie ich das hinbekomme. Könnt ihr mir weiter helfen?

Re: tkinter.combobox und Foreign Key

Verfasst: Samstag 10. August 2024, 22:29
von __blackjack__
@guhamail: Erstell ein Wörterbuch das den Namen auf die ID abbildet. Dann kannst Du da einfach nachschauen.

Zu den SQL-Namen: Die Tabellennamen sollten eher in der Einzahl sein, also `gender` und `name`, denn das ist so ähnlich wie eine Klassendefinition, da wird *ein* Datensatz beschrieben.

Den Tabellennamen sollte man nicht noch mal in den Attributen wiederholen. Also `genders.gender_id` und `genders.gender_name` sollte eher `gender.id` und `gender.name` sein, und `names.name_id` eher `name.id` sein. Es macht keinen Sinn diese Information zu wiederholen.

Re: tkinter.combobox und Foreign Key

Verfasst: Samstag 10. August 2024, 23:54
von guhamail
Vielen Dank für die Hinweise. Habe ich gleich umgesetzt.

Ich habe mir auch eine Lösung überlegt:

Ich ziehe mir alle Datensätze von der Tabelle gender in eine Variable

Code: Alles auswählen

c.execute("SELECT  * FROM gender")
gender = c.fetchall()
beim Absenden des tkinter-Formulars ermittle ich, welcher Index in der gender-Combobox vom User ausgewählt wurde

Code: Alles auswählen

selected_index = gender_combobox.current()
mit diesem Index ziehe ich mir die id aus der Variable gender

Code: Alles auswählen

gender_id = gender[selected_index][0]
Mit dieser id kann ich die Speicherung in der Datenbank vornehmen.

Ist meine Lösung zu laienhaft??

Re: tkinter.combobox und Foreign Key

Verfasst: Sonntag 11. August 2024, 00:11
von __blackjack__
@guhamail: Das ist halt ein bisschen indirekt und undurchsichtig mit dem Sternchen und der magischen 0 wo man nicht weiss was da selektiert wird ohne die Tabellendefinition zu schauen. Und es hat das kleine Problem, dass das auch ”funktioniert” wenn man gar nichts ausgewählt hat, weil -1 auch ein gültiger Index ist.

Man kann bei der `Combobox` ja ein `StringVar`-Objekt verwenden. Ungetestet:

Code: Alles auswählen

    cursor.execute("SELECT name, id FROM gender")
    gender_name_to_id = dict(cursor.fetchall())

    ...

    gender_name = gender_name_var.get()
    if gender_name:
        gender_id = gender_name_to_id[gender_name]
        # do something with gender_id
Edit: Bei `gender.name` in der Datenbank würde es sich anbieten ein UNIQUE-Constraint anzugeben.