Anfänger-Problem bei Änderung eines Datensatzes mit sqlite3

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
19feet
User
Beiträge: 7
Registriert: Mittwoch 27. Juni 2012, 21:04

Ich bin ein Neuling bezüglich der Programmiersprache python und nutze seit Jahren privat Ubuntu und Fedora. Nach 15 Jahren hat mich wieder die Programmier-Sucht erfasst und ich will ein relativ einfaches Programm schreiben und im Erfolgsfall unter GNU-Lizenz veröffentlichen.
Allerdings hakt es bereits bei der Datenbankprogrammierung mit sqlite3.
Aktuelles Problem ist, dass ich über die grafische Oberfläche eine Änderung eines einzelnen, bestimmten Datensatzes nicht in die Datenbank geschrieben bekomme. Die Änderung an der (parallel) angezeigten Tabelle (=Treeview =Baumansicht) funktioniert jedoch.
Hier ist der Code der Aktionen etc. (Datei: tnote.py):

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: utf-8-*-

from gi.repository import Gtk
import random, sqlite3


# Erstellung der Datenbankdatei mit einer Tabelle mit zwei Spalten "vorname" und "nachname"

con = sqlite3.connect('testdb1.db')
con.isolation_level = None
cur=con.cursor()

con.execute("CREATE TABLE IF NOT EXISTS schueler (vorname TEXT, nachname TEXT)")

def add_cell_renderer(control, col_no=0, renderer=None, attr='text'):
    if renderer is None:
        renderer=Gtk.CellRendererText()
    control.pack_start(renderer, True)
    control.add_attribute(renderer, attr, col_no)
    
def create_treeview_column(widget, title, col_no, renderer=None, attr='text'):
    column = Gtk.TreeViewColumn(title)
    widget.append_column(column)
    add_cell_renderer(column, col_no, renderer, attr)

def set_entry_completion(entry, completion, col_no, renderer=None):
    add_cell_renderer(completion, col_no, renderer)
    entry.set_completion(completion)



class TnoteWindow(object):
    def __init__(self):
        self.builder = Gtk.Builder()
        self.builder.add_from_file("tnote.ui")
        self.builder.connect_signals(self)

	#Daten der Datenbank werden ausgelesen und in Tabelle (=TreeView =Baumansicht) angezeigt
        rows = con.execute("SELECT * FROM schueler")

	for row in rows:
	    self.obj('ls_kdaten').append((row[0], row[1]))

        ## Erzeuge Spalten für Tabelle (=TreeView =Baumansicht) in Grafikmodus
        create_treeview_column(self.obj('tv_kdaten'), 'Vorname', 0,
                               Gtk.CellRendererSpin())

        create_treeview_column(self.obj('tv_kdaten'), 'Nachname', 1,
                               Gtk.CellRendererText())

        
        ## Erstes Element der Liste auswählen
        self.obj('tv_kdaten').set_cursor(0)


    def obj(self, name):
    	"""
	Gibt Glade-Object 'name' zurück
	"""
        return self.builder.get_object(name)
        

    def run(self):
    	"""
	Startet die zentrale Warteschleife von Gtk
	"""
        try:
            Gtk.main()
        except KeyboardInterrupt:
            pass
    

    def quit(self):
    	"""
        Verlässt die zentrale Warteschleife von Gtk

	"""
        Gtk.main_quit()

    
    def get_values(self):
        """
        Gibt die Werte aus den Eingabe-Elementen zurück
        """
        vorname = self.obj('e_vorname').get_text()
        nachname = self.obj('e_nachname').get_text()
        return vorname, nachname


    def set_values(self, values):
        """
        Setzt die Werte der Eingabe-Elemente
        """
        self.obj('e_vorname').set_text(values[0])
        self.obj('e_nachname').set_text(values[1])


    def remove_from_list(self, path):
        """
        Entfernt das Elemente mit Pfad 'pfad' aus der Liste
        """
	
        it = self.obj('ls_kdaten').get_iter(path)
        self.obj('ls_kdaten').remove(it)
        print path, len(self.obj('ls_kdaten'))
        if not self.obj('ls_kdaten').iter_is_valid(it):
            if path[0] > len(self.obj('ls_kdaten')):
                path=(path[0]-1,)
            else:
                self.set_values(('',''))
        self.obj('tv_kdaten').set_cursor(path)
        

###############################
## Signal-Behandlungsroutinen
###############################


#################
## Hauptfenster

    def on_window1_delete_event(self, *args):
        self.quit()

