Kategorienhierarchie aufbauen und ausgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
cuthbert
User
Beiträge: 5
Registriert: Samstag 11. August 2007, 14:43

Hallo zusammen!

Ich schreibe mir gerade ein kleines System, um Texte, Anleitungen, Schnipsel etc. zu kategorisieren. Die Daten werden in einer Postgres-DB gespeichert, so auch die Kategorien. Für die Kategorien speichere ich dort auch, ob es übergeordnete Kategorien gibt (also bei jeder Kategorie die ID der übergeordneten, wenn es eine gibt). Nun hätte ich aber gerne auch eine Gesamtübersicht der Kategorien, möglichst auch hierarchisch (also die Unterkategorien etwas eingerückt) dargestellt. Mit SQL an sich lässt sich das nicht realisieren, daher hatte ich vor die ganzen Kategorien mit Angabe der id und übergeordneter id in Python einzulesen und dies dann dort entsprechend zu sortieren und aufzubereiten. Nur an diesem Punkt hakt es dann irgendwie.
Wie kann ich das am besten umsetzen, mit welchen Datentypen etc.?
Wäre nett, wenn ihr mir da ein wenig auf die Sprünge helfen könntet.

Gruß,
cuthbert
BlackJack

Datentyp ist ein Baum. Die Ausgabe löst man am einfachsten rekursiv. Der Aufbau ist linear machbar.

So etwas ähnliches ist hier Thema: http://www.python-forum.de/topic-10852.html

Da hatte ich diesen Quelltext verbrochen: http://www.ubuntuusers.de/paste/11331/

Der Baumaufbau steckt in `MenuTree.__init__()`. Erst werden in einer Schleife Knoten-Objekte erstellt und in einer weiteren Schleife werden diese dann zu einem Baum verbunden.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

cuthbert hat geschrieben:Nun hätte ich aber gerne auch eine Gesamtübersicht der Kategorien, möglichst auch hierarchisch
Hallo cuthbert!

Willkommen im Python-Forum!

Dazu habe ich auch einen Quellcode verbrochen. Als Datenbank wird hier SQLite eingesetzt, aber das kann man locker nach PostgreSQL umsetzen.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import os
import sys
try:
    from pysqlite2 import dbapi2 as sqlite3
except ImportError:
    import sqlite3
from pprint import pprint

FILENAME = "categories.sdb3"


def fill_db(conn):
    sql = """
    CREATE TABLE categories (
      id INT,
      parent INT NULL,
      name TEXT
    )
    """
    conn.execute(sql)
    conn.commit()
    
    sql = """
    INSERT INTO categories VALUES (
      ?, ?, ?
    )
    """
    values = (
        (1, None, "Hauptkategorie 1"),
        (2, None, "Hauptkategorie 2"),
        (3, None, "Hauptkategorie 3"),
        (4, 1, "Unterkategorie 1"),
        (5, 1, "Unterkategorie 2"),
        (6, 1, "Unterkategorie 3"),
        (7, 2, "Unterkategorie 1"),
        (8, 2, "Unterkategorie 2"),
        (9, 2, "Unterkategorie 3"),
        (10, 3, "Unterkategorie 1"),
        (11, 3, "Unterkategorie 2"),
        (12, 11, "UnterUnterkategorie 1"),
        (13, 3, "Unterkategorie 3"),
    )
    conn.executemany(sql, values)
    conn.commit()


def get_categories_list(conn):
    cat_index = {}
    cat_list = []
    sql = """
    SELECT id, parent, name FROM categories 
    ORDER BY parent, id
    """
    cur = conn.cursor()
    cur.execute(sql)
    for row in cur:
        id = row[0]
        parent_id = row[1]
        name = row[2]
        if parent_id is None:
            cat_list.append(
                {"id": id, "parent_id": parent_id, "name": name, "children": []}
            )
            cat_index[id] = cat_list[-1]
        else:
            parent = cat_index[parent_id]
            parent["children"].append(
                {"id": id, "parent_id": parent_id, "name": name, "children": []}
            )
            cat_index[id] = parent["children"][-1]
    
    return cat_list


def make_categories_tree(cat_list, cat_tree = "", indend = ""):
    for item in cat_list:
        cat_tree += "\n%s%s" % (indend, item["name"])
        if item["children"]:
            cat_tree = make_categories_tree(item["children"], cat_tree, indend = indend + " ")
    
    return cat_tree
    

def main():
    
    # Zum TESTEN -- Alte DB löschen
    if os.path.isfile(FILENAME):
        os.remove(FILENAME)
    
    # SQLite-Connection
    conn = sqlite3.connect(FILENAME)
    
    # Tabelle erstellen und mit Werten füllen
    fill_db(conn)
    
    # Daten von der Tabelle als Liste holen
    cat_list = get_categories_list(conn)
    pprint(cat_list)
    
    # Daten als Baum ausgeben
    cat_tree = make_categories_tree(cat_list)
    print cat_tree
    
    # Featisch Meista :-)
    conn.close()


if __name__ == "__main__":
    main()

Code: Alles auswählen

[{'children': [{'children': [],
                'id': 4,
                'name': u'Unterkategorie 1',
                'parent_id': 1},
               {'children': [],
                'id': 5,
                'name': u'Unterkategorie 2',
                'parent_id': 1},
               {'children': [],
                'id': 6,
                'name': u'Unterkategorie 3',
                'parent_id': 1}],
  'id': 1,
  'name': u'Hauptkategorie 1',
  'parent_id': None},
 {'children': [{'children': [],
                'id': 7,
                'name': u'Unterkategorie 1',
                'parent_id': 2},
               {'children': [],
                'id': 8,
                'name': u'Unterkategorie 2',
                'parent_id': 2},
               {'children': [],
                'id': 9,
                'name': u'Unterkategorie 3',
                'parent_id': 2}],
  'id': 2,
  'name': u'Hauptkategorie 2',
  'parent_id': None},
 {'children': [{'children': [],
                'id': 10,
                'name': u'Unterkategorie 1',
                'parent_id': 3},
               {'children': [{'children': [],
                              'id': 12,
                              'name': u'UnterUnterkategorie 1',
                              'parent_id': 11}],
                'id': 11,
                'name': u'Unterkategorie 2',
                'parent_id': 3},
               {'children': [],
                'id': 13,
                'name': u'Unterkategorie 3',
                'parent_id': 3}],
  'id': 3,
  'name': u'Hauptkategorie 3',
  'parent_id': None}]

Hauptkategorie 1
  Unterkategorie 1
  Unterkategorie 2
  Unterkategorie 3
Hauptkategorie 2
  Unterkategorie 1
  Unterkategorie 2
  Unterkategorie 3
Hauptkategorie 3
  Unterkategorie 1
  Unterkategorie 2
    UnterUnterkategorie 1
  Unterkategorie 3
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten