Programming-Challenges/41 Complete the update feature/address_book.py

216 lines
5.3 KiB
Python

import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
from pathlib import Path
ROOT = Path(__file__).resolve().parent
DB = ROOT / "address_book.db"
root = tk.Tk()
root.title("Address Book")
root.geometry("620x620")
root.resizable(False, False)
def connect():
return sqlite3.connect(DB)
def clear_entries():
f_name.delete(0, tk.END)
s_name.delete(0, tk.END)
mob.delete(0, tk.END)
email.delete(0, tk.END)
def submit():
values = (
f_name.get().strip(),
s_name.get().strip(),
mob.get().strip(),
email.get().strip(),
)
if not all(values):
messagebox.showwarning("Missing data", "Please fill in all four fields.")
return
conn = connect()
c = conn.cursor()
c.execute(
"""
INSERT INTO address_book (f_name, s_name, mob, email)
VALUES (?, ?, ?, ?)
""",
values,
)
conn.commit()
conn.close()
clear_entries()
search()
def search():
conn = connect()
c = conn.cursor()
c.execute("""
SELECT f_name, s_name, mob, email, oid
FROM address_book
ORDER BY oid
""")
records = c.fetchall()
conn.close()
output.delete("1.0", tk.END)
if not records:
output.insert(tk.END, "No records found.")
return
for record in records:
output.insert(
tk.END,
f"OID: {record[4]} | "
f"{record[0]} {record[1]} | "
f"Mobile: {record[2]} | "
f"Email: {record[3]}\n"
)
def delete_rec():
oid = id_no.get().strip()
if not oid.isdigit():
messagebox.showwarning("Invalid OID", "Enter a valid numeric OID.")
return
conn = connect()
c = conn.cursor()
c.execute("DELETE FROM address_book WHERE oid = ?", (int(oid),))
deleted = c.rowcount
conn.commit()
conn.close()
id_no.delete(0, tk.END)
if deleted:
messagebox.showinfo("Deleted", f"Record {oid} was deleted.")
else:
messagebox.showwarning("Not found", f"No record with OID {oid} exists.")
search()
def update_rec():
oid = id_no.get().strip()
column = update_column.get()
value = update_value.get().strip()
allowed_columns = {
"First Name": "f_name",
"Surname": "s_name",
"Mobile": "mob",
"Email": "email",
}
if not oid.isdigit():
messagebox.showwarning("Invalid OID", "Enter a valid numeric OID.")
return
if not value:
messagebox.showwarning("Missing value", "Enter the new value.")
return
# The column name cannot be passed as a normal SQL parameter,
# so only a value from this fixed whitelist is allowed.
db_column = allowed_columns[column]
conn = connect()
c = conn.cursor()
sql = "UPDATE address_book SET {} = ? WHERE oid = ?".format(db_column)
c.execute(sql, (value, int(oid)))
updated = c.rowcount
conn.commit()
conn.close()
if updated:
messagebox.showinfo(
"Updated",
f"Record {oid} was updated successfully."
)
id_no.delete(0, tk.END)
update_value.delete(0, tk.END)
search()
else:
messagebox.showwarning(
"Not found",
f"No record with OID {oid} exists."
)
# Create database/table if it does not already exist.
conn = connect()
c = conn.cursor()
c.execute("""
CREATE TABLE IF NOT EXISTS address_book (
f_name TEXT,
s_name TEXT,
mob TEXT,
email TEXT
)
""")
conn.commit()
conn.close()
# ---------- GUI ----------
tk.Label(root, text="First Name").grid(row=0, column=0, sticky="e", padx=8, pady=6)
f_name = tk.Entry(root, width=35)
f_name.grid(row=0, column=1, padx=8, pady=6)
tk.Label(root, text="Surname").grid(row=1, column=0, sticky="e", padx=8, pady=6)
s_name = tk.Entry(root, width=35)
s_name.grid(row=1, column=1, padx=8, pady=6)
tk.Label(root, text="Mobile").grid(row=2, column=0, sticky="e", padx=8, pady=6)
mob = tk.Entry(root, width=35)
mob.grid(row=2, column=1, padx=8, pady=6)
tk.Label(root, text="Email").grid(row=3, column=0, sticky="e", padx=8, pady=6)
email = tk.Entry(root, width=35)
email.grid(row=3, column=1, padx=8, pady=6)
tk.Button(root, text="Save", command=submit, width=14).grid(
row=4, column=0, padx=8, pady=10
)
tk.Button(root, text="Display all", command=search, width=14).grid(
row=4, column=1, sticky="w", padx=8, pady=10
)
tk.Label(root, text="Enter OID").grid(row=5, column=0, sticky="e", padx=8, pady=6)
id_no = tk.Entry(root, width=35)
id_no.grid(row=5, column=1, padx=8, pady=6)
tk.Button(root, text="Delete", command=delete_rec, width=14).grid(
row=6, column=0, padx=8, pady=8
)
tk.Label(root, text="Update field").grid(row=7, column=0, sticky="e", padx=8, pady=6)
update_column = ttk.Combobox(
root,
values=("First Name", "Surname", "Mobile", "Email"),
state="readonly",
width=32,
)
update_column.current(0)
update_column.grid(row=7, column=1, padx=8, pady=6)
tk.Label(root, text="New value").grid(row=8, column=0, sticky="e", padx=8, pady=6)
update_value = tk.Entry(root, width=35)
update_value.grid(row=8, column=1, padx=8, pady=6)
tk.Button(root, text="Update", command=update_rec, width=14).grid(
row=9, column=0, columnspan=2, pady=8
)
output = tk.Text(root, width=72, height=13, wrap="word")
output.grid(row=10, column=0, columnspan=2, padx=10, pady=12)
search()
root.mainloop()