EINFÜHRUNG |
Im Umgang mit Datenbanken wird meistens ein benutzerfreundliches Dialogfenster verwendet, damit ein Anwender die wichtigsten Datenbankmanipulationen ohne Programmierkenntnisse durchführen kann. Die wichtigsten Manipulationen sind:
Trotzdem ist das Programm DbManager.py zu lang, um als Ganzes publiziert zu werden. Du kannst es aber von download/dbmanager.zip downloaden und dann in den TigerJython-Editor kopieren. Es verwendet die Datenbank schule.db und die Tabelle person, wie du sie im vorhergehenden Kapitel erzeugt hast. Die Tabelle sollte zu Beginn auch bereits die 5 Datensätze enthalten, die du mit dem Programm im vorhergehenden Kapitel erzeugt hast. |
DEN DATENBANK-MANAGER VERWENDEN |
Personendaten werden üblicherweise in einem Eingabedialog aufgenommen und dann in der Datenbank eingefügt. Beim Start des Managers wird ein Dialogfenster mit der ersten Person angezeigt. (Wenn die Datenbank noch keine Datensätze enthält ist, sind die Eingabefelder unter Information leer.)
Die Entwicklung von GUI-basierten Programmen erfordert eine konsequente Bedienungslogik, die sich an die üblichen Standards hält. Insbesondere sollte der Benutzer immer eine Rückmeldung über Erfolg oder Misserfolg seiner Aktionen erhalten. Dazu eignet sich eine Statuszeile gut. Wichtig ist auch, dass das Programm sogar bei unvernünftigen Eingaben niemals abstürzt. Hier ist folgende Bedienungslogik implementiert:
Das Programm ist strukturiert aufgebaut und enthält zum besseren Verständnis einige Kommentare. Im Folgenden werden wichtige Implementierungsverfahren erläutert. |
EREIGNISSTEUERUNG |
Der Einfachheit halber werden in der Klasse EntryDialog Button-Ereignisse nicht wie üblich mit Callbacks erfasst, sondern jedes Button-Objekt hat eine Methode isTouched(), die True zurückliefert, wenn ein Button geklickt wurde. Um die Button-Ereignisse zu erfassen, lässt du daher das Hauptprogramm in einer Ereignisschleife laufen, in der du alle Buttons abfragst, und rufst jeweils die entsprechenden Funktionen doFirst(), doLast(), usw. auf, in denen du die entsprechenden Aktionen ausführst. while not dlg.isDisposed(): if firstBtn.isTouched(): doFirst() if lastBtn.isTouched(): doLast() if nextBtn.isTouched(): doNext() ... Die Ereignisschleife wird abgebrochen, wenn du mit dem Close-Button der Titelzeile das Dialogfenster schliesst. |
NAVIGIEREN IM RESULTSET |
Beim Navigieren durch die Datensätze holst du zuerst mit einem SELECT-Befehl die Datensätze als Resultset. Da es in SQLite nicht möglich ist, im Resultset nach vorne und wieder zurück zu navigieren, kopierst du den Resultset mit resultSet = cursor.fetchall() in eine globale Python-Liste, in der jeder Datensatz als Tupel enthalten ist: [(4, 'Bauer', 'Paul', 'Muri', 'm', 14), ... ] Zudem speicherst du den Index des aktuell angezeigten Datensatzes in der globalen Variablen currentIndex, damit du jederzeit weisst, welcher Datensatz gerade angezeigt wird und du leicht auf die Daten zugegriffen kannst, beispielsweise auf den Familiennamen des aktuellen Datensatzes mit fName = resultSet[currentIndex][1] |
EINFÜGEN EINES NEUEN DATENSATZES |
Beim Klicken auf den Button Insert wird das System in einen speziellen Zustand versetzt, bei dem die globale Variablen isInsertMode auf True gesetzt ist. Die Eingabefelder werden gelöscht und die Navigation unterbunden. Beim Drücken von Save untersuchst du zuerst die Eingabewerte mit der Funktion validate() auf offensichtliche Fehler und schreibst eine gegebenenfalls Fehlermeldung aus. Ein Datensatz mit gleichem Familien- und Vornamen wird ebenfalls zurückgewiesen, damit eine Eindeutigkeit der Personen bezüglich ihres vollen Namens gewährleistet ist. Dies ist besonders beim Suchen wichtig, weil es nur eine einzige Person mit einem bestimmten Familien- und Vornamen geben sollte. |
SUCHEN, WILDCARDS |
Beim Klicken auf den Button Search werden Familien- und Vorname aus den Search-Eingabefeldern ausgelesen und mit einem SELECT-Befehl danach gesucht. Dabei wird aber nicht auf exakte Übereinstimmung geprüft, sondern LIKE verwendet. Damit können im Suchnamen auch Wildcards % verwendet werden, die an Stelle von beliebig vielen Buchstaben stehen. Es kann auch der Wildcard _ verwendet werden, der für genau einen Buchstaben steht. Der entsprechende SQL-Befehl lautet: "SELECT * FROM person WHERE familienname LIKE '%s'
AND vorname LIKE '%s'" %(familienname, vorname)
Gibt es mehrere Datensätze, welche die Suchbedingung erfüllen, wird der erste Datensatz des Resultsets angezeigt. |
DATENSATZ MUTIEREN ODER LÖSCHEN |
Ein angezeigter Datensatz kann auch verändert werden. Dabei wird der SQL-Befehl UPDATE person SET familienname = ... verwendet. Beim Löschen wird der SQL-Befehl DELETE FROM person WHERE familienname = ... verwendet. Bei beiden ist es wichtig, dass Familien- und Vorname den Datensatz eindeutig identifizieren. |
MEMO |
Im Gegensatz zu einer Tabellenkalkulation spielt die Reihenfolge der Datensätze (Zeilen) in der Datenbank keine Rolle und sollte nie ein wichtiges Kriterium sein. Darum darf die Reihenfolge im Resultset eines SELECT-Befehls nur dann eine Rolle spielen, wenn mit ORDER eine bestimmte Reihenfolge erzwungen wird. Dies ist in der Funktion getAllRecords() mit dem SQL-Befehl SELECT * FROM person ORDER BY familienname, vorname der Fall, wo zuerst mit der alphabetischen Reihenfolge der Familiennamen und bei Gleichheit mit der Reihenfolge der Vornamen geordnet wird. Bei Namen mit Akzenten ist allerdings die Reihenfolge problematisch. |
AUFGABEN |
|