#############
## Aktionen

    def on_ac_quit_activate(self, action, *args):
        self.quit()

    def on_ac_neu_activate(self, action, *args):
        cur.execute("insert into schueler(vorname, nachname) VALUES('Vorname','Nachname')")
        self.obj('ls_kdaten').append(('Vorname', 'Nachname'))
        self.obj('tv_kdaten').set_cursor(len(self.obj('ls_kdaten'))-1)
        
    def on_ac_speichern_activate(self, action, *args):
#	Problembereich: Aus der angezeigten Tabelle (=TreeView =Baumansicht) und aus der Datenbank sollen zugleich ein einzelner, ausgewählter Datensatz (siehe 'def set_values') geändert werden
	vorname = self.builder.get_object('e_vorname').get_text()
	nachname = self.builder.get_object('e_nachname').get_text()
#       cur.execute("update schueler set vorname=?,nachname=? where id=?", (vorname,nachname))
        path = self.obj('tv_kdaten').get_cursor()[0]
        if path is not None: 
            self.obj('ls_kdaten')[path] = self.get_values()

    def on_ac_loeschen_activate(self, action, *args):
#	wird später weiterentwickelt und soll dann aus der angezeigten Tabelle (=TreeView =Baumansicht) und der Datenbank ein einzelner, ausgewählter Datensatz (siehe 'def set_values') gelöscht werden
        path = self.obj('tv_kdaten').get_cursor()[0]
        if path is not None: 
            self.remove_from_list(path)
	con.execute("delete from schueler").rowcount, "rows"

    def on_tv_kdaten_cursor_changed(self, action, *args):
        path = self.obj('tv_kdaten').get_cursor()[0]
        if path is not None:
            row = self.obj('ls_kdaten')[path]
            self.set_values(row)


if __name__ == '__main__':
    app = TnoteWindow()
    app.run()
Und hier ist der Code der grafischen Oberfläche (Datei: tnote.ui):

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="2.16"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkAction" id="ac_loeschen">
    <property name="stock_id">gtk-delete</property>
    <signal name="activate" handler="on_ac_loeschen_activate" swapped="no"/>
  </object>
  <object class="GtkAction" id="ac_neu">
    <property name="stock_id">gtk-new</property>
    <signal name="activate" handler="on_ac_neu_activate" swapped="no"/>
  </object>
  <object class="GtkAction" id="ac_quit">
    <property name="stock_id">gtk-quit</property>
    <signal name="activate" handler="on_ac_quit_activate" swapped="no"/>
  </object>
  <object class="GtkAction" id="ac_speichern">
    <property name="stock_id">gtk-save</property>
    <signal name="activate" handler="on_ac_speichern_activate" swapped="no"/>
  </object>
  <object class="GtkAdjustment" id="adjustment1">
    <property name="upper">100</property>
    <property name="step_increment">1</property>
    <property name="page_increment">10</property>
  </object>
  <object class="GtkEntryCompletion" id="ec_text">
    <property name="text_column">2</property>
    <property name="inline_completion">True</property>
  </object>
  <object class="GtkListStore" id="ls_kdaten">
    <columns>
      <!-- column-name Vorname -->
      <column type="gchararray"/>
      <!-- column-name Nachname -->
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkListStore" id="ls_farben">
    <columns>
      <!-- column-name Farbe -->
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkListStore" id="ls_text"/>
  <object class="GtkWindow" id="window1">
    <property name="width_request">500</property>
    <property name="height_request">500</property>
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="role">Listen-Demo</property>
    <signal name="delete-event" handler="on_window1_delete_event" swapped="no"/>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkMenuBar" id="menubar1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkMenuItem" id="menuitem1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="use_action_appearance">False</property>
                <property name="label" translatable="yes">_Datei</property>
                <property name="use_underline">True</property>
                <child type="submenu">
                  <object class="GtkMenu" id="menu1">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <child>
                      <object class="GtkImageMenuItem" id="imagemenuitem5">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="related_action">ac_quit</property>
                        <property name="use_underline">True</property>
                        <property name="use_stock">True</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkHBox" id="hbox1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkScrolledWindow" id="scrolledwindow1">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="hscrollbar_policy">automatic</property>
                <property name="vscrollbar_policy">automatic</property>
                <property name="shadow_type">etched-in</property>
                <child>
                  <object class="GtkTreeView" id="tv_kdaten">
                    <property name="width_request">200</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="model">ls_kdaten</property>
                    <property name="rules_hint">True</property>
                    <property name="search_column">2</property>
                    <signal name="cursor-changed" handler="on_tv_kdaten_cursor_changed" swapped="no"/>
                  </object>
                </child>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkTable" id="table1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="border_width">30</property>
                <property name="n_rows">4</property>
                <property name="n_columns">2</property>
                <child>
                  <object class="GtkLabel" id="label3">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Nachname</property>
                    <property name="use_underline">True</property>
                  </object>
                  <packing>
                    <property name="top_attach">2</property>
                    <property name="bottom_attach">3</property>
                    <property name="y_options"></property>
                  </packing>
                </child>
                <child>
                  <object class="GtkEntry" id="e_nachname">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="invisible_char">•</property>
                    <property name="primary_icon_activatable">False</property>
                    <property name="secondary_icon_activatable">False</property>
                    <property name="primary_icon_sensitive">True</property>
                    <property name="secondary_icon_sensitive">True</property>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">2</property>
                    <property name="bottom_attach">3</property>
                    <property name="y_options"></property>
                  </packing>
                </child>
                <child>
                  <object class="GtkHButtonBox" id="hbuttonbox1">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="spacing">5</property>
                    <property name="layout_style">spread</property>
                    <child>
                      <object class="GtkButton" id="bt_neu">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                        <property name="related_action">ac_neu</property>
                      </object>
                      <packing>
                        <property name="expand">False</property>
                        <property name="fill">False</property>
                        <property name="position">0</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkButton" id="bt_speichern">
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">False</property>
                        <property name="related_action">ac_speichern</property>
                      </object>
                      <packing>
                        <property name="expand">False</property>
                        <property name="fill">False</property>
                        <property name="position">1</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkButton" id="bt_loeschen">
                        <property name="label" translatable="yes">_Löschen</property>
                        <property name="visible">True</property>
                        <property name="can_focus">True</property>
                        <property name="receives_default">True</property>
                        <property name="related_action">ac_loeschen</property>
                        <property name="use_underline">True</property>
                      </object>
                      <packing>
                        <property name="expand">False</property>
                        <property name="fill">False</property>
                        <property name="position">2</property>
                      </packing>
                    </child>
                  </object>
                  <packing>
                    <property name="right_attach">2</property>
                    <property name="top_attach">3</property>
                    <property name="bottom_attach">4</property>
                    <property name="y_padding">5</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="label2">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">Vorname</property>
                    <property name="use_underline">True</property>
                  </object>
                  <packing>
                    <property name="top_attach">1</property>
                    <property name="bottom_attach">2</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="label4">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">label</property>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="label1">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">label</property>
                  </object>
                </child>
                <child>
                  <object class="GtkEntry" id="e_vorname">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="invisible_char">•</property>
                    <property name="primary_icon_activatable">False</property>
                    <property name="secondary_icon_activatable">False</property>
                    <property name="primary_icon_sensitive">True</property>
                    <property name="secondary_icon_sensitive">True</property>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">1</property>
                    <property name="bottom_attach">2</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>
Vielen Dank im Voraus. Zudem suche ich Mitstreiter, die Interesse an der gemeinsamen Programmierung haben. Dabei wäre ich bereits mit einem Ratgeber zufrieden, würde mich aber an aktive Mitprogrammierer freuen. Ziel ist ein Open-Source-Programm für Lehrer, welches den Lehrern die Notenverwaltung und Kommunikation zu den Eltern erleichtert. Ich selbst bin kein Lehrer, sondern Rechtsanwalt uńd will hierdurch Freunde und Lebensgefährtin unterstützen.
Zuletzt geändert von Anonymous am Mittwoch 27. Juni 2012, 22:09, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Hallo und Willkommen im Forum :)


Kannst du uns erklären was nicht funktioniert bzw. den Fehler einschränken? Es hat selten jemand Lust ein fremdes unbekanntes Programm zu debuggen, ohne einen Anhaltspunkt zu haben, und ich denke dafür ist dieses Forum auch nicht da ;)
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
BlackJack

@19feet: Mir war jetzt auch nicht nach näherem Studium des Quelltextes, aber ich habe mal die Suchfunktion vom Browser bemüht und nach `commit()` gesucht — und keinen Suchtreffer erhalten.
19feet
User
Beiträge: 7
Registriert: Mittwoch 27. Juni 2012, 21:04

BlackJack hat geschrieben:@19feet: Mir war jetzt auch nicht nach näherem Studium des Quelltextes, aber ich habe mal die Suchfunktion vom Browser bemüht und nach `commit()` gesucht — und keinen Suchtreffer erhalten.
Entsprechende 'commit()' Befehle habe ich bei mir nicht, da auch ohne sie ein Neueintrag in der Datenbank möglich war (Siehe 'con.isolation_level = None'). Gruß, 19feet
BlackJack

@19feet: Dann habe ich jetzt mal nach einem ``UPDATE`` gesucht, und ein *auskommentiertes* gefunden, bei dem zudem die Anzahl der Platzhalter nicht mit der Anzahl der Werte übereinstimmt.
19feet
User
Beiträge: 7
Registriert: Mittwoch 27. Juni 2012, 21:04

BlackJack hat geschrieben:@19feet: Dann habe ich jetzt mal nach einem ``UPDATE`` gesucht, und ein *auskommentiertes* gefunden, bei dem zudem die Anzahl der Platzhalter nicht mit der Anzahl der Werte übereinstimmt.
Danke für die ersten schnellen Antworten.

In der Tat habe ich die Befehlszeile nach meinem eigenen erfolglosen Versuch auskommentiert. Es geht im Grunde um die Stelle:

Code: Alles auswählen

def on_ac_speichern_activate(self, action, *args):
        vorname = self.builder.get_object('e_vorname').get_text()
        nachname = self.builder.get_object('e_nachname').get_text()
        cur.execute("update schueler set vorname=?,nachname=? where id=?", (vorname,nachname))
        path = self.obj('tv_kdaten').get_cursor()[0]
        if path is not None:
            self.obj('ls_kdaten')[path] = self.get_values()
Ziel ist, dass in der sqlite3 Datenbank ein einzelner Datensatz geändert wird. Die Daten aus der sqlite3-Datenbank werden auf der grafischen Oberfläche des Programms in einer Tabelle (GtkTreeview) angezeigt und können dort ausgewählt werden. Die Daten werden bei einer Auswahl in zwei Textfelder (e_vorname, e_nachname) übernommen und dort nochmals angezeigt. Dort können die Daten verändert werden. Durch den 'Speichern'-Knopf, der die Aktion 'on_ac_speichern_activate' aufruft, sollen die geänderten Daten sowohl in den entsprechenden Datensatz der sqlite3-Datenbank als auch in der Tabelle des Programms erscheinen.

Mit dem Neu-Knopf klappt es entsprechend, so dass ein neuer Datensatz in die sqlite3-Datenbank geschrieben und in der Tabelle am Ende angezeigt wird.

Ich hatte bei meinen Recherchen ein Beispiel gefunden, in dem behauptet wird, dass sqlite3 automatisch für jeden Datensatz eine aufsteigende Nummer vergibt, die unter 'rowid' läuft. Allerdings konnte ich diese nicht selbst abrufen bzw. durch

Code: Alles auswählen

cur.execute("update schueler set vorname=?,nachname=? where rowid=?", (vorname,nachname))
verwenden.

Auch ein zweiter Ansatz, wonach ich selber eine solche id mit

Code: Alles auswählen

con.execute("CREATE TABLE IF NOT EXISTS schueler (id INTEGER PRIMARY, KEYvorname TEXT, nachname TEXT)")
erzeugen und dann mit

Code: Alles auswählen

cur.execute("update schueler set vorname=?,nachname=? where id=?", (vorname,nachname))
verwenden wollte, scheiterte.
Wie kann ich dem 'Update' Befehl einen eindeutigen Datensatz zuweisen, wenn ich bspw. den Vornamen und Nachnamen ändern und sodann speichern möchte.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

1. Wie lautet die Fehlermeldung die erscheint?

2. Wenn du drei ? in deinem Statement hast musst du auch 3 Werte übergeben, welche die ? ersetzen. Du übergibst aber nur 2 (vorname und nachname)
BlackJack

@19feet: Auf DBMS-Interna wie eine implizite `rowid` sollte man sich nicht verlassen und selbst explizit einen Primärschlüssel festlegen. Was in den allermeisten Fällen ein „künstlicher” Schlüssel, also eine zusätzliche Spalte vom Typ ``INTEGER`` mit dem Zusatz ``PRIMARY KEY``, sein sollte. Natürliche Schlüssel ändern sich erfahrungsgemäss doch öfter als man das vermutet.

