Sylvain
Sylvain

Reputation: 563

Trying to have an tkinter app save data into an SQLite3 database

I am coding a small program to simply save text data and integer data into an SQLite3 database.

I have created the db called test.db with the following code:

con = sqlite3.connect('test.db')
cur = con.cursor()
cur.execute('drop table if exists data')
cur.execute('create table data(t1 TEXT, i1 INT)')
con.commit()
print('DB created')

The problem is when I run it it tells me that the cur.execute line requires strings as parameters, but I have already defined text1 as string with StringVar.

from tkinter import *
from tkinter import ttk
import sqlite3

def savedata(text1, int1):
    con = sqlite3.connect('test.db')
    cur = con.cursor()
    cur.execute(('INSERT INTO data (t1, i1) VALUES (?,?)', (text1, int1)))
    con.commit()
    print('record inserted in data')

root = Tk()
root.title("Little Program To Save Data")

mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column = 0, row = 0, sticky = (N,W,E,S))
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)

text1 = StringVar()
text_entry = ttk.Entry(mainframe, width = 20, textvariable=text1)
text_entry.grid(column = 2, row = 1, sticky = (N,W,E,S))

int1 = IntVar()
int_entry = ttk.Entry(mainframe, width = 20, textvariable=int1)
int_entry.grid(column = 2, row = 2, sticky = (N,W,E,S))

ttk.Button(mainframe, text = "Save!", command=savedata(text1, int1)).grid(column = 3, row = 3, sticky = (W, E))

for child in mainframe.winfo_children(): 
    child.grid_configure(padx = 5, pady = 5)

root.mainloop()

Upvotes: 1

Views: 4696

Answers (1)

mmgp
mmgp

Reputation: 19221

The code doesn't work because StringVar and IntVar are not the typical Python objects str and int, they actually represent Tcl variables which you might happen to set to contain values that can be classified either as string or integer.

The first thing you need to do is change savedata(text1, int1) to savedata(text1.get(), int1.get()) so you actually obtain the values stored in them. Secondly, the way you define the value for the command parameter in the Button widget is wrong because you are executing it instead of passing a function to be executed when you actually click the button. That is fixed by changing that part to command = lambda: savedata(...). Thirdly, you are calling

cur.execute(('INSERT INTO data (t1, i1) VALUES (?,?)', (text1, int1)))

but that will certainly fail, because you are passing a tuple to execute, what you actually want is:

cur.execute('INSERT INTO data (t1, i1) VALUES (?,?)', (text1, int1))

Now your code works, but there is no need to use Tcl variables here.

Upvotes: 2

Related Questions