Referring to a python variable in SQLite3 DELETE statement - python

I am writing a function to delete a record from a table. The variable I am trying to refer to in the delete statement is a Tkinter entry field.
I get the variable using the .get() method, but I can't then pass this into the SQLite statment without returning an error.
The following code is part of the frame, I've only added the relevant code to the problem
from tkinter import *
import sqlite3
class EditOrdersForm(Frame):
def __init__(self):
Frame.__init__(self)
self.master.title("Edit Orders form:")
self.pack()
def displayDelOrderOptions(self):
self.deleteOrderOptionsLabel = Label(self, text="Enter the Order ID of the order you wish to delete: ").grid(row=numOrders+4, pady=2, sticky=W)
self.deleteOrderOptionsEntry = Entry(self, bd=3, width=10)
self.deleteOrderOptionsEntry.grid(row=numOrders+4, pady=5, column=1)
global orderToDelete
orderToDelete = self.deleteOrderOptionsEntry.get()
self.deleteButton = Button(self, text = "Delete this order", command = self.deleteOrder)
self.deleteButton.grid(row=numOrders+5, pady=5, column=1)
def deleteOrder(self):
conn = sqlite3.connect("testdb.db")
c = conn.cursor()
c.execute("DELETE FROM orders WHERE orders_id=:1)", (orderToDelete,))
conn.commit
c.close()
root = EditOrdersForm()
root.mainloop()
The problem I have is with the WHERE statement, how do I refer to orderToDelete. I have tried converting it to a string and using (?) as the parameter but this didn't work either.

THe correct syntax for parameterized query is:
c.execute("DELETE FROM orders WHERE orders_id=?)", (orderToDelete,))
I believe you just need to call commit instead of reference it
conn.commit()

Related

one instance of tkinter's entry get function isn't working while others around it work

In my code I have two .get functions referring to filled tkinter cells. They are entirely identical as far as I can tell. However, new_comp_name.get() works perfectly while new_comp_email.get() returns an empty value. A couple hours I give up and I thought I could get some help regarding this here. The code below is simplified but running it, I still encounter the same bizzar issue. I even resorted to restarting my computer but still, no luck. Any help would be much appreciated.
def newc_popup():
compviewFresh()
newc_popup = Toplevel()
newc_popup.title("New Company")
#-----------fetch options list from types DB
connection = sqlite3.connect('companyDB99.db')
###### end of connection ####
query="SELECT type_name as class FROM types"
r_set=connection.execute(query);
my_list = [r for r, in r_set] # create a list
options = tk.StringVar(newc_popup)
comptypeSELECT =tk.OptionMenu(newc_popup, options, *my_list)
#om1.grid(row=2,column=5)
#-----------
comp_name_label = Label(newc_popup, text="Company Name")
comp_name_label.grid(row=1, column=0)
new_comp_name = Entry(newc_popup, width=50)
new_comp_name.grid(row=1, column=1)
comp_email_label = Label(newc_popup, text="Email Address")
comp_email_label.grid(row=2, column=0)
new_comp_email = Entry(newc_popup, width=50)
new_comp_email.grid(row=2, column=1)
comptypeSELECT_lable = Entry(newc_popup, width=50)
comptypeSELECT_lable.grid(row=2, column=1)
comptypeSELECT.grid(row=3, column=1,)
def addComp():
compviewFresh()
connection = sqlite3.connect('companyDB99.db')
cursor = connection.cursor()
print(new_comp_name.get())
print(new_comp_email.get())
addComp_btn = Button(newc_popup, text="Add Company", command=addComp)
addComp_btn.grid(row=4, column=0, columnspan=2)
Your call to .get is working fine. The problem is that you have two entries in the same place so you're not typing into the widget you think you're typing into.
Here's the problem:
new_comp_email.grid(row=2, column=1)
comptypeSELECT_lable.grid(row=2, column=1)
comptypeSELECT_label is an Entry, so when you think you are typing into new_comp_email you're actually typing into comptypeSELECT_label since it was added last and thus is on top of new_comp_email. Thus, new_comp_email is empty.

Multiple GUI with Tkinter

I am using Python 3.x, and I'm trying to fetch Dataset records and display them in an extra Window. I'm a bloody beginner and currently I don't see my error. I've checked multiple threads but didn't get the solution. Debugging isn't helping me either.
Here's my approach:
import sqlite3
from tkinter import *
class Overview():
def __init__(self,master):
self.master = master
self.master.geometry('170x110+100+200')
self.master.title('Welcome!')
self.button1 = Button(self.master, text="Show dataset", fg='green', command=self.gotoMenu).grid(
row=1, column=1)
def gotoMenu(self):
# This is the Dataset GUI#
root2 = Toplevel(self.master)
myGUI = Menu(root2)
def main():
root = Tk()
overviewGUI = Overview(root)
root.mainloop()
if __name__ == '__main__':
main()
class Menu:
def __init__(self,master):
# This is the Dataset GUI#
self.connection = sqlite3.connect('test.db')
print("Opened database successfully")
self.cur = self.connection.cursor()
self.master = master
self.master.title('Dataset')
self.master.geometry("320x240")
print("GUI created")
self.dateLabel = Label(self.master, text="Date", width=10)
self.dateLabel.grid(row=0, column=0)
self.BMILabel = Label(self.master, text="Name", width=10)
self.BMILabel.grid(row=0, column=1)
self.stateLabel = Label(self.master, text="ID", width=10)
self.stateLabel.grid(row=0, column=2)
self.insertDS('random')
self.showallrecords()
def showallrecords(self):
data = self.readfromdatabase()
for index, dat in enumerate(data):
Label(self.master, text=dat[2]).grid(row=index + 1, column=0)
Label(self.master, text=dat[1]).grid(row=index + 1, column=1)
Label(self.master, text=dat[0]).grid(row=index + 1, column=2)
def readfromdatabase(self):
self.cur.execute("SELECT * FROM LOGGING")
return self.cur.fetchall()
def createTable(self):
try:
self.connection.execute(
"CREATE TABLE LOGGING(ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT NOT NULL, TIMESTAMP DATE DEFAULT (datetime('now','localtime')));")
print("Table created successfully")
except:
print("Table already exists")
def insertDS(self, name):
self.connection.execute("INSERT INTO LOGGING (NAME) \
VALUES (?);", [name])
self.connection.commit()
print("Records created successfully")
My Application should start with the "Overview" GUI, on button click I want to see all fetched Datasets from "Menu" Class.
However, after clicking the button the next window is empty and has the title "Welcome" which should be "Dataset"
UPDATE:
I am getting no error, BUT my fetched results won't show in the 2nd Window, and the title isn't self.master.title('Dataset') as initialized in class Menu.
I feel like it's just creating some empty Window without even looking in my Menu Class?
Solution:
python className not defined NameError
Somehow(can't explain why) when I moved the ´name´ block down with the def (even though indentions were right) it worked.
You have overloaded Menu, change your class name by an another name.
And don't use import *

How to format SQL query output properly in Tkinter?

I am having trouble outputting my SQL queries properly. I have posted this earlier but I don't think I explained it very well. I am using an entry widget for at least 10 rows in a SQL query.
The program can search for a first name or last name and provide a list of names tied to the search criteria.
It should only list the name in relation to the present query.
Right now, if you enter a name, it will list all the people that have the same name. Then if you do a second search, it will list the new name plus the previous names you searched for. I am trying to figure out how to properly clear it so that the previous names will no longer show.
I am attaching a screen shot of 3 searches from a database of random names.
The first search is for the first name Burney. There is only one Burney in my database so it lists that one Burney.
Second, Josh is searched for. There are probably around 20 Josh's in the datbase so it overwrites Burney and lists Josh names.
Third, Burney is search for again.
Well, it only overwrites the top Entry row with Burney but leaves all of the previous Josh names.
I only want it to show Burney.
I have played with self.myentry.delete(0, END) in the results[x] but I am not sure if I am using it properly. Or if it would even help my situation.
Attached is a screenshot and a short version of my code:
import os
import pypyodbc
import tkinter
from tkinter import ttk
from tkinter import messagebox
from tkinter import BOTH, END, LEFT
class Adder(ttk.Frame):
"""The adders gui and functions."""
def __init__(self, parent, *args, **kwargs):
ttk.Frame.__init__(self, parent, *args, **kwargs)
self.root = parent
self.init_gui()
def calculate(self):
firstname = str(self.first_entry.get())
lastname = str(self.last_entry.get())
if (firstname and not lastname): # "You entered first name."
try:
connection = pypyodbc.connect('Driver={SQL Server};Server=MYSERVERNAME;Database=MYDATABASE;Trusted_Connection=yes;')
except pypyodbc.Error as ex:
sqlstate = ex.args[0]
if sqlstate == '28000':
self.answer_label['text'] = "You do not have access."
cursor = connection.cursor()
SQLCommand = ("SELECT LASTNAME, FIRSTNAME "
"FROM dbo.MYTABLENAMEHERE " # table name
"with (nolock)"
"WHERE FIRSTNAME = ?")
Values = [firstname]
cursor.execute(SQLCommand,Values)
results = cursor.fetchmany(10)
if results:
self.output0.delete(0, END)
self.output0.insert(0,results[0])
self.output1.insert(0,results[1])
self.output2.insert(0,results[2])
self.output3.insert(0,results[3])
self.output4.insert(0,results[4])
connection.close()
def init_gui(self):
"""Builds GUI."""
self.root.title('Verify')
self.root.option_add('*tearOff', 'FALSE')
self.grid(column=0, row=0, sticky='nsew') # this starts the entire form
# Input Boxes and Button
self.first_entry = tkinter.Entry(self, width=28) # first input box
self.first_entry.grid(sticky='', column=1, row=1)
self.last_entry = tkinter.Entry(self, width=28) # second input box
self.last_entry.grid(sticky='', column=2, row=1)
self.calc_button = ttk.Button(self, text='Search', command=self.calculate) # button
self.calc_button.grid(column=4, row=1, columnspan=1, sticky='w', padx=14)
# Output entries for answers
self.output0 = tkinter.Entry(self, width=150, bd=0,)
self.output0.grid(column=0, row=6, columnspan=5, padx=100, pady=0)
self.output1 = tkinter.Entry(self, width=150, bd=0,)
self.output1.grid(column=0, row=7, columnspan=5, padx=100, pady=0)
self.output2 = tkinter.Entry(self, width=150, bd=0,)
self.output2.grid(column=0, row=8, columnspan=5, padx=100, pady=0)
self.output3 = tkinter.Entry(self, width=150, bd=0,)
self.output3.grid(column=0, row=9, columnspan=5, padx=100, pady=0)
self.output4 = tkinter.Entry(self, width=150, bd=0,)
self.output4.grid(column=0, row=10, columnspan=5, padx=100, pady=0)
if __name__ == '__main__':
root = tkinter.Tk()
Adder(root)
root.resizable(width=False, height=False) # locks window from being resized
root.mainloop()

How can I fetch the result of a SQL Query which uses a variable?

Please help. I am creating a little GUI dictionary and am trying to link the interface to a database. I can enter data (word and definition) into the database correctly but I cannot seem to look up words in the database so that the appropriate definition displays in the output box on my GUI.
Module 1 (main program):
from tkinter import *
import libraryentrySQL
import sqlite3
import os
def click():
entered_text = entry.get() #collect text from text entry box
output.delete(0.0,END) #clears text box - start clearing from 0.0 (from line 0) to END (after last character)
new_db = sqlite3.connect('dictionary.db')
c=new_db.cursor()
try:
definition = c.execute("SELECT definition FROM Dictionary WHERE word=%s", (entered_text))
except:
definition = "No word found in dictionary, try again!"
output.insert(END, definition) #this inserts the contents of variable 'definition' at the beginning (END) - because it was cleared before, END is the at the start
def clickentry(): #this function is run when the 2nd button (entry is pressed)
def definition_submitted(word, definition):
new_db = sqlite3.connect('dictionary.db')
c=new_db.cursor()
c.execute("INSERT INTO Dictionary VALUES (?, ?)", (word, definition))
new_db.commit()
new_db.close()
definition_window = libraryentrySQL.DefinitionWindow(window, definition_submitted) #this creates the object 'definition window' and passes to it 'the window variable'
#so that it can have a canvas
#and also passes the function 'definition_submitted' so that as the new word and definition are entered
#in the this object (second window) it can be passed into the function and the dictionary updated
window = Tk()
window.title("My Little Dictionary")
#Create the Label
Label(window, text="Enter the word you want defining:").grid(row=0, column=0, sticky=W)
#create entry box
entry=Entry(window, width=20, bg="light green")
entry.grid(row=1, column=0, sticky=W)
#create submit button
Button(window, text="Submit", width=5, command=click).grid(row=2, column=0, sticky=W)
#create second label
Label(window, text="\nDefinition").grid(row=3, column=0, sticky=W)
#create text box
output=Text(window, width=75, height=6, wrap=WORD, background="light green")
output.grid(row=4, column=0, sticky=W)
#create submit button to open enter new definition window
Button(window, text="Enter a New Definition", width=20, command=clickentry).grid(row=5, column=0, sticky=W)
#Create the Dictionary.db if not already present
if not os.path.isfile("dictionary.db"):
new_db = sqlite3.connect('dictionary.db')
c=new_db.cursor()
c.execute('''CREATE TABLE Dictionary
(word text,
definition text)''')
c.execute('''INSERT INTO Dictionary VALUES
('Algorithm', 'Step by step instructions to complete a task')''')
new_db.commit()
new_db.close()
window.mainloop()
module 2 (enter word and definition window):
from tkinter import *
class DefinitionWindow(Toplevel):
def __init__(self, root, click_callback):
Toplevel.__init__(self, root)
self.click_callback = click_callback
self.title("Library entry")
#Create the Label
Label(self, text="Enter the word you want to add:").grid(row=0, column=0, sticky=W)
#create entry box
self.word_entry=Entry(self, width=20, bg="light green")
self.word_entry.grid(row=1, column=0, sticky=W)
#create second label
Label(self, text="\nDefinition").grid(row=2, column=0, sticky=W)
#create entry box
self.definition_entry = Entry(self, width=50, bg="light green")
self.definition_entry.grid(row=3, column=0, sticky=W)
#create submit button
Button(self, text="Submit", width=5, command=self.clicked).grid(row=4, column=0, sticky=W)
def clicked(self):
self.click_callback(self.word_entry.get(), self.definition_entry.get()) #when this function is called (on submit button click) it takes the entered
#word and definition and assigns it to click_callback, which is an attribute of DefinitionWindow??
self.destroy() #after the word and definition are added to the call_back variable, the frame containing this instance of definition window is closed
What am I doing wrong? I know it is the "SELECT" SQL command which is not correct. Any help would be gratefully received. Thanks
This is not how SQL queries in Python work.
The execute method returns not a value but a cursor.
When nothing was found, no exception is raised, and the cursor is just empty.
Handling all exceptions blindy in the except block will hide any programming errors.
Furthermore, the parameters marker is not %s but ?.
Finally, a Python tuple with a single value must include a comma to differentiate it from a single expression:
c = new_db.cursor()
c.execute("SELECT definition FROM Dictionary WHERE word = ?", (entered_text,))
for row in c:
definition = row[0]
break
else:
definition = "No word found in dictionary, try again!"
output.insert(END, definition)

Tkinter Program for making a calculator

I am trying to make a simple GUI calculator just for addition/subtraction in the beginning. I am able to print the result to the console but I want to print it to the Entry box like the First Name entry box for example but not able to do it. I would really appreciate if you could help.(*Please neglect the alignment right now of the buttons I am focusing on the functioning, trying to get it right)
from Tkinter import *
import tkMessageBox
import sys
class scanner:
list1 = []
def __init__(self,parent):
self.entrytext = StringVar()
self.entrytext1 = StringVar()
Label(root, text="first name", width=10).grid(row=0,column=0)
Entry(root, textvariable=self.entrytext, width=10).grid(row=0,column=1)
Label(root, text="last name", width=10).grid(row=1,column=0)
Entry(root, textvariable=self.entrytext1, width=10).grid(row=1,column=1)
Button(root, text="ADD", command=self.add).grid()
Button(root, text="SUBTRACT", command=self.subtract).grid()
def add(self):
global a
global b
self.a=int(self.entrytext.get())
self.b=int(self.entrytext1.get())
print "result is", self.a+self.b
def subtract(self):
global a
global b
self.a=int(self.entrytext.get())
self.b=int(self.entrytext1.get())
print "result is", self.a-self.b
root= Tk()
root.geometry("300x300")
calc = scanner(root)
root.mainloop()
If you want to show the result of the operation as a label's text, just create a new label and configure it with the text option and the string you are printing as its value. As a side note, you don't need the global statements, and the use of instance variables is not necessary either. However, it is very important to check that the content of the entries are actually valid numbers:
def __init__(self,parent):
# ...
self.result = Label(root, text='')
self.result.grid(row=4, column=0)
def add(self):
try:
a = int(self.entrytext.get())
b = int(self.entrytext1.get())
self.result.config(text=str(a+b))
except ValueError:
print("Incorrect values")
To add entry text to the widget, use the insert method. To replace the current text, you can call delete before you insert the new text.
e = Entry(master)
e.pack()
e.delete(0, END)
e.insert(0, "a default value")
The first parameter in the delete method is which number character to delete from and the second parameter is where to delete too. Notice how END is a tkinter variable.
The parameters for the insert function is where the text will be inserted too, and the second parameter is what will be inserted.
In the future, I recommend going to Effbot and reading about the widget that you are trying to use to find out all about it.

Categories

Resources