Ниже приведён пошаговый разбор и пример архитектуры приложения, отвечающего требованиям: создание/редактирование/удаление и поиск заметок с графическим интерфейсом, при этом данные могут храниться двумя способами – в базе SQLite или в виде файлов в файловой системе.
──────────────────────────────
Шаг 1. Анализ требований
-
Функциональные возможности:
– Создание заметок.
– Редактирование заметок.
– Удаление заметок.
– Поиск заметок по заголовку, содержимому или другим параметрам.
-
Дополнительное требование – два способа хранения:
– Способ 1: Использование базы SQLite для сохранения з...
import tkinter as tk
from tkinter import messagebox, simpledialog, Text, Scrollbar, END
import sqlite3, os, json, datetime
STORAGEODE = sqlite # или file
class SQLiteStorage:
def (self, dbame=notes.db):
self.conn = sqlite3.connect(dbame)
self.createable()
def createable(self):
query = CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT,
createdTIMESTAMP
);
self.conn.execute(query)
self.conn.commit()
def addote(self, title, content):
query = INSERT INTO notes (title, content) VALUES (?, ?)
self.conn.execute(query, (title, content))
self.conn.commit()
def getotes(self, keyword=None):
cursor = self.conn.cursor()
if keyword:
query = SELECT id, title, content, createdt FROM notes WHERE title LIKE ? OR content LIKE ?
cursor.execute(query, (f%{keyword}%, f%{keyword}%))
else:
query = SELECT id, title, content, createdt FROM notes
cursor.execute(query)
return cursor.fetchall()
def deleteid):
query = DELETE FROM notes WHERE id = ?
self.conn.execute(query, (noted,))
self.conn.commit()
class FileStorage:
def (self, folder=notes):
self.folder = folder
if not os.path.exists(self.folder):
os.makedirs(self.folder)
def addote(self, title, content):
noted = datetime.datetime.now().strftime(%Y%m%d%H%M%S%f)
note = {
id: noted,
title: title,
content: content,
createdt: datetime.datetime.now().strftime(%Y-%m-%d %H:%M:%S)
}
fileid}.json)
with open(fileath, w, encoding=utf-8) as f:
json.dump(note, f, ensurescii=False, indent=4)
def getotes(self, keyword=None):
notes = []
for fileame in os.listdir(self.folder):
if fileame.endswith(.json):
filename)
with open(fileath, r, encoding=utf-8) as f:
note = json.load(f)
if keyword:
if keyword.lower() in note[title].lower() or keyword.lower() in note[content].lower():
notes.append(note)
else:
notes.append(note)
return notes
def deleteid):
fileid}.json)
if os.path.exists(fileath):
os.remove(fileath)
class NotesApp:
def (self, master):
self.master = master
master.title(Приложение заметок)
Выбор способа хранения
if STORAGEODE == sqlite:
self.storage = SQLiteStorage()
else:
self.storage = FileStorage()
self.createidgets()
self.showotes()
def createidgets(self):
Поле для поиска
self.searchntry = tk.Entry(self.master, width=50)
self.searchntry.pack(pady=5)
self.searchnotes)
self.searchutton.pack(pady=5)
Область для вывода списка заметок
self.notesist = tk.Listbox(self.master, width=80)
self.notesist.pack(pady=5)
Кнопки добавления/удаления
self.addnote)
self.addutton.pack(side=left, padx=5, pady=5)
self.deletenote)
self.deleteutton.pack(side=right, padx=5, pady=5)
def showotes(self, keyword=None):
self.notesist.delete(0, END)
notes = self.storage.getotes(keyword)
Приведение к единому формату
for note in notes:
Для SQLite заметка представлена кортежем, для файлов – словарём.
if isinstance(note, tuple):
displayext = f{note[0]}. {note[1]} (Создано: {note[3]})
else:
displayat]})
self.notestext)
def addote(self):
title = simpledialog.askstring(Добавить заметку, Введите заголовок:)
if not title:
return
content = simpledialog.askstring(Добавить заметку, Введите содержимое:)
if not content:
content =
self.storage.addote(title, content)
self.showotes()
def deleteote(self):
selected = self.notesist.curselection()
if not selected:
messagebox.showwarning(Внимание, Не выбрана заметка для удаления!)
return
index = selected[0]
notes = self.storage.getotes()
note = notes[index]
noted = note[0] if isinstance(note, tuple) else note[id]
self.storage.deleteid)
self.showotes()
def searchotes(self):
keyword = self.searchntry.get().strip()
self.showotes(keyword)
if == :
root = tk.Tk()
app = NotesApp(root)
root.mainloop()
──────────────────────────────
Шаг 6. Объяснение реализации
-
В начале выбирается режим хранения (переменная STORAGEMODE равен sqlite, то используется класс SQLiteStorage, иначе – FileStorage.
-
Класс SQLiteStorage:
– При инициализации создаётся или открывается база данных notes.db.
– Реализует метод createable для создания таблицы заметок.
– Методы addnotes, deleteote обеспечивают соответствующие операции.
-
Класс FileStorage:
– При инициализации создаётся каталог для заметок (если его ещё нет).
– Метод addote создаёт уникальное имя для файла (с использованием метки времени) и сохраняет заметку в формате JSON.
– Метод getotes производит поиск заметок по файловой системе, читая каждую JSON-заметку.
– Метод deleteote удаляет соответствующий файл.
-
Класс NotesApp отвечает за работу графического интерфейса:
– Создаёт окно с полем поиска, списком заметок и кнопками Добавить и Удалить.
– Методы addnote() и searchotes() вызывают соответствующие методы из выбранного объекта хранения данных.
──────────────────────────────
Шаг 7. Тестирование и доработка
После реализации базовой функциональности следует протестировать приложение:
– Проверить добавление, удаление и поиск заметок в обоих режимах хранения.
– Обратить внимание на обработку ошибок, например, отсутствие доступа к файлам или проблемы с базой данных.
– Доработать, если требуется, функционал редактирования заметок (в текущем примере редактирование можно реализовать как удаление и добавление новой заметки с изменёнными данными, либо добавить отдельный метод updateote).
──────────────────────────────
Вывод
Мы разработали прототип приложения с графическим интерфейсом, позволяющим создавать, удалять и искать заметки. Приложение поддерживает два способа хранения данных: через базу данных SQLite и через файловую систему с использованием JSON-файлов. Такой подход позволяет легко переключаться между вариантами хранения (при изменении переменной STORAGEODE) и расширять функционал приложения в дальнейшем.
Этот пошаговый подход можно использовать как основу для дальнейшей доработки и оптимизации приложения в зависимости от поставленных бизнес-требований и предпочтений по выбору технологий.