Und diese ID musst Du beim ``UPDATE`` natürlich mit angeben. Dazu musst Du sie auch aus der Datenbank abfragen. Und Dir merken zu welchem Datensatz sie in der Anzeige gehört.
19feet
User
Beiträge: 7
Registriert: Mittwoch 27. Juni 2012, 21:04

Mittlerweile habe ich das Problem mit der id durchschaut.

Allerdings lässt sich hierdurch noch immer nicht der neue Wert mit der "update"-Funktion in die Datenbank schreiben.

Ich habe nachfolgend das Problem anhand eines verkürzten Programms dargestellt:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sqlite3
import sys
 
con = sqlite3.connect('loeschen.db')
con.isolation_level = None
 
# Tabelle wird in der Datenbank erstellt. In der ersten Spalte wird eine fortlaufende Nummer erzeugt.
con.execute("CREATE TABLE IF NOT EXISTS schueler(id integer primary key autoincrement, vorname TEXT, nachname TEXT)")

# Das Programm fordert zur Eingabe zweier Werte auf, die sodann in die Datenbank geschrieben werden.
try:
    while True:
        vorname = raw_input("(Abbruch mit STRG-C) Gebe den Vornamen ein: ")
        nachname = raw_input("Gebe den Nachnamen von %s ein: " % vorname)
        con.execute("INSERT INTO schueler(vorname, nachname) VALUES(?, ?)", (vorname, nachname))
except:
    print ; print
 
# Das Programm zeigt sodann die gesamten Werte aus der Datenbank an. An erster Stelle steht die automatisch erzeugte, fortlaufende id.
rows = con.execute("SELECT * FROM schueler")
print "Die Namen der Schüler lauten:"
for row in rows:
    print row[0], row[1], row[2]

# Nunmehr fordert das Programm auf die 'id' des Datensatzes zu benennen, der verändert werden soll. Sodann werden die neuen Werte abgefragt.
aid = raw_input("Welcher Datensatz soll verändert werden (id)?: ")
vorname = raw_input("Gebe den neuen Vornamen ein: ")
nachname = raw_input("Gebe den neuen Nachnamen von %s ein: " % vorname)
con.execute("UPDATE schueler SET vorname=?, nachname=? WHERE id='aid'", (vorname, nachname))
con.commit() # aufgrund des eingangs genannten Befehls 'con.isolation_level = None' scheint der Befehl 'con.commit()' überflüssig zu sein

# Das Programm zeigt sodann die gesamten neuen Werte aus der Datenbank an.
rows = con.execute("SELECT * FROM schueler")
print "Die Namen der Schüler lauten:"
for row in rows:
    print row[0], row[1], row[2]

## Problem: Es werden wieder dieselben Ergebnisse aus der Datenbank, ohne die Änderung angezeigt
BlackJack

@19feet: Wie bist Du denn da drauf gekommen: ``id='aid'``? Es gibt natürlich keine `id` mit dem Wert 'aid'. „Richtige” Datenbanken hätten Dir hier auch um die Ohren gehauen, dass Du versuchst numerische Spaltenwerte mit einer Zeichenkette zu vergleichen.
19feet
User
Beiträge: 7
Registriert: Mittwoch 27. Juni 2012, 21:04

BlackJack hat geschrieben:@19feet: Wie bist Du denn da drauf gekommen: ``id='aid'``? Es gibt natürlich keine `id` mit dem Wert 'aid'. „Richtige” Datenbanken hätten Dir hier auch um die Ohren gehauen, dass Du versuchst numerische Spaltenwerte mit einer Zeichenkette zu vergleichen.
Danke für den richtigen Denkanstoß. Du hättest aber meine Wissenslücke gleich mit schließen und mir sagen können, dass es zutreffend:

Code: Alles auswählen

con.execute("UPDATE schueler SET vorname=?, nachname=? WHERE id=?", (vorname, nachname, aid))
heißen muss.
19feet
User
Beiträge: 7
Registriert: Mittwoch 27. Juni 2012, 21:04

Nachdem das Problem mit der Erzeugung, Abfrage, Veränderung und Löschen von Datensätzen in Tabellen in einer Datenbank in sqlite3 geklärt ist, verbleibt mein 2. Problem mit der Übertragung in 'Gtk.TreeView'-Tabellen.

Ich habe für das Problem das nachfolgende Programm anhand eines anderen Beispiels aus dem Internet dargestellt:

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: utf-8-*-

from gi.repository import Gtk
import sqlite3

# Erstellung der Datenbankdatei mit einer Tabelle mit drei Spalten: automatische "id", "vorname" und "nachname"
con = sqlite3.connect('testdb2.db')
con.isolation_level = None

con.execute("CREATE TABLE IF NOT EXISTS schueler(id integer primary key autoincrement, vorname TEXT, nachname TEXT)")

# In die Tabelle 'schueler' der Datenbank werden Beispielwerte eingetragen.
con.execute("insert into schueler(vorname,nachname) VALUES('Vorname','Nachname')")
con.execute("insert into schueler(vorname,nachname) VALUES('Vorname1','Nachname1')")
con.execute("insert into schueler(vorname,nachname) VALUES('Vorname2','Nachname2')")

class CellRendererTextWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="CellRendererText Example")

        self.set_default_size(800, 200)

        self.liststore = Gtk.ListStore(int, str, str)
	#war zuvor Teil des ursprünglichen COde-Beispiels ohne sqlite3 Datenbank und erzeugte dort die Beispielwerte.
        #self.liststore.append(["Fedora", "yo", "a"])
        #self.liststore.append(["Slackware", "ja", "b"])
        #self.liststore.append(["Sidux", "hey", "c"])

        treeview = Gtk.TreeView(model=self.liststore)

	#Daten der Datenbank sollen ausgelesen und in TreeView-Tabelle übernommen werden.
        rows = con.execute("SELECT * FROM schueler")

	for row in rows:
	    self.liststore.append(row[0], row[1], row[2]) # Hier liegt das Problem !!! Fehlermeldung:
	    ############################################################
	    # [...]
	    # File "./Beispiel-Renderer.py", line 36, in __init__
	    # self.liststore.append(row[0], row[1], row[2])
	    # TypeError: append() takes at most 2 arguments (4 given) 
	    ############################################################
	    #print row[0], row[1], row[2] # dient unkommentiert als Kontrolle, ob die Daten in der sqlite3-Datenbank eingetragen wurden.

	#Erzeugt erste Spalte mit unveränderbarem Wert.
        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
        treeview.append_column(column_text)

	#Erzeugt zweite Spalte mit änderbarem Wert.
        renderer_editabletext = Gtk.CellRendererText()
        renderer_editabletext.set_property("editable", True)

        column_editabletext = Gtk.TreeViewColumn("Editable Text",
            renderer_editabletext, text=1)
        treeview.append_column(column_editabletext)

        renderer_editabletext.connect("edited", self.text_edited)

	#Erzeugt dritte Spalte mit unveränderbarem Wert.
        column_text1 = Gtk.TreeViewColumn("Text1", renderer_text, text=2)
        treeview.append_column(column_text1)

        self.add(treeview)

    def text_edited(self, widget, path, text):
        self.liststore[path][1] = text


win = CellRendererTextWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Das Problem liegt meines Erachtens hier:

Code: Alles auswählen

        rows = con.execute("SELECT * FROM schueler")

	for row in rows:
	    self.liststore.append(row[0], row[1], row[2])
Wie lese ich richtig mit TreeView die Werte aus der sqlite3-Tabelle aus?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Die Fehlermeldung sagt doch schon alles
TypeError: append() takes at most 2 arguments (4 given)
Es werden zwei Parameter erwartet und du übergibst vier Stück. Ein Parameter ist in diesem fall die Liste selbst (der self-Parameter), d.h. append erwartet ein Argument (jenes, welches an die Liste angehängt werden soll) und du übergibst drei.

Noch als Anmerkung: Zeige doch bei deinem nächsten Problem bitte dem GESAMTEN Traceback und nicht nur den letzten Teil. In diesem Fall war die Fehler leicht zu erkennen, aber oft sind die davor aufgerufenen Funktionen durchaus wichtig.

Sebastian

Edit: Anmerkung 2: Temporäre Sqlite-Datenbanken kannst du auch im Speicher anlegen, dafür brauchst du keine extra Datei. Schau einfach mal in die Dokumentation zum Modul.
Das Leben ist wie ein Tennisball.
19feet
User
Beiträge: 7
Registriert: Mittwoch 27. Juni 2012, 21:04

Danke für den Denkanstoß.

Richtig lautet es also:

Code: Alles auswählen

	for row in rows:
	    self.liststore.append(row)
Die Überlegung mit

Code: Alles auswählen

con = sqlite3.connect(':memory:')
zu arbeiten ist auch richtig, allerdings brauche ich für weitere Versuche eine dauerhafte Datenbank.
Antworten