treeWidget rekursiv füllen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
sucram
User
Beiträge: 2
Registriert: Donnerstag 17. Juni 2021, 09:02

Donnerstag 17. Juni 2021, 09:44

Hallo zusammen,

mein Ziel ist es eine Art Themenbaum zu erstellen. Die Themen mit den dazugehörigen IDs und Parent-IDs befinden sich in der SQlite-Tabelle "themenbaum":

Code: Alles auswählen

id	parent_id		thema				layer
1	0			Liegenschaftskataster				
2	1			Flurstücke			F1_FLURST
3	1			Gebäude				
4	3			geplante Gebäude		GEBAEUDE_GEPLANT
5	3			oberirdische Gebäude		GEBAEUDE_OBERIRDISCH
6	3			unterirdische Gebäude		GEBAEUDE_UNTERIRDISCH
7	3			Gebäudedetails			GEBAEUDEDETAIL_F
8	0			Jagdbezirke			JAGDBEZIRKE
9	8			Jagdbezirkskarte		JAGDBEZIRKSKARTE
10	3			Gebäudetetails			GEBAEUDEDETAIL_L
11	1			Nutzungsarten			NUTZUNGSARTEN_ALLE
12	1			Verkehr				VERKEHR_ALLE_NUTZUNGSARTEN
13	12			Plätze				VERKEHR_PLAETZE_F
14	12			Schienen			VERKEHR_SCHIENEN_F
15	12			Straßen				VERKEHR_STRASSEN_F
16	0			Rettungswesen				
17	16			Sirenenstandorte		SIRENENSTANDORTE
18	16			Rettungsbezirke			RETTUNGSBEZIRKE
Bei den Einträgen, deren parent_id 0 ist, handelt es sich somit um TopLevelItems. Bei diesem Beispiel gibt es nur drei Verschachtelungsebenen, es können aber durchaus mehr sein, d.h. ich versuche das Problem durch eine Rekursion zu lösen.

Im ersten Schritt habe ich das treeWidget jedoch mittels Schleifen bis zur dritten Ebene gefüllt:

Code: Alles auswählen

            connection = sqlite3.connect("C:/Datenbanken/Themenbaum.sqlite", isolation_level=None)
            cursor = connection.cursor()
            cursor.execute("SELECT id, parent_id, thema, layer FROM themenbaum where parent_id=0 ORDER BY id;")
            data = cursor.fetchall()
            self.dlg.treeWidget.clear()

            items = []
            for id, parent_id, thema, layer in data:
                item = QTreeWidgetItem([thema, layer])
                p_id = str(id)
                cursor.execute("SELECT id, thema, layer FROM themenbaum where parent_id='" + p_id + "' ORDER BY id;")
                child_data = cursor.fetchall()
                for c_id, c_thema, c_layer in child_data:
                    child = QTreeWidgetItem([c_thema, c_layer])
                    p_id = str(c_id)
                    child.setCheckState(0, 2)
                    cursor.execute("SELECT thema, layer FROM themenbaum where parent_id='" + p_id + "' ORDER BY id;")
                    cchild_data = cursor.fetchall()
                    for cc_thema, cc_layer in cchild_data:
                        cchild = QTreeWidgetItem([cc_thema, cc_layer])
                        cchild.setCheckState(0, 2)
                        child.addChild(cchild)
                    item.addChild(child)
                items.append(item)
            self.dlg.treeWidget.insertTopLevelItems(0, items)
Soweit funktioniert das ganze. Bei der Umsetzung der Rekursion dagegen hänge ich fest, sie läuft unendlich...:

Code: Alles auswählen

    def themenbaum(self, cursor, item, p_id):
        cursor.execute("SELECT id, thema, layer FROM themenbaum where parent_id='" + p_id + "' ORDER BY id;")
        data = cursor.fetchall()
        if not data:
            return item
        else:
            for id, thema, layer in data:
                child = QTreeWidgetItem([thema, layer])
                c_id = str(id)
                child.setCheckState(0, 2)
                item.addChild(self.themenbaum(cursor, child, c_id))

Code: Alles auswählen

            connection = sqlite3.connect("C:/Datenbanken/Themenbaum.sqlite", isolation_level=None)
            cursor = connection.cursor()
            cursor.execute("SELECT id, parent_id, thema, layer FROM themenbaum where parent_id=0 ORDER BY id;")
            data = cursor.fetchall()
            self.dlg.treeWidget.clear()

            items = []
            for id, parent_id, thema, layer in data:
                item = QTreeWidgetItem([thema, layer])
                p_id = str(id)
               items.append(self.themenbaum(cursor, item, p_id))
            self.dlg.treeWidget.insertTopLevelItems(0, items)

Kann mir jemand gedanklich auf die Sprünge helfen?


Viele Grüße,
Marcus
sucram
User
Beiträge: 2
Registriert: Donnerstag 17. Juni 2021, 09:02

Donnerstag 17. Juni 2021, 11:43

Das Problem habe ich bereits behoben, es fehlte lediglich die Zeile mit der Rückgabe:

Code: Alles auswählen

    def themenbaum(self, cursor, item, p_id):
        cursor.execute("SELECT id, thema, layer FROM themenbaum where parent_id='" + p_id + "' ORDER BY id;")
        data = cursor.fetchall()
        if not data:
            return item
        else:
            for id, thema, layer in data:
                child = QTreeWidgetItem([thema, layer])
                c_id = str(id)
                child.setCheckState(0, 2)
                item.addChild(self.themenbaum(cursor, child, c_id))
            return item
Sirius3
User
Beiträge: 14755
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 17. Juni 2021, 12:14

Man stückelt keine Werte per + in SQL-Statements, sondern benutzt Platzhalter.
Da im if- und im else-Block jeweils das selbe return steht, kann man es auch einfach am Ende schreiben, dann ist das if auch überflüssig.
Noch überflüssiger ist es, ein Argument, das man einer Funktion übergibt, wieder als Rückgabewert zu benutzen. Benutze keine kryptischen Abkürzungen. Wenn Du parent_id meinst, dann schreibe nicht p_id. Eine ID ist kein String, das in einen solchen umzuwandeln macht keinen Sinn.

Code: Alles auswählen

    def themenbaum(self, cursor, item, parent_id):
        cursor.execute("SELECT id, thema, layer FROM themenbaum where parent_id=?' ORDER BY id", (parent_id,))
        data = cursor.fetchall()
        for id, thema, layer in data:
            child = QTreeWidgetItem([thema, layer])
            child.setCheckState(0, 2)
            item.addChild(child)
            self.themenbaum(cursor, child, id)
Antworten