Python зависимый комбинированный список на основе значений БД sqlite - PullRequest
0 голосов
/ 21 марта 2020

Я новичок в python и пытаюсь создать приложение для отслеживания бюджета с GUI. Для этого я вписываю каждую сумму, которую трачу в программе. Эти суммы хранятся в базе данных sqlite, где каждая сумма имеет общую категорию, а каждая категория имеет несколько подкатегорий. Это позволит генерировать статистику на основе категории и подкатегории, связанной с каждой введенной суммой.

Все возможные категории и подкатегории, которые я могу выбрать, хранятся в БД sqlite, и их можно выбрать в GUI через комбинированные списки. Моя цель заключается в том, чтобы при выборе определенной категории в комбинированном списке категорий в комбинированном списке подкатегорий отображались только подкатегории, связанные с этой категорией.

Проблема, с которой я сталкиваюсь, заключается в том, что я не могу ссылаться на значение, выбранное в поле со списком категории для фильтрации значений, которые будут отображаться в поле со списком подкатегории.

Часть моего кода, которая вызывает проблемы, выглядит следующим образом:

query = c.execute('SELECT Name_Subcategory FROM Subcategory WHERE ID_Category == Categorybox.get()')

Когда я меняю «Categorybox.get ()» на ID_Category, которую можно найти в моей БД sqlite (для пример 2) код работает, и возможные подкатегории в выпадающих списках подкатегорий фильтруются, чтобы показать только те подкатегории со значением ID_Category «2».

Кто-нибудь знает способ решения этой проблемы? Заранее благодарим за любые советы, которые вы можете дать.


Обзор Gui и таблицы БД

Overview Gui and DB tables

#connect database
conn = sqlite3.connect("Budget.db")

#create cursor
c = conn.cursor()


# Combobox_Category
def Cat_opt():
    conn = sqlite3.connect('Budget.db')
    query = c.execute('SELECT Name_Category FROM Category')
    data = []
    for row in c.fetchall():
        data.append(row[0])
    return data
    conn.close(row=1, column=0)

Category_box = Combobox(width=27)
Category_box['value'] = Cat_opt()

# Combobox_Subcategory
def Subcat_opt():
    conn = sqlite3.connect('Budget.db')
    query = c.execute('SELECT Name_Subcategory FROM Subcategory WHERE ID_Category == Categorybox.get()')
    data = []
    for row in c.fetchall():
        data.append(row[0])
    return data
    conn.close(row=1, column=0)

Subcategory_box = Combobox(width=27)
Subcategory_box['value'] = Subcat_opt()

1 Ответ

0 голосов
/ 25 марта 2020

Вопрос : На основании выбранной опции в первом Combobox запросить из таблицы sqlite3 values второго Combobox.


Основные точки :

  1. Привязать обратный вызов к событию '<<ComboboxSelected>>'

    self.bind('<<ComboboxSelected>>', self.on_selected)
    
  2. Запрос id выбранного элемента и передача его SubCategory.configure(query=<id>)

    def on_selected(self, event):
        _query = 'SELECT id FROM Category WHERE name == "{}"'.format(self.get())
        self.subcategory.configure(query=self.db.query(_query)[0])
    
  3. Запрос name на основе id и настройте SubCategory(Combobox) values.

    def configure(self, cnf=None, **kw):
        ...
            _query = 'SELECT name FROM SubCategory WHERE ID_Category == {}'.format(_query)
            super().configure(values=self.db.query(_query))
    

Импорт и данные

import tkinter as tk
import tkinter.ttk as ttk
import sqlite3


class DB:
    conn = None

    def __init__(self):
        if not DB.conn:
            DB.conn = sqlite3.connect(':memory:')

            print('DB.__init__()'.format())
            cur = DB.conn.cursor()
            cur.execute("CREATE TABLE IF NOT EXISTS Category(name TEXT, id INTEGER)")

            for _id, name in enumerate(('Revenues', 'Assets', 'Living expenses'), 1):
                cur.execute("INSERT INTO Category(id, name) VALUES (?,?)", (_id, name))

            cur.execute("CREATE TABLE IF NOT EXISTS SubCategory(name TEXT, id INTEGER, ID_Category INTEGER)")
            for _id, name in enumerate(('Salary', 'Saving account', 'Interest costs'), 1):
                cur.execute("INSERT INTO SubCategory(id, name, ID_Category) VALUES (?,?,?)", (_id, name, _id))

    def query(self, query):
        cur = DB.conn.cursor()
        return [record[0] for record in cur.execute(query)]

Настроенная категория Combobox

class Category(ttk.Combobox):
    def __init__(self, parent, **kwargs):
        self.subcategory = kwargs.pop('subcategory', None)
        self.db = kwargs.pop('db', None)

        # defaults
        kwargs['width'] = kwargs.get('width', 27)
        super().__init__(parent, values=(), **kwargs)

        self.configure(values=self.db.query('SELECT name FROM Category'))
        self.bind('<<ComboboxSelected>>', self.on_selected)

    def on_selected(self, event):
        _query = 'SELECT id FROM Category WHERE name == "{}"'.format(self.get())
        self.subcategory.configure(query=self.db.query(_query)[0])

Настроенная подкатегория Combobox

class SubCategory(ttk.Combobox):
    def __init__(self, parent, **kwargs):
        self.db = kwargs.pop('db', None)

        # defaults
        kwargs['width'] = kwargs.get('width', 27)
        super().__init__(parent, values=(), **kwargs)

    def configure(self, cnf=None, **kw):
        _query = kw.pop('query', None)
        if _query is not None:
            _query = 'SELECT name FROM SubCategory WHERE ID_Category == {}'.format(_query)
            super().configure(values=self.db.query(_query))
            self.event_generate('<Button-1>')
        else:
            super().configure(cnf, **kw)

Использование

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry('200x200')

        self.db = DB()

        subcategory = SubCategory(self, db=self.db)
        category = Category(self, subcategory=subcategory, db=self.db)

        category.pack()
        subcategory.pack()

        category.event_generate('<Button-1>')


if __name__ == "__main__":
    App().mainloop()

Протестировано с Python: 3,5 - 'TclVersion': 8,6 'TkVersion': 8,6

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...