Tilbake

Flask 1.0 · 45 minutter

Intro til Flask og SQLite: HTTP GET/POST på egen maskin

I denne introduksjonslaben lager du en liten app med én funksjon: Du trykker på en knapp, Flask lagrer statusen i en SQLite-database, og siden viser siste lagrede status.

Målet med oppgaven

Du skal forstå kjernen i en tredelt arkitektur: nettleseren sender HTTP-forespørsler, Flask tolker dem, og SQLite lagrer dataene. Dette er den samme typen kommunikasjon som skjer i større systemer, bare i en veldig liten og synlig versjon.

GET

Hent siden

Nettleseren ber Flask om forsiden. Flask henter siste status fra databasen.

POST

Send status

Skjemaet sender valgt humør til backend-ruten /oppdater.

SQLite

Lagre data

Statusen lagres i filen intro.db, så dataene overlever restart.

Hvorfor dette ligner Supabase

I Supabase-introen bruker vi JavaScript i frontend til å lagre data slik: supabaseClient.from('messages').insert(...). Det ser ut som nettleseren snakker direkte med databasen.

Under panseret sender Supabase-klienten en HTTP-request til Supabase sin server i skyen. Serveren sjekker API-nøkkel, RLS-policyer og tabellregler før data lagres. I Flask bygger du en enkel versjon av den serveren selv, slik at den skjulte trafikken blir synlig.

Frontend

Nettleser

HTML-siden viser skjemaet og sender GET eller POST.

HTTP
Backend

Flask-server

Python-koden tar imot requesten, bestemmer hva som skal skje og lager svaret.

SQL
Database

SQLite

Data lagres i intro.db og kan hentes igjen senere.

Flyten i appen

1. Første sidevisning

Nettleseren sender GET /. Flask henter siste rad fra databasen.

2. Brukeren velger status

Skjemaet sender POST /oppdater med feltet humoer_input.

3. Flask redirecter

Statusen lagres i SQLite, og brukeren sendes tilbake til forsiden.

Mappestruktur

Lag en mappe som heter introduksjon.

introduksjon/
├── app.py
└── templates/
    └── index.html

Steg 1 - Backend: app.py

Denne filen setter opp Flask, lager en SQLite-database og håndterer både GET og POST.

import os
import sqlite3
from flask import Flask, render_template, request, redirect

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_PATH = os.path.join(BASE_DIR, "intro.db")

app = Flask(__name__)

# Opprett en minimal database med en gang serveren starter
with sqlite3.connect(DB_PATH) as conn:
    conn.execute("CREATE TABLE IF NOT EXISTS status (tilstand TEXT)")


@app.route("/")
def index():
    # HTTP GET: Hent det siste lagrede humøret fra databasen
    with sqlite3.connect(DB_PATH) as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT tilstand FROM status ORDER BY rowid DESC LIMIT 1")
        resultat = cursor.fetchone()

    gjeldende_humoer = resultat[0] if resultat else "Ingen data ennå"
    return render_template("index.html", humoer=gjeldende_humoer)


@app.route("/oppdater", methods=["POST"])
def oppdater():
    # HTTP POST: Ta imot dataene som ble sendt i forespørselen
    eget_humoer = (request.form.get("eget_humoer") or "").strip()
    valgt_humoer = eget_humoer or request.form.get("humoer_input")

    with sqlite3.connect(DB_PATH) as conn:
        conn.execute("INSERT INTO status (tilstand) VALUES (?)", (valgt_humoer,))

    return redirect("/")


if __name__ == "__main__":
    app.run(debug=True)
debug=True er nyttig i denne lokale introduksjonslaben fordi Flask viser tydelige feilmeldinger. Når appen deles med andre maskiner på nettverket, skal du bruke oppsettet i neste modul.

Hva betyr de viktigste delene?

app = Flask(__name__)

Starter Flask-appen. Dette er objektet som holder styr på rutene våre.

@app.route("/")

Bestemmer hva som skjer når nettleseren åpner forsiden med en GET-request.

render_template(...)

Sender HTML-filen tilbake til nettleseren, med variabelen humoer fylt inn.

request.form.get(...)

Leser verdier som kom fra skjemaet da brukeren trykket på lagre-knappen.

sqlite3.connect(...)

Åpner databasefilen intro.db, slik at Flask kan lese og lagre data.

redirect("/")

Sender nettleseren tilbake til forsiden etter at statusen er lagret.

Steg 2 - Frontend: templates/index.html

Legg merke til at skjemaet eksplisitt bruker method="POST" og sender data til /oppdater.

<!DOCTYPE html>
<html lang="no">
<head>
    <meta charset="UTF-8">
    <title>Humørsjekk</title>
</head>
<body>

    <h1>Akkurat nå føler jeg meg: {{ humoer }}</h1>

    <form action="/oppdater" method="POST">
        <p>Endre status:</p>

        <input type="radio" id="gla" name="humoer_input" value="Klar for koding!" checked>
        <label for="gla">Klar for koding!</label><br>

        <input type="radio" id="troett" name="humoer_input" value="Trenger kaffe...">
        <label for="troett">Trenger kaffe...</label><br><br>

        <label for="eget_humoer">Eller skriv din egen status:</label><br>
        <input type="text" id="eget_humoer" name="eget_humoer" maxlength="60"
               placeholder="F.eks. Nysgjerrig på Flask"><br><br>

        <button type="submit">Lagre i databasen</button>
    </form>

</body>
</html>

Steg 3 - Kjør prosjektet

  1. Åpne terminalen i mappen introduksjon.
  2. Lag et virtuelt Python-miljø, slik at Flask installeres lokalt i prosjektet.
  3. Start serveren og åpne adressen Flask viser, vanligvis http://127.0.0.1:5000.
Første gang du installerer Flask må maskinen ha internettilgang. Etter at Flask er installert i .venv, kan prosjektet kjøres lokalt uten internett.
Husk: Hver nye prosjektmappe med egen .venv starter med et tomt Python-miljø. Da må pakkene installeres på nytt i den mappen, for eksempel med python3 -m pip install flask.
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install flask
python3 app.py
Når terminalen viser (.venv) foran linjen, bruker du riktig Python-miljø for prosjektet.

Aha-opplevelser i terminalen

1. Se GET

Når siden lastes inn, viser terminalen GET / HTTP/1.1. Det er nettleseren som ber om siden.

2. Se POST

Når du trykker på knappen, viser terminalen POST /oppdater HTTP/1.1. Det er skjemaet som sender data.

3. Test persistens

Stopp serveren med Ctrl+C og start den igjen. Statusen ligger fortsatt i intro.db.

Se innholdet i databasen: Ikke åpne intro.db i vanlig tekstbehandler; SQLite-filer er binære og ser rotete ut. Stopp eventuelt serveren med Ctrl+C, og kjør:
sqlite3 intro.db "SELECT rowid, tilstand FROM status;"

Som dere ser, bruker vi her en standard SQL-spørring for å hente data fra databasen.

Kontrollspørsmål

  1. Hva er forskjellen på GET / og POST /oppdater?
  2. Hvorfor bruker vi redirect("/") etter at data er lagret?
  3. Hvor ligger dataene etter at serveren er stoppet?
  4. Hva skjuler Supabase for deg som Flask gjør synlig i denne laben?