Python Forum
Problem with bindnig for query
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Problem with bindnig for query
#1
I had an issue with the results of my database query displaying curly brackets at the beginning and end of the results when it populated a tkinter widget. I found that if I change the insert string from output.insert(0,each_result) to output.insert(0,each_result[0]) it resolved the issue but it has raised a new issue.

The widget populated with the data now displays properly without the {} brackets but I can no longer click an item in that list displayed and run the query for that item.

The call to query the database for a selection made from the OptionMenu:
button = tkinter.Button(window_2, text="Load Category", font=('Times 9 bold'), bg = "#F9F8D6", fg = "#9A0615", command=select)
button.pack
The query for the selection made from the OptionMenu:
def select():
    try:
        output.delete(0, END)
        selection = var.get()
        c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC', {"selection": selection})
        results = c.fetchall()
        for each_result in results:
            output.insert(0,each_result[0])
    except:
        messagebox.showerror("DataBase Error", "Failed to load category")
The results of this query works properly and I no longer have the curly brackets showing the beginning and end of each result in the list that is displayed.(adding the [0] in the insert line resolved that)

The binding for the displayed list to be clicked:
output = tkinter.Listbox(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615', selectmode=SINGLE)
output.pack()
output.place(x=210, y=200)
yscroll = tkinter.Scrollbar(command=output.yview, orient=tkinter.VERTICAL)
yscroll.place(x=450, y=200)
output.configure(yscrollcommand=yscroll.set)
output.bind('<ButtonRelease-1>', getRecipe)
The procedure getRecipe to query the item in the displayed list when clicked:

This is the getRecipe procedure run when an item is clicked:
try:
    dish_type_entry.delete(0,END)
    index = output.curselection()[0]
    selected = output.get(index)
    c.execute('SELECT Dish_Type FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
    dish_type_results = c.fetchone()
    dish_type_entry.insert(0,dish_type_results)

    recipe_entry.delete(0,END)
    index = output.curselection()[0]
    selected = output.get(index)
    c.execute('SELECT Recipe FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
    recipe_results = c.fetchone()
    recipe_entry.insert(0,recipe_results[0])

    serves_entry.delete(0,END)
    index = output.curselection()[0]
    selected = output.get(index)
    c.execute('SELECT Serves FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
    serves_results = c.fetchone()\serves_entry.insert(0,serves_results[0])

    cook_time_entry.delete(0,END)
    index = output.curselection()[0]
    selected = output.get(index)
    c.execute('SELECT Cook_Time FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
    cook_time_results = c.fetchone()
    cook_time_entry.insert(0,cook_time_results[0])

    index = output.curselection()[0]
    selected = output.get(index)
    c.execute('SELECT Ingredients FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
    ingredients_results = c.fetchone()
    ingredients.insert(1.0,ingredients_results[0])
    ingredients.config(wrap=WORD)

    index = output.curselection()[0]
    selected = output.get(index)
    c.execute('SELECT Instructions FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
    instructions_results = c.fetchone()
    instructions.insert(1.0, instructions_results[0])
    instructions.config(wrap=WORD)
except:
    messagebox.showerror("DataBase Error", "Failed to load category")
This no longer populates the widgets and draws the error messagebox. This started when I added the [0] to the insert line of the for the selection made from the OptionMenu. (the second snip of code above)

Any advice and/or a point to documents that can explain why this is happening and how I can make the items in the displayed list clickable again without having the show the curly brackets would be appreciated.
"Often stumped... But never defeated."
Reply
#2
add the following in snippet labeled: The query for the selection made from the OptionMenu:
after line 7, and post (partial if large) results
            print('each_result: {}'.format(each_result))
Reply
#3
When I print the result of the query it provides the correct data, exactly as it is input in the column.
Print:
each_result: ("Sonic's Extreme Tots",)
each_result: ('Mozzarella Sticks',)
each_result: ('Loaded Potato Skins\r\n',)
each_result: ('Chile Con Queso\r\n',)
each_result: ('Buffalo Blasts',)
The problem I am having it that without having the [0] at the end of the insert line in that query it populates the widget with each item having the curly bracket at the beginning and end of each item listed.
if I have the query as:
def select():
    try:
        output.delete(0, END)
        selection = var.get()
        c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC', {"selection": selection})
        results = c.fetchall()
        for each_result in results:
            output.insert(0,each_result)
    except:
        messagebox.showerror("DataBase Error", "Failed to load category")
This populates the widget as well but displays the curly brackets.
Example:
{Sonic's Extreme Tots}
{Mozzarella Sticks}
{Loaded Potato Skins}
and so on....

Only when I used the [o] in used the insert line did it remove the brackets, but then I cannot click one of the items displayed and have it load the data from the getRecipe query.
If I remove the [0] from the insert line and the curly brackets show again I can click an item and it will populate all fields properly.
"Often stumped... But never defeated."
Reply
#4
change line 8 from output.insert(0,each_result[0])
to output.insert(0,each_result.strip())
Reply
#5
I have added strip() to the line and it does the same as [0] to remove the curly brackets but it also prevents an item in the list to be actively clicked and populate the other widget.
When I remove the "try:' and comment out all but the first query to show me the problem I am getting the following from the getRecipe procedure:
File "C:\Users\Home\Documents\Python Projects\Recipe\3 Module\Recipe.py", line 158, in getRecipe
dish_type_entry.insert(1.0,dish_type_result)
tkinter.TclError: wrong # args: should be ".!entry insert index text
But the query should be correct I think.
dish_type_entry.delete(0,END)
index = output.curselection()[0]
selected = output.get(index)
c.execute('SELECT Dish_Type FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
dish_type_results = c.fetchone()
dish_type_entry.insert(0,dish_type_results)
Any thoughts?
"Often stumped... But never defeated."
Reply
#6
It's very difficult without being able to run the code.
Since you have only provided snippets, that's not possible without a lot of work.
I'd only be guessing.
It sounds like it's treating the entire entry as a single item.
I do have some code on the forum that uses a listbox and works fine, you're welcome to take a look: https://python-forum.io/Thread-
California-Public-Salary-Files?highlight=public
code is here: https://github.com/Larz60p/CaliforniaPublicSalaries
Reply
#7
I will have a look at the links you provided... I truly appreciate the help.
I know that when the initial query is done (begins at line 174), it returns a tuple and that is the reason for the curly brackets showing on each item it fetched and populated in the widget.
I have now found the I can remove the curly brackets in a couple ways.
Adding [0] at the end of the insert line - output.insert(0,each_result[0])
or
Adding a comma in the "for" statement - for recipe, in results:
Either method changes the retrieved data from a tuple to a string variable.

The issue then become after it populates in the widget without the bracket and an item is then clicked the binding that goes to the query procedure "getRecipe()" to fetch the data for the item clicked no longer works.
Full code:
import os
import tkinter
import sqlite3
from tkinter import *
from tkinter import ttk
from tkinter import messagebox

#================================ BEGIN PROGRAM ================================
def main():
#============================= CONNECT TO DATABASE =============================
    conn = sqlite3.connect('Recipe.db')
    c = conn.cursor()
#========================= CREATE DATABASE WITH TABLES =========================
    c.execute('''CREATE TABLE IF NOT EXISTS Recipes(
    Dish_Type CHAR(50) NOT NULL,
    Recipe CHAR(50) NOT NULL,
    Cook_Time CHAR(15) NOT NULL,
    Serves CHAR(8) NOT NULL,
    Ingredients CHAR(5000) NOT NULL,
    Instructions CHAR(5000) NOT NULL);''')
    conn.commit()
#================================= MAIN WINDOW =================================
    root = tkinter.Tk()
    root.title('Recipes')
    w = 1024
    h = 612
    ws = root.winfo_screenwidth()
    hs = root.winfo_screenheight()
    x = (ws/2) - (w/2)
    y = (hs/2) - (h/2)
    root.geometry('%dx%d+%d+%d' % (w, h, x, y))
    root.title('Recipes')

    class OpenButton(Widget):
        """Button widget."""
        def __init__(self, master=None, cnf={}, **kw):
            start_button = tkinter.Button(root, text='Open',  font='Times 12 bold italic', border = 2, bg = "#F9F8D6", fg = "#9A0615", width = 10, height = 2, command = window_2)
            start_button.pack()
            start_button.place(x=448, y=460)
#================================== MODULE 2 ===================================
    def window_2():
        root.destroy()
        window_2 = tkinter.Tk()
        w = 1024
        h = 612
        ws = window_2.winfo_screenwidth()
        hs = window_2.winfo_screenheight()
        x = (ws/2) - (w/2)
        y = (hs/2) - (h/2)
        window_2.geometry('%dx%d+%d+%d' % (w, h, x, y))
        window_2.title('Recipes')
#============================== STRING VARIABLES ===============================
        Recipe_Selection = StringVar()
        Dish_Type = StringVar()
        Recipe = StringVar()
        Cook_Time = StringVar()
        Serves = StringVar()
        Ingredients = StringVar()
        Instructions = StringVar()
#=========================== MODULE 2 CLEAR INPUT ==============================
        def clear1():
            output.delete(0,END)
            instructions.delete(1.0,END)
#================================ RECIPE UPLOAD ================================
        def save():
            try:
                c.execute('''INSERT INTO Recipes VALUES (?,?,?,?,?,?)''', (Dish_Type.get(), (Recipe.get()),
                (Cook_Time.get()), (Serves.get()), (Ingredients.get()), (Instructions.get())))
                conn.commit()
                messagebox.showinfo("Information","Recipe saved successfully.")
            except:
                messagebox.showerror("Data Base Error", "Recipe was not saved.")
#=========================== MODULE 2 CLEAR INPUT ==============================
        def clear2():
            dish_type_entry.delete(0,END)
            recipe_entry.delete(0,END)
            serves_entry.delete(0,END)
            cook_time_entry.delete(0,END)
            ingredients.delete(1.0,END)
            instructions.delete(1.0,END)
#============================== GET RECIPE QUERY ===============================
        def getRecipe(event):
            def clear2():
                dish_type_entry.delete(0,END)
                recipe_entry.delete(0,END)
                serves_entry.delete(0,END)
                cook_time_entry.delete(0,END)
                ingredients.delete(1.0,END)
                instructions.delete(1.0,END)
            dish_type = tkinter.Label(window_2, font=('Times 9 bold'), text='Category:', bg = "#FFD599", fg = '#9A0615')
            dish_type.pack()
            dish_type.place(x=210, y=105)
            dish_type_entry = tkinter.Entry(window_2, textvariable=Dish_Type, width = 20, bg = "#FFD599", fg = '#9A0615', justify=CENTER)
            dish_type_entry.place(x=288, y=106)
            recipe = tkinter.Label(window_2, font=('Times 9 bold'), text='Recipe:', bg = "#FFD599", fg = '#9A0615')
            recipe.pack()
            recipe.place(x=210, y=125)
            recipe_entry = tkinter.Entry(window_2, textvariable=Recipe, width = 20, bg = "#FFD599", fg = '#9A0615', justify=CENTER)
            recipe_entry.place(x=288, y=126)
            serves = tkinter.Label(window_2, font=('Times 9 bold'), text='Serves:', bg = "#FFD599", fg = '#9A0615')
            serves.pack()
            serves.place(x=547, y=105)
            serves_entry = tkinter.Entry(window_2, textvariable=Serves, width = 3, bg = "#FFD599", fg = '#9A0615', justify=CENTER)
            serves_entry.place(x=623, y=106)
            cook_time = tkinter.Label(window_2, font=('Times 9 bold'), text='Cook Time:', bg = "#FFD599", fg = '#9A0615')
            cook_time.pack()
            cook_time.place(x=547, y=125)
            cook_time_entry = tkinter.Entry(window_2, textvariable=Cook_Time, width = 11, bg = "#FFD599", fg = '#9A0615', justify=CENTER)
            cook_time_entry.place(x=623, y=126)
            ingredients = tkinter.Text(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615')
            ingredients.pack()
            ingredients.place(x=210, y=200)
            yscroll = tkinter.Scrollbar(command=ingredients.yview, orient=tkinter.VERTICAL)
            yscroll.place(x=450, y=200)
            ingredients.configure(yscrollcommand=yscroll.set)
            instructions = tkinter.Text(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615')
            instructions.pack()
            instructions.place(x=547, y=200)
            yscroll = tkinter.Scrollbar(command=instructions.yview, orient=tkinter.VERTICAL)
            yscroll.place(x=787, y=200)
            instructions.configure(yscrollcommand=yscroll.set)
            dish_type_entry.focus()
            clear1Button = tkinter.Button(window_2, text='Clear Page',  font='Times 9 bold italic', border = 1, height = 1, width = 14, bg = "#F9F8D6", fg = '#9A0615', command = clear2)
            clear1Button.pack
            clear1Button.place(x=630, y=527)
            saveButton = tkinter.Button(window_2, text='Save Recipe',  font='Times 9 bold italic', border = 1, height = 1, width = 14, bg = "#F9F8D6", fg = '#9A0615')##, command = Save)
            saveButton.pack
            saveButton.place(x=293, y=527)
            try:
                dish_type_entry.delete(0,END)
                index = output.curselection()[0]
                selected = output.get(index)
                c.execute('SELECT Dish_Type FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
                dish_type_result = c.fetchone()
                dish_type_entry.insert(0,dish_type_result[0])

                recipe_entry.delete(0,END)
                index = output.curselection()[0]
                selected = output.get(index)
                c.execute('SELECT Recipe FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
                recipe_result = c.fetchone()
                recipe_entry.insert(0,recipe_result[0])

                serves_entry.delete(0,END)
                index = output.curselection()[0]
                selected = output.get(index)
                c.execute('SELECT Serves FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
                serves_result = c.fetchone()
                serves_entry.insert(0,serves_result[0])

                cook_time_entry.delete(0,END)
                index = output.curselection()[0]
                selected = output.get(index)
                c.execute('SELECT Cook_Time FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
                cook_time_result = c.fetchone()
                cook_time_entry.insert(0,cook_time_result[0])

                index = output.curselection()[0]
                selected = output.get(index)
                c.execute('SELECT Ingredients FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
                ingredients_result = c.fetchone()
                ingredients.insert(1.0,ingredients_result[0])
                ingredients.config(wrap=WORD)

                index = output.curselection()[0]
                selected = output.get(index)
                c.execute('SELECT Instructions FROM Recipes WHERE Recipe = :selected', {"selected": selected[0]})
                instructions_result = c.fetchone()
                instructions.insert(1.0, instructions_result[0])
                instructions.config(wrap=WORD)
            except:
                messagebox.showerror("DataBase Error", "Failed to load category")
#================================ SELECT QUERY =================================
        def select():
            try:
                output.delete(0, END)
                selection = var.get()
                c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC', {"selection": selection})
                results = c.fetchall()
                for each_result in results: ## ADD "," AFTER each_result TO CHANGE TO A STRING VARIABLE INSTEAD OF A TUPLE"
                    output.insert(0,each_result)## ADDING ".strip" DID NOT WORK
            except:
                messagebox.showerror("DataBase Error", "Failed to load category")
#================================ OPTION MENU ==================================
        var = tkinter.StringVar(window_2)
        var.set('Category')
        choices = [
            'Appetizers',
            'Beef',
            'Cake/Pastry',
            'Desserts',
            'Drinks',
            'Eggs',
            'Fish',
            'Pasta',
            'Pork',
            'Potato',
            'Poultry',
            'Rice',
            'Salads',
            'Sandwiches',
            'Sauces/Dips',
            'Sea Food',
            'Slow Cooker',
            'Soups/Chilli',
            'Spicy'
            'Stews',
            'Turkey',
            'Vegetables']
        option = tkinter.OptionMenu(window_2, var, *choices)
        option.config(font=('Times 9 bold'), bg = '#F9F8D6', fg = '#9A0615')
        option.place(x=210, y=157)
        option["menu"].config(bg = '#F9F8D6', fg = '#9A0615')
        backer = tkinter.Label(window_2, font=('Times 17 bold'), text='              ')
        backer.pack()
        backer.place(x=360, y=157)
        button = tkinter.Button(window_2, text="Load Category", font=('Times 9 bold'), bg = "#F9F8D6", fg = "#9A0615", command=select)
        button.pack
        button.place(x=362, y=160)
#=============================== MENU PAGE WIDGETS =============================
        instructions = tkinter.Text(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615')
        instructions.pack()
        instructions.place(x=547, y=200)
        yscroll = tkinter.Scrollbar(command=instructions.yview, orient=tkinter.VERTICAL)
        yscroll.place(x=787, y=200)
        instructions.configure(yscrollcommand=yscroll.set)
        output = tkinter.Listbox(window_2, font=('Times 9'), height = 20, width=40, bd=0, bg = "#FFD599", fg = '#9A0615', selectmode=SINGLE)
        output.pack()
        output.place(x=210, y=200)
        yscroll = tkinter.Scrollbar(command=output.yview, orient=tkinter.VERTICAL)
        yscroll.place(x=450, y=200)
        output.configure(yscrollcommand=yscroll.set)
        output.bind('<ButtonRelease-1>', getRecipe)
#=================================== BUTTONS ===================================
        enterButton = tkinter.Button(window_2, text='Enter a Recipe',  font='Times 9 bold italic', border = 1, height = 1, width = 14, bg = "#F9F8D6", fg = '#9A0615')##, command = getRecipe())
        enterButton.pack
        enterButton.place(x=293, y=527)
        clear1Button = tkinter.Button(window_2, text='Clear Page',  font='Times 9 bold italic', border = 1, height = 1, width = 14, bg = "#F9F8D6", fg = '#9A0615', command = clear1)
        clear1Button.pack
        clear1Button.place(x=630, y=527)

    OpenButton()
    root.mainloop()
if __name__ == '__main__':
    main()
The problem with this as I said is that once the tuple is change to a string variable by using either method, as I mentions above, I can no longer click on a recipe from the category list and have it query the "getRecipe()" procedure successfully.

(on a small separate note I am also trying to find the correct way to allow the Listbox at line 228 to again be viewable after getRecipe() has run. I naturally assume that I might want to select another category to view if I do not like the selection I initially make. So it needs to change from displaying the Text box back to the Listbox)
"Often stumped... But never defeated."
Reply
#8
I loaded the code into my IDE. but I won't get to this for a wkile, it's 4:20 A.M. and I've been up all night working on my own project.
If no one has answered by the time I wake up, I'll take a look at the code first thing.
Reply
#9
Resolved, thank you.
"Often stumped... But never defeated."
Reply
#10
I have found that the issue of the curly brackets has not been fully resolve.
I can remove the curly brackets by adding add a comma at line 8:
#================================ SELECT QUERY =================================
        def select():
            try:
                output.delete(0, END)
                selection = var.get()
                c.execute('SELECT Recipe FROM Recipes WHERE Dish_Type = :selection ORDER BY Recipe DESC', {"selection": selection})
                results = c.fetchall()
                for each_result, in results: ## ADDED "," AFTER each result to remove the curly bracket when it inserts into widget. 
                    output.insert(0,each_result)## ADDING ".strip" DID NOT WORK
            except:
                messagebox.showerror("DataBase Error", "Failed to load category")
But as I said before it no longer allows the fetched data that is inserted into the widget to be actively clickable (from the binding), so it will query the database for the item clicked. If I leave the curly brackets then each item in the list is clickable and the query is done and fetches the data for the clicked item.
Having the brackets on each item after it populates the widget looks terrible and they need to be removed but keep it actively clickable.
I am not sure how to resolve this so any help or a point to literature that explains this would be greatly appreciated.
"Often stumped... But never defeated."
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Problem Using SQL Placeholder In MySQL Query AdeS 11 6,131 Jul-31-2021, 12:19 AM
Last Post: Pedroski55
  MySQLdb, problem with query with user-defined variables buran 6 6,412 Feb-03-2017, 06:16 PM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020