Rozdział 22 · Tworzenie stron internetowych z Python

Flask i SQLite: zapisują dane w bazie danych

Lista Python w sekcji 22.5 staje się tabelą SQLite, która przetrwa restart.

Teraz lista Python z sekcji 22.5 został zastąpiony bazą danych SQLite. Schemat jest prosty — Jedna tabela:

schema.sql
CREATE TABLE IF NOT EXISTS tasks (
    id INTEGER PRIMARY KEY,
    title TEXT NOT NULL,
    done INTEGER NOT NULL DEFAULT 0 CHECK (done IN (0, 1))
);

CHECK (done IN (0, 1)) jest dodatkowym ograniczeniem: SQLite nie pozwoli ci pisać do done nic poza 0 lub 1, Nawet jeśli gdzieś w kodzie aplikacji pojawi się jakiś błąd.

Jedno połączenie na żądanie

Otwieranie połączenia z bazą przy każdym małym połączeniu to marnotrawstwo, ale utrzymanie jednego Wspólne połączenie w całej aplikacji bez ostrożności jest ryzykowne przy równoległych rozwiązaniach zapytania. Flask oferuje wygodne miejsce na dane, które muszą być dokładnie w jednym miejscu zapytanie, jest obiektem g:

app.py
import sqlite3
from flask import Flask, g

app = Flask(__name__)
app.config["DATABASE"] = "zadachi.db"


def get_db():
    if "db" not in g:
        g.db = sqlite3.connect(app.config["DATABASE"])
        g.db.row_factory = sqlite3.Row
    return g.db


@app.teardown_appcontext
def close_db(exception=None):
    db = g.pop("db", None)
    if db is not None:
        db.close()
g jest powiązany z kontekstem aplikacji, a nie dosłownie z żądaniem
g przechowuje dane w kontekst aplikacji Flask. W normalnym przetwarzaniu HTTP- żądania ten kontekst występuje dokładnie od początku jego zakończenia i jest tworzony na nowo dla każdego kolejnego żądania — zatem w praktyce, g zachowuje się jak magazyn jednego zapytania, a nie jak wspólna zmienna, z której dane mogą przypadkowo „wyciec” do innego zapytania. teardown_appcontext jest wywoływane, gdy kontekst aplikacji jest zamknięty, nawet jeśli handler zawiodł, połączenie jest zawsze zamykane.

Trasy na górze bazy danych

app.py
@app.route("/")
def glavnaya():
    db = get_db()
    zadachi = db.execute("SELECT id, title, done FROM tasks ORDER BY id").fetchall()
    return render_template("index.html", zadachi=zadachi)


@app.route("/dobavit", methods=["POST"])
def dobavit():
    title = clean_title(request.form.get("zadacha", ""))
    if title is None:
        flash(„Nazwa zadania nie może być pusta i nie dłuższa niż 200 znaków.”)
        return redirect(url_for("glavnaya"), code=303)
    db = get_db()
    db.execute("INSERT INTO tasks (title) VALUES (?)", (title,))
    db.commit()
    return redirect(url_for("glavnaya"), code=303)

Proszę zauważyć: ? w SQL- zapytaniu i wartość jako osobny argument — to samo parametryzowane zapytanie z rozdziału 22.22, teraz wewnątrz aplikacji roboczej. flash(...) zapisuje pojawioną wiadomość Na następnej stronie po przekierowaniu następna pokazuje dokładnie, jak to działa Rozdział, 22:30. clean_title(...) jest prostą funkcją kontrolną z Rozdział 22.31: Pusta lub zbyt długa nazwa jest odrzucana przed dostępem do bazy danych.

Pusty lista zadania: "Mój lista zadań" tytuł, "Jeszcze żadnych zadań – dodaj pierwsze poniżej" oraz pole wprowadzania
Lista zadań bezpośrednio po init_db() – Tabela została utworzona, ale jest pusta.
Lista zadań z jedną linią „Kup chleb”
Po wysłaniu formularza: INSERT przeszedł, przekierowanie wróciło na / — zadanie jest widoczne na liście.
Ten sam lista: „Kup chleb”
Po kliknięciu na kółko: UPDATE tasks SET done = 1 – łańcuch znaków oznaczone jako ukończone.

Pełny plik roboczy — ze wszystkimi trasami, obsługą błędów i API — można znaleźć tutaj:

projects/flask/todo-app/app.py

Sprawdź sam: restartuj – zadania nadal są
Uciekaj python app.pydodaj kilka zadań, zatrzymaj proces (Ctrl+C) i zacznij od nowa. Lista pozostanie taka sama – dokładnie to, czego brakowało wersji w sekcji 22.5.
Lista zadań przeglądarki po wznowieniu procesu: "Kup chleb" nadal jest oznaczone jako zakończone, poniżej dodano nowy łańcuch znaków "Pisz testy dla API"
Prawdziwa kontrola: proces Flask został całkowicie zatrzymany i wznowiony na tym samym pliku bazy danych. „Kup chleb”
Praktyka: Flask na SQLite
Moduł flask nie jest zainstalowany w środowisku przeglądarki Pyodide – działa lokalnie w VS Code, PyCharm lub Jupyter
Praktyka kursuje lokalnie
Otwórz praktykę →