Форум сайта python.su
Класс Child функция insert_data. Как правильно обратится к переменной с и сonn чтоб выполнялось добавление данных в БД.
import tkinter as tk from tkinter import ttk import sqlite3 class Main(tk.Frame): def __init__(self, root): super().__init__(root) self.init_main() def init_main(self): toolbar = tk.Frame(bg='#d7d8e0', bd=2) toolbar.pack(side=tk.TOP, fill=tk.X) self.add_img = tk.PhotoImage(file="add.gif") btn_open_dialog = tk.Button(toolbar, text='Добавить позицию', command=self.open_dialog, bg='#d7d8e0', bd=0, compound=tk.TOP, image=self.add_img) btn_open_dialog.pack(side=tk.LEFT) self.tree = ttk.Treeview(self, columns=('ID', 'description', 'costs', 'total', 'date'), height=15, show='headings') self.tree.column("ID", width=30, anchor=tk.CENTER) self.tree.column("description", width=250, anchor=tk.CENTER) self.tree.column("costs", width=150, anchor=tk.CENTER) self.tree.column("total", width=100, anchor=tk.CENTER) self.tree.column("date", width=100, anchor=tk.CENTER) self.tree.heading("ID", text='ID') self.tree.heading("description", text='Наименование') self.tree.heading("costs", text='Статья дохода/расхода') self.tree.heading("total", text='Сумма') self.tree.heading("date", text='Дата') self.tree.pack(side=tk.TOP, fill=tk.X) self.viewing_records() def run_query(self): conn = sqlite3.connect('finance.db') c = conn.cursor() c.execute( '''CREATE TABLE IF NOT EXISTS finance (id integer primary key, description text, costs text, total real, date current_timestamp)''') c.execute('''select * from finance''') conn.commit() return c def viewing_records(self): c = self.run_query() for row in c.fetchall(): self.tree.insert('', 'end', values=row) def open_dialog(self): Child() class Child(tk.Toplevel): def __init__(self): super().__init__(root) self.init_child() def init_child(self): self.title('Добавить доходы/расходы') self.geometry('400x220+400+300') self.resizable(False, False) label_description = tk.Label(self, text='Наименование:') label_description.place(x=50, y=50) label_select = tk.Label(self, text='Статья дохода/расхода:') label_select.place(x=50, y=80) label_sum = tk.Label(self, text='Сумма:') label_sum.place(x=50, y=110) self.entry_description = ttk.Entry(self) self.entry_description.place(x=200, y=50) self.entry_money = ttk.Entry(self) self.entry_money.place(x=200, y=110) self.combobox = ttk.Combobox(self, values=[u"Доход", u"Расход"]) self.combobox.current(0) self.combobox.place(x=200, y=80) btn_cancel = ttk.Button(self, text='Отмена', command=self.destroy) btn_cancel.place(x=300, y=170) btn_ok = ttk.Button(self, text='OK') btn_ok.place(x=220, y=170) btn_ok.bind('<Button-1>', lambda event: self.insert_data()) self.grab_set() self.focus_set() self.wait_window() def insert_data(self): c.execute('''INSERT INTO finance(description, costs, total) VALUES (?, ?, ?)''', (self.entry_description.get(), self.combobox.get(), self.entry_money.get())) conn.commit() '''conn.close()''' self.destroy() if __name__ == "__main__": root = tk.Tk() app = Main(root) app.pack() root.title("Домашние финансы") root.geometry("650x450+300+200") root.resizable(False, False) root.mainloop()
Офлайн
Ребят помогите! Может что-то нужно уточнить?
Офлайн
Надо сделать класс для управления базой данных. Потом ты его снаружи инициализируешь и инициализированный объект подаёшь в __init__ класса Main, где он сохраняется внутри класса. Когда создаёшь дочернее окно, в __init__ класса Child ты точно так же подаёшь этот сохранённый объект, где он сохраняется внутри класса.
Классы не должны знать друг про друга, но каждый класс для работы с базой данных принимает её снаружи, уже проинициализированную. Это мы делаем шаблон ООП интерфейс, где принимается какой-то интерфейс снаружи и внутри класса выполняются действия с этим интерфейсом, но при этом содержимое этого интерфейса нам неизвестно. Так ты можешь подавать любые базы данных снаружи (SQLite, MySQL, PostgreSQL), при этом что это за база, класс не знает, но может из неё что-то читать и что-то в неё сохранять через заданные методы интерфейса.
Это пример
>>> class Doing: ... def __init__(self, intobj): ... self.obj = intobj ... def do_action(self): ... self.obj.do() ... def repeat_action(self): ... self.obj.repeat() ... >>> class Cat: ... def do(self): ... print('meow') ... def repeat(self): ... print('meow meow meow') ... >>> class Dog: ... def do(self): ... print('woof') ... def repeat(self): ... print('woof woof woof') ... >>> class DB: ... def do(self): ... print('insert a into table') ... def repeat(self): ... print('insert a, a into table') ... >>> def do(obj): ... for i in range(5): ... obj.do_action() ... obj.repeat_action() ... >>> do(Doing(Cat())) meow meow meow meow meow meow meow meow >>> do(Doing(Dog())) woof woof woof woof woof woof woof woof >>> do(Doing(DB())) insert a into table insert a into table insert a into table insert a into table insert a into table insert a, a into table >>>
Отредактировано py.user.next (Сен. 4, 2017 11:28:40)
Офлайн
Огромное спасибо! Общая смысловая линия понятна, но вот с реализацией проблема…
Офлайн
Вытаскивай создание базы SQLite наружу из класса окна.
FeelgoodВот это должно происходить в классе DB, который ты должен сделать.conn = sqlite3.connect('finance.db')
FeelgoodПотом ты снаружи создаёшь базу и подаёшь её (уже готовую) в конструктор окна.app = Main(root)
app = Main(root, DB('finance.db'))
Feelgoodclass Main(tk.Frame): def __init__(self, root, db): super().__init__(root) self.db = db self.init_main()
Отредактировано py.user.next (Сен. 6, 2017 02:23:39)
Офлайн
py.user.next
Простите за наглость, я самоучка и учусь “гавнокодить”
Очень прошу показать реализацию моей проблемы!
Как говорится: “лучше один раз увидеть, чем тысячу раз услышать”)
Офлайн
примерно так
import tkinter as tk import sqlite3 class DB(): def __init__(self,dbname): self.name = dbname self.data = '' def query(self,q_str): try: conn = sqlite3.connect(self.name) c = conn.cursor() c.execute(q_str) self.data = c.fetchall() conn.commit() conn.close() except Exception as e: return str(e) else: s = '' for row in self.data: s += '\t'.join([str(i) for i in row]) +'\n' return s class W(tk.Frame): def __init__(self,parent): tk.Frame.__init__(self,parent) self.db = DB('test.db') self.pack(fill=tk.BOTH,expand=True) self.text = tk.Text(self) self.text.pack(fill=tk.BOTH,expand=True) frame = tk.Frame(self,bg="#ccc") self.entry = tk.Entry(frame,width = 64) self.entry.bind('<Return>',self.query) self.entry.grid(row=0,column=0) self.btn = tk.Button(frame,text = 'Query') self.btn.grid(row=0,column=1) self.btn.bind('<Button-1>',self.query) frame.pack(fill=tk.BOTH,expand=True) def query(self,event): q = self.entry.get() a = self.db.query(q) self.text.delete(1.0,tk.END) self.text.insert(1.0,a) if __name__ == "__main__": root = tk.Tk() app = W(root) root.geometry("600x400+100+100") root.mainloop()
Офлайн
FeelgoodВот без самих окон
Очень прошу показать реализацию моей проблемы!
import sqlite3 class SQLite: def __init__(self, filename): self.conn = sqlite3.connect(filename) self.cur = self.conn.cursor() def execute(self, cmd, subvars=None): if subvars is None: self.cur.execute(cmd) else: newcmd = translate_universal_to_sqlite3(cmd) self.cur.execute(newcmd, subvars) self.conn.commit() def __del__(self): self.conn.close() class DB: def __init__(self, db): self.db = db def execute(self, cmd): self.db.execute(cmd) def main(): root = tk.Tk() db = DB(SQLite('file.sqlite')) win1 = Main(root, db) win2 = Child(win1, db) root.mainloop() if __name__ == '__main__': main()
Отредактировано py.user.next (Ноя. 22, 2017 11:11:14)
Офлайн
py.user.next, можете построчно рассказать что делает эта функция, так как есть пробелы
Спасибо
def execute(self, cmd, subvars=None): if subvars is None: self.cur.execute(cmd) else: newcmd = translate_universal_to_sqlite3(cmd) self.cur.execute(newcmd, subvars) self.conn.commit()
Отредактировано Feelgood (Дек. 7, 2017 22:27:47)
Офлайн
Вот моя первая версия приложения и всё работало, верю что гавно код, но оставалось было решить только одну проблему, отображение введенной информации сразу после нажатие кнопки ОК, а не после закрытия и вновь открытия приложения.
import tkinter as tk from tkinter import ttk import sqlite3 conn = sqlite3.connect('finance.db') c = conn.cursor() c.execute( '''CREATE TABLE IF NOT EXISTS finance (id integer primary key, description text, costs text, total real, date current_timestamp)''') c.execute('''select * from finance''') class Main: def __init__(self, master): self.master = master self.master.title('Домашние финансы') self.master.geometry('650x450+300+200') self.master.resizable(False, False) toolbar = tk.Frame(master) toolbar.pack(side=tk.TOP, fill=tk.X) toolbar.config(bg='#d7d8e0', bd=2) self.add_img = tk.PhotoImage(file="add.gif") self.btnOpenDialog = tk.Button(toolbar, text='Добавить позицию', command=self.open_dialog, image=self.add_img) self.btnOpenDialog.pack(side=tk.LEFT) self.btnOpenDialog.config(bg='#d7d8e0', bd=0, compound=tk.TOP) self.tree = ttk.Treeview(self.master, columns=('ID', 'description', 'costs', 'total', 'date'), height=15, show='headings') self.tree.column("ID", width=30, anchor=tk.CENTER) self.tree.column("description", width=250, anchor=tk.CENTER) self.tree.column("costs", width=150, anchor=tk.CENTER) self.tree.column("total", width=100, anchor=tk.CENTER) self.tree.column("date", width=100, anchor=tk.CENTER) self.tree.heading("ID", text='ID') self.tree.heading("description", text='Наименование') self.tree.heading("costs", text='Статья дохода/расхода') self.tree.heading("total", text='Сумма') self.tree.heading("date", text='Дата') for row in c.fetchall(): self.tree.insert('', 'end', values=row) self.tree.yview() self.tree.pack(side=tk.TOP, fill=tk.X) self.master.mainloop() def open_dialog(self): Child(self.master) class Child: def __init__(self, master): self.slave = tk.Toplevel(master) self.slave.title('Добавить доходы/расходы') self.slave.geometry('400x220+400+300') self.slave.resizable(False, False) self.labelDescription = tk.Label(self.slave, text='Наименование:') self.labelDescription.place(x=50, y=50) self.labelSelect = tk.Label(self.slave, text='Статья дохода/расхода:') self.labelSelect.place(x=50, y=80) self.labelSum = tk.Label(self.slave, text='Сумма:') self.labelSum.place(x=50, y=110) self.entryDescription = ttk.Entry(self.slave) self.entryDescription.place(x=200, y=50) self.entryMoney = ttk.Entry(self.slave) self.entryMoney.place(x=200, y=110) self.combobox = ttk.Combobox(self.slave, values=[u"Доход", u"Расход"]) self.combobox.current(0) self.combobox.place(x=200, y=80) self.btnCancel = ttk.Button(self.slave, text='Отмена', command=self.slave.destroy) self.btnCancel.place(x=300, y=170) self.btnOk = ttk.Button(self.slave, text='OK') self.btnOk.place(x=220, y=170) self.btnOk.bind('<Button-1>', lambda event: self.insert_data(self.entryDescription.get(), self.combobox.get(), self.entryMoney.get())) self.slave.grab_set() self.slave.focus_set() self.slave.wait_window() def insert_data(self, description, costs, total): c.execute('''INSERT INTO finance(description, costs, total) VALUES (?, ?, ?)''', (description, costs, total)) conn.commit() '''conn.close()''' self.slave.destroy() root = tk.Tk() Main(root)
Офлайн