Praktická příručka CRUD: vytvoříme správce úkolů v Pythonu s Tkinterem
CRUD (Create, Read, Update, Delete) je základní vzor pro práci s daty. V této příručce ho uvedeme do praxe vytvořením desktopové aplikace pro správu úkolů s využitím Pythonu, Tkinteru a JSON pro ukládání dat. Projekt je vhodný pro vývojáře, kteří chtějí upevnit základy OOP, práci se soubory a tvorbu grafických rozhraní.
Architektura aplikace a příprava prostředí
Naše aplikace bude sestávat z jednoho souboru app.py. Pro ukládání dat je zvolen JSON formát, jako nejjednodušší a nejnázornější pro podobné úlohy. Každý úkol je reprezentován jako slovník s poli: id (jedinečný identifikátor), text (popis) a completed (stav dokončení). Všechny úkoly jsou uloženy v seznamu, který je serializován do souboru tasks.json.
Před začátkem se ujistěte, že máte nainstalován Python 3.6 nebo vyšší. Tkinter je součástí standardní knihovny, takže není potřeba dodatečná instalace. Vytvořte nový adresář pro projekt a otevřete ho ve své IDE.
Implementace datového modelu a práce s JSON
Jako první implementujeme funkce pro načítání a ukládání dat. To je základ CRUD operací Read a Update.
import json
import os
TASKS_FILE = "tasks.json"
def load_tasks():
"""Načte seznam úkolů z JSON souboru."""
if not os.path.exists(TASKS_FILE):
return []
with open(TASKS_FILE, "r", encoding="utf-8") as f:
try:
return json.load(f)
except json.JSONDecodeError:
return []
def save_tasks(tasks):
"""Uloží seznam úkolů do JSON souboru."""
with open(TASKS_FILE, "w", encoding="utf-8") as f:
json.dump(tasks, f, ensure_ascii=False, indent=2)
def get_next_id(tasks):
"""Vygeneruje další jedinečné ID pro nový úkol."""
if not tasks:
return 1
return max(task["id"] for task in tasks) + 1
Klíčové aspekty této implementace:
- Funkce
load_taskszpracovává případy absence nebo poškození souboru. - Parametr
ensure_ascii=Falsevjson.dumpzajišťuje správné uložení diakritiky. indent=2formátuje JSON pro čitelnost.
Vytváření grafického rozhraní s Tkinter
Vytvoříme třídu TodoApp, která bude spravovat hlavní okno a widgety. Použijeme Tkinter pro vytvoření rozhraní, které se skládá z:
- Vstupního pole pro nový úkol.
- Seznamu (Listbox) pro zobrazení všech úkolů.
- Ovládacích tlačítek: přidání, označení jako hotovo, odstranění.
import tkinter as tk
from tkinter import messagebox
class TodoApp:
def __init__(self, root):
self.root = root
self.root.title("Správce úkolů")
self.root.geometry("500x400")
self.root.resizable(False, False)
self.tasks = load_tasks()
self.create_widgets()
self.refresh_task_list()
def create_widgets(self):
"""Inicializuje všechny prvky rozhraní."""
# Horní panel: vstupní pole a tlačítko pro přidání
top_frame = tk.Frame(self.root)
top_frame.pack(pady=10, padx=10, fill=tk.X)
self.entry = tk.Entry(top_frame, font=("Arial", 12))
self.entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))
self.entry.bind("<Return>", lambda event: self.add_task())
self.add_button = tk.Button(top_frame, text="➕ Přidat", command=self.add_task)
self.add_button.pack(side=tk.RIGHT)
# Seznam úkolů s posuvníkem
list_frame = tk.Frame(self.root)
list_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
scrollbar = tk.Scrollbar(list_frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.task_listbox = tk.Listbox(
list_frame,
font=("Arial", 11),
yscrollcommand=scrollbar.set,
selectmode=tk.SINGLE,
height=15
)
self.task_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.config(command=self.task_listbox.yview)
# Dolní panel: tlačítka akcí
bottom_frame = tk.Frame(self.root)
bottom_frame.pack(pady=10, padx=10, fill=tk.X)
self.done_button = tk.Button(bottom_frame, text="✅ Hotovo", command=self.mark_done)
self.done_button.pack(side=tk.LEFT, padx=5)
self.delete_button = tk.Button(bottom_frame, text="🗑 Odstranit", command=self.delete_task)
self.delete_button.pack(side=tk.LEFT, padx=5)
self.exit_button = tk.Button(bottom_frame, text="Konec", command=self.root.quit)
self.exit_button.pack(side=tk.RIGHT, padx=5)
def refresh_task_list(self):
"""Aktualizuje zobrazení seznamu úkolů v rozhraní."""
self.task_listbox.delete(0, tk.END)
for task in self.tasks:
status = "✓" if task["completed"] else "○"
display_text = f"{status} {task['id']}. {task['text']}"
self.task_listbox.insert(tk.END, display_text)
Metoda refresh_task_list implementuje operaci Read, zobrazující aktuální stav dat. Symboly ✓ a ○ vizualizují stav dokončení.
Implementace CRUD operací v rozhraní
Přidáme do třídy metody, které zpracovávají akce uživatele, provádějící odpovídající CRUD operace.
Create: přidání nového úkolu
def add_task(self):
"""Přidá nový úkol (Create)."""
text = self.entry.get().strip()
if not text:
messagebox.showwarning("Varování", "Zadejte text úkolu")
return
next_id = get_next_id(self.tasks)
new_task = {
"id": next_id,
"text": text,
"completed": False
}
self.tasks.append(new_task)
save_tasks(self.tasks)
self.entry.delete(0, tk.END)
self.refresh_task_list()
messagebox.showinfo("Úspěch", f"Úkol přidán (ID: {next_id})")
Update: označení úkolu jako hotovo
def mark_done(self):
"""Označí vybraný úkol jako hotový (Update)."""
selection = self.task_listbox.curselection()
if not selection:
messagebox.showwarning("Varování", "Vyberte úkol")
return
index = selection[0]
task_id = self.tasks[index]["id"]
for task in self.tasks:
if task["id"] == task_id:
if task["completed"]:
messagebox.showinfo("Informace", "Úkol je již hotový")
else:
task["completed"] = True
save_tasks(self.tasks)
self.refresh_task_list()
messagebox.showinfo("Úspěch", f"Úkol #{task_id} označen jako hotový")
return
Delete: odstranění úkolu
def delete_task(self):
"""Odstraní vybraný úkol (Delete)."""
selection = self.task_listbox.curselection()
if not selection:
messagebox.showwarning("Varování", "Vyberte úkol")
return
index = selection[0]
task_id = self.tasks[index]["id"]
task_text = self.tasks[index]["text"]
if messagebox.askyesno("Potvrzení", f"Odstranit úkol #{task_id} \"{task_text}\"?"):
del self.tasks[index]
save_tasks(self.tasks)
self.refresh_task_list()
messagebox.showinfo("Úspěch", f"Úkol #{task_id} odstraněn")
Každá metoda zahrnuje validaci vstupu, změnu dat v paměti, uložení do souboru a aktualizaci rozhraní. Použití messagebox zlepšuje UX, poskytuje zpětnou vazbu.
Sestavení a spuštění aplikace
Pro dokončení projektu spojíme všechny komponenty v jednom souboru a přidáme vstupní bod.
if __name__ == "__main__":
root = tk.Tk()
app = TodoApp(root)
root.mainloop()
Spusťte skript příkazem python app.py. Aplikace otevře okno, kde můžete testovat všechny CRUD operace. Data budou uložena mezi sezeními v souboru tasks.json.
Co je důležité
- CRUD je základ: Vzor Create, Read, Update, Delete je základní pro většinu aplikací pracujících s daty.
- JSON pro ukládání: Použití JSON souborů je jednoduchý a efektivní způsob ukládání dat pro malé projekty, které nevyžadují plnohodnotnou databázi.
- Tkinter pro GUI: Knihovna Tkinter umožňuje rychle vytvářet multiplatformní desktopová rozhraní bez externích závislostí.
- Struktura kódu: Jasné oddělení na datový model (práce s JSON), prezentaci (Tkinter) a logiku aplikace (třída TodoApp) zlepšuje udržovatelnost kódu.
- Zpracování chyb: Implementace zahrnuje kontroly správnosti vstupu a zpracování výjimek (např. poškozený JSON soubor).
Další rozvoj projektu
Tento správce úkolů lze rozšířit následujícími způsoby:
- Přidání kategorií úkolů s možností filtrování.
- Implementace termínů s použitím modulu
datetimea barevnou indikací. - Export dat do formátů CSV nebo Excel pro reportování.
- Integrace s databázemi (SQLite, PostgreSQL) pro spolehlivější ukládání.
- Vytvoření webové verze s využitím Flask nebo Django, což umožní procvičit stejné CRUD operace v jiném kontextu.
Taký přístup demonstruje, jak se základní koncepty programování aplikují v reálných projektech, poskytuje pevný základ pro studium složitějších témat.
— Editorial Team
Zatím žádné komentáře.