Teil 26: Umstieg auf SQLite – von JSON zur echten Datenbank


🎯 Ziel dieses Teils

✅ Aufgaben in SQLite-Datenbank speichern
✅ Aufgaben beim Start aus der DB laden
✅ Aufgaben hinzufügen, ändern, löschen – direkt in der DB
✅ JSON-Datei wird nicht mehr gebraucht


Warum überhaupt Datenbank?

JSON (bisher)SQLite (neu)
Nur für kleine ProjekteFür viele Daten & Benutzer
Eine Datei, alles manuellTabellen, Abfragen, Sicherheit
Nicht gleichzeitig nutzbarMehrere Benutzer möglich
Kein SuchfilterSQL-Suchabfragen, Sortierungen

→ SQLite ist eingebaut in Python. Du brauchst keine Server oder Extras.


Vorbereitung: Modul sqlite3 ist dabei

Du brauchst nichts installieren. SQLite ist Teil von Python.


Neue Struktur

todo-app/
├── app.py
├── db.sqlite                ← Neue Datenbank
├── static/
│   └── style.css
└── templates/
    ├── index.html
    └── bearbeiten.html

Schritt 1: Datenbank beim Start anlegen

In app.py, ganz oben:

import sqlite3
from flask import g

Dann:

DB_NAME = "db.sqlite"

def get_db():
    if "db" not in g:
        g.db = sqlite3.connect(DB_NAME)
        g.db.row_factory = sqlite3.Row
    return g.db

@app.teardown_appcontext
def close_db(error):
    if "db" in g:
        g.db.close()

Schritt 2: Datenbank initialisieren

Erstelle eine kleine Datei init_db.py mit folgendem Inhalt:

import sqlite3

connection = sqlite3.connect("db.sqlite")

with connection:
    connection.execute("""
        CREATE TABLE IF NOT EXISTS aufgaben (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            text TEXT NOT NULL,
            erledigt INTEGER NOT NULL DEFAULT 0
        );
    """)

print("📦 Datenbank erstellt!")

Dann im Terminal:

python init_db.py

Ergebnis: Datei db.sqlite wird erzeugt


Schritt 3: Aufgaben aus Datenbank laden

In startseite():

@app.route("/")
def startseite():
    db = get_db()
    cursor = db.execute("SELECT id, text, erledigt FROM aufgaben")
    daten = cursor.fetchall()

    aufgaben = [
        {"id": row["id"], "text": row["text"], "erledigt": bool(row["erledigt"])}
        for row in daten
    ]

    offen = sum(1 for a in aufgaben if not a["erledigt"])
    erledigt = sum(1 for a in aufgaben if a["erledigt"])
    sortierte = sorted(aufgaben, key=lambda a: a["erledigt"])

    return render_template("index.html", aufgaben=sortierte, offen=offen, erledigt=erledigt)

Schritt 4: Aufgaben in DB einfügen

In /hinzufuegen:

@app.route("/hinzufuegen", methods=["POST"])
def aufgabe_hinzufuegen():
    text = request.form.get("text")
    if text:
        db = get_db()
        db.execute("INSERT INTO aufgaben (text) VALUES (?)", (text.strip(),))
        db.commit()
    return redirect(url_for("startseite"))

Schritt 5: Aufgabenstatus ändern oder löschen

Als erledigt markieren:

@app.route("/erledigt/<int:id>")
def aufgabe_erledigen(id):
    db = get_db()
    db.execute("UPDATE aufgaben SET erledigt = 1 WHERE id = ?", (id,))
    db.commit()
    return redirect(url_for("startseite"))

Zurücksetzen:

@app.route("/zuruecksetzen/<int:id>")
def aufgabe_zuruecksetzen(id):
    db = get_db()
    db.execute("UPDATE aufgaben SET erledigt = 0 WHERE id = ?", (id,))
    db.commit()
    return redirect(url_for("startseite"))

Löschen:

@app.route("/loeschen/<int:id>")
def aufgabe_loeschen(id):
    db = get_db()
    db.execute("DELETE FROM aufgaben WHERE id = ?", (id,))
    db.commit()
    return redirect(url_for("startseite"))

Schritt 6: Bearbeiten

Beim Anzeigen der Bearbeitungsseite:

@app.route("/bearbeiten/<int:id>")
def aufgabe_bearbeiten(id):
    db = get_db()
    cursor = db.execute("SELECT text FROM aufgaben WHERE id = ?", (id,))
    row = cursor.fetchone()
    if row:
        return render_template("bearbeiten.html", id=id, text=row["text"])
    return redirect(url_for("startseite"))

Speichern:

@app.route("/bearbeiten/<int:id>", methods=["POST"])
def aufgabe_speichern(id):
    text = request.form.get("text")
    if text:
        db = get_db()
        db.execute("UPDATE aufgaben SET text = ? WHERE id = ?", (text.strip(), id))
        db.commit()
    return redirect(url_for("startseite"))

Schritt 7: HTML anpassen

In index.html, verwende aufgabe.id statt loop.index0:

<a href="/erledigt/{{ aufgabe.id }}">✅</a>
<a href="/zuruecksetzen/{{ aufgabe.id }}">🔁</a>
<a href="/bearbeiten/{{ aufgabe.id }}">✏️</a>
<a href="/loeschen/{{ aufgabe.id }}">❌</a>

Was du jetzt kannst

FähigkeitTechnik
Datenbank verwendensqlite3, get_db(), SQL
Aufgaben verwaltenINSERT, UPDATE, DELETE
SQL und HTML verbindenTemplate + id in der URL
Vollständiger UmstiegKeine JSON-Datei mehr nötig

Vorteile der Datenbank

  • ✅ Stabil bei mehreren Benutzern (bald!)
  • 🔍 Filter, Suche, Sortierung sind leichter
  • 🔄 Änderungen sind robuster
  • 💾 Struktur kann erweitert werden (z. B. Benutzer, Tags, Deadlines)

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert