Kap 5.6 · Guidad övning
Skämtregister med GUI, API och databas
Bygg ett skämtregister med tkinter, requests och SQLite.
Mål
Tre tekniker i ett program
tkinterskapar gränssnittet.requestshämtar data från ett API.sqlite3sparar data lokalt.- Funktioner kopplar ihop hela flödet.
Projektet
Skämtregister
- Hämta ett skämt från ett API.
- Visa skämtet i GUI:t.
- Spara skämtet i SQLite.
- Visa alla sparade skämt.
Helhetsbild
Så samarbetar delarna
Klick i tkinter
startar en Pythonfunktion
requests → API → JSON
hämtar ett nytt skämt
sqlite3 → skamt.db
sparar skämtet permanent
Förberedelse
Installera requests
python3 -m pip install requests
tkinter och sqlite3 ingår normalt i Python.
requests behöver vanligtvis installeras separat.
Hela programmet · del 1
Import, konstanter och databas
import tkinter as tk
import sqlite3
from contextlib import closing
import requests
DB_FIL = "skamt.db"
API_URL = "https://official-joke-api.appspot.com/random_joke"
senaste_skamt = None
def skapa_databas():
try:
with closing(sqlite3.connect(DB_FIL)) as conn:
conn.execute("CREATE TABLE IF NOT EXISTS skamt (...)")
conn.commit()
except sqlite3.Error as error:
skamt_label.config(text=f"Databasfel: {error}")
Hela programmet · del 2
Hämta säkert från API
def hamta_skamt():
global senaste_skamt
try:
response = requests.get(API_URL, timeout=10)
response.raise_for_status()
data = response.json()
senaste_skamt = (data["setup"], data["punchline"])
skamt_label.config(text=" - ".join(senaste_skamt))
except (requests.RequestException, KeyError, ValueError):
senaste_skamt = None
skamt_label.config(text="Kunde inte hämta ett skämt.")
Hela programmet · del 3
Spara och läsa med stängda anslutningar
def spara_skamt():
if senaste_skamt is None:
skamt_label.config(text="Hämta ett skämt först.")
return
with closing(sqlite3.connect(DB_FIL)) as conn:
conn.execute(
"INSERT INTO skamt (setup, punchline) VALUES (?, ?)",
senaste_skamt
)
conn.commit()
def visa_skamt():
with closing(sqlite3.connect(DB_FIL)) as conn:
rader = conn.execute("SELECT * FROM skamt").fetchall()
Databas
Skapa fil och tabell
with closing(sqlite3.connect(DB_FIL)) as conn:
conn.execute("CREATE TABLE IF NOT EXISTS skamt (...)")
closing() ser till att anslutningen alltid stängs.
CREATE TABLE IF NOT EXISTS skamt (...)
Tabellen skapas bara om den inte redan finns.
Tillstånd
Kom ihåg det senast hämtade skämtet
senaste_skamt = None
None betyder att inget skämt har hämtats ännu.
senaste_skamt = (
data["setup"],
data["punchline"]
)
Efter API-anropet innehåller variabeln en tuple med två texter.
global
Funktionen ändrar den yttre variabeln
def hamta_skamt():
global senaste_skamt
global anger att funktionen ska ändra variabeln utanför funktionen.
Utan raden skulle en tilldelning skapa en lokal variabel med samma namn.
API
Hämta och tolka ett skämt
response = requests.get(API_URL, timeout=10)
response.raise_for_status()
data = response.json()
requests.get() skickar en GET-förfrågan.
raise_for_status() upptäcker HTTP-fel.
json() gör svaret till Pythondata.
Visa resultat
API-data blir text i GUI:t
skamt_label.config(
text=f"{data['setup']} - {data['punchline']}"
)
setup innehåller skämtets första del.
punchline innehåller poängen.
config() ändrar texten i etiketten.
Spara
Spara bara när ett skämt finns
if senaste_skamt is not None:
with closing(sqlite3.connect(DB_FIL)) as conn:
conn.execute(
"INSERT INTO skamt (setup, punchline) VALUES (?, ?)",
senaste_skamt
)
conn.commit()
? är platshållare för värdena i tuplen.
commit() sparar ändringen permanent.
Läsa
Hämta alla databasrader
with closing(sqlite3.connect(DB_FIL)) as conn:
rader = conn.execute("SELECT * FROM skamt").fetchall()
fetchall() ger en lista med alla rader.
output = "\n".join(
[f"{rad[1]} - {rad[2]}" for rad in rader]
)
Varje rad görs om till en text på en egen rad.
GUI
Tre knappar, tre funktioner
tk.Button(
root,
text="Hämta skämt",
command=hamta_skamt
).pack()
Varje knapp får sin funktion via command.
hamta_skamtanvänder API:et.spara_skamtskriver till databasen.visa_skamtläser från databasen.
Prova själv
Interaktiv simulering: skämtregister
Vad händer i koden?
Hela flödet
Från klick till databas
- Användaren klickar på Hämta skämt.
- API-svaret visas och sparas i
senaste_skamt. - Användaren klickar på Spara skämt.
INSERTlägger in tuplen i databasen.commit()sparar ändringen.- Visa alla läser och visar raderna.
Testning
Kontrollera fler än normalfallet
- Klicka på Spara innan något har hämtats.
- Spara flera olika skämt.
- Spara samma skämt flera gånger.
- Starta om programmet och visa sparade skämt.
- Testa när API:et eller nätverket inte svarar.
Förbättring
API-anropet behöver felhantering
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
except requests.exceptions.RequestException:
skamt_label.config(
text="Kunde inte hämta ett skämt."
)
Övningens kod använder denna robustare variant för nätverks- och HTTP-fel.
Bygg vidare
Nästa steg
- lägg till ett sökfält
- ta bort valda skämt
- visa skämten i en lista
- förhindra dubbletter
- dela upp GUI, API och databas i egna moduler
- kontrollera tabellen med SQLite Viewer
Sammanfattning
Kom ihåg
- GUI:t startar funktioner genom knapptryck.
- API:et levererar data som JSON.
- En tuple håller det senast hämtade skämtet.
- SQLite sparar skämt mellan programkörningar.
- Funktionerna binder ihop GUI, API och databas.
- Testning och felhantering behövs för ett robust program.
Använd arbetsgången som stöd, men lämna inte in grundversionen oförändrad som Inlämningsuppgift 5.