Python TKinter data entry window GUI for SQLITE3 tableGuess the Number Game in PythonClumsy PHP5 code reading...

Monthly Patch Releases for Linux CentOS/RedHat

How do you funnel food off a cutting board?

What is the wife of a henpecked husband called?

Why does a metal block make a shrill sound but not a wooden block upon hammering?

Quenching swords in dragon blood; why?

How do I say "Brexit" in Latin?

Is there some relative to Dutch word "kijken" in German?

Book where aliens are selecting humans for food consumption

Dilemma of explaining to interviewer that he is the reason for declining second interview

Compress command output by piping to bzip2

A starship is travelling at 0.9c and collides with a small rock. Will it leave a clean hole through, or will more happen?

Typing Amharic inside a math equation?

What is this metal M-shaped device for?

Lick explanation

The effects of magnetism in radio transmissions

How to deal with an incendiary email that was recalled

Why did other German political parties disband so fast when Hitler was appointed chancellor?

Process to change collation on a database

Why did this image turn out darker?

Is a debit card dangerous for an account with low balance and no overdraft protection?

Explain the objections to these measures against human trafficking

Does Windows 10's telemetry include sending *.doc files if Word crashed?

Difference between two quite-similar Terminal commands

Parsing a string of key-value pairs as a dictionary



Python TKinter data entry window GUI for SQLITE3 table


Guess the Number Game in PythonClumsy PHP5 code reading from an SQLite3 databasePython tkinter GUITkinter file searching programUsing popup window to get user inputs and use those inputs in button's function in OpenERPTransferring a CSV file to a database while merging some columnsA GUI program for a Buzzer system using arduinoAutocomplete for tkinter Entry widgetsParse one table out of CSV with multiple titled tables with the Python CSV moduleMinimal SQLite table view in PyQt5Searching for a word in a list of tuple extracted from a db via SQL













3












$begingroup$


I would like to offer for review a simple tkinter GUI window in Python 3 to be used for data entry into an SQLite database table. As a noob, this is my first attempt at OOP and my first experience with tkinter, therefore, I was hoping for a thoughough review before I got too carried away.



The script below builds a simple table bar in a sqlite database foo.sqlite. This is for demo purposes. In reality, the database schema would be built elsewhere.



An instance of the class EntryWindow provides the GUI for the window. Upon initialization, the window will read the column names of the given table (bar) from the sqlite database (foo.sqlite) and the build TK labels from the column names as well as entry fields for each column. Finally, there is a button added which, when pressed will get the values from the entry fields and add a row to the database.



There is obviously a lot of additional logic which needs to be added (i.e. some data validation, disabling fields for PK's where the database should be assigning the next value, etc.) but I am at a place where I feel like I need to check in before I start adding complexity to the design. Here's the code:



"""
A simple TKinter GUI to enter data into a given table in a database.

This program will build a small sample table into a given database
and then build a simple TKinter window with label and entry widgets
for each column in the table.
"""
import sqlite3
import tkinter as tk
from tkinter import N, S, E, W
from tkinter import TOP, BOTTOM, LEFT, RIGHT, END, ALL


def main():
"""Main function for demo."""
# define some variables for demo only.
# In full app, these will come programmatically.
db = 'foo.sqlite'
tbl = 'bar'
columns = 'ID integer primary key', 'bizz text', 'bam text'
create_table(db, tbl, *columns)

root = tk.Tk()
demo_window = EntryWindow(root, *[db, tbl])
root.mainloop()


# create a sample table for demo purposes only.
# in full app the database schema would be created elsewhere.
def create_table(database, table, *col_defs):
"""
Insert a simple table into sqlite3 database.

Args:
database (string):
Name of database function will be creating table in.

table (string):
Name of table to be created in given database.

*col_defs (tuple of strings):
A tuple of strings containing the SQL column definitions for the
given table being created in given database.
"""
stmnt = (('create table {}('+('{},'*len(col_defs))[:-1]+');')
.format(table, *col_defs))
with sqlite3.connect(database) as conn:
c = conn.cursor()
c.execute('drop table if exists {};'.format(table))
c.execute(stmnt)
conn.commit()


class EntryWindow(tk.Frame):

"""
Provides a simple data entry window for a given table in given database.

Automatically generates labels and entry fields based on the column
headers for the given table. Provides a button to submit the row of data
into the table and a button to close window.
"""

def __init__(self, master=None, *args):
tk.Frame.__init__(self, master)
self.master = master
self.database = args[0]
self.table = args[1]
self.init_window()

def init_window(self):
"""Build the entry window."""
self.master.title('Enter data into {}'.format(self.table.upper()))
self.grid(column=0, row=0, sticky=(N, W, E, S), padx=10, pady=5)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)

def get_col_names(self):
"""Retrieve column names for given table in database."""
with sqlite3.connect(self.database) as conn:
c = conn.cursor()
c.execute("PRAGMA table_info('{}')".format(self.table))
# Currently only uses one value from returned tuple.
# TODO: Add logic to utilize type, not null and PK fields.
self.col_names = [x[1] for x in c.fetchall()]
return self.col_names

self.column_names = get_col_names(self)

# Add a label and entry box for each column in table.
# TODO: Add functionality to gray out primary key fields where the
# database should be assigning the next value.
# TODO: Add some validation logic.
self.item_entry = []
for item in self.column_names:
num = len(self.item_entry)
# print(num, ' --> '+item)
tk.Label(self, text=item).grid(row=num, column=0,
pady=1, sticky=E)
self.item_entry.append(tk.Entry(self))
self.item_entry[num].grid(row=num, column=1, pady=1, padx=5)

def add_item(self):
"""Get entries from input fields and insert into database table."""
entries = [e.get() for e in self.item_entry]
# Build the SQL statement
stmnt = ('insert into {0}({1}) values ({2})'
.format(self.table, ','.join(self.column_names),
':'+',:'.join(self.column_names)))
# print(stmnt, entries)
with sqlite3.connect(self.database) as conn:
c = conn.cursor()
c.execute(stmnt, entries)
conn.commit()
clear_fields(self)

def clear_fields(self):
"""Clear fields of entry windo and return focus to first field."""
for e in self.item_entry:
e.delete(0, END)
self.item_entry[0].focus()

# Add button to submit user inputs into database.
submit_button = tk.Button(self, text='Add Item', width=8,
command=lambda: add_item(self))
submit_button.grid(row=3, column=0, sticky=E, pady=10, padx=1)

# Add a cancel button which closes window.
quit_button = tk.Button(self, text='Cancel', width=8,
command=self.quit)
quit_button.grid(row=3, column=1, sticky=W, pady=10, padx=1)

if __name__ == '__main__':
main()


Some specific questions I have are:




  • Is my class structure proper? As I mentioned above, this is my first venture into OOP, and I was a little unclear as to what functionality should be in the EntryWindow class and what should be upper level functions.

  • I have read in multiple places on SE (like here) that caution against classes engaging in IO, which obvioulsy (I think?) doesn't apply to a gui class, but got me thinking, should the database interactions (like the get_col_names method) be in a seperate database class?

  • Something is screwey with the way I have the args defined for the __init__ method. I don't think I should be using *args notation here as: def __init__(self, master=None, *args): and instantiating like demo_window = EntryWindow(root, *[db, tbl]), but when I change them to explicit like def __init__(self, database, table, master=None): and instantiate like demo_window = EntryWindow(root, db, tbl) (which seems proper to me), I get an error AttributeError: 'str' object has no attribute 'tk'










share|improve this question











$endgroup$












  • $begingroup$
    Please keep in mind that you should not ask a question on Code Review @ SE to fix programming issues. codereview.stackexchange.com/help/on-topic (seeing your Attribute Error) this should be asked at stackoverflow.com
    $endgroup$
    – R4PH43L
    Nov 16 '15 at 6:44










  • $begingroup$
    @R4PH43L The code for review does not throw the error.
    $endgroup$
    – Christopher Pearson
    Dec 2 '15 at 2:17


















3












$begingroup$


I would like to offer for review a simple tkinter GUI window in Python 3 to be used for data entry into an SQLite database table. As a noob, this is my first attempt at OOP and my first experience with tkinter, therefore, I was hoping for a thoughough review before I got too carried away.



The script below builds a simple table bar in a sqlite database foo.sqlite. This is for demo purposes. In reality, the database schema would be built elsewhere.



An instance of the class EntryWindow provides the GUI for the window. Upon initialization, the window will read the column names of the given table (bar) from the sqlite database (foo.sqlite) and the build TK labels from the column names as well as entry fields for each column. Finally, there is a button added which, when pressed will get the values from the entry fields and add a row to the database.



There is obviously a lot of additional logic which needs to be added (i.e. some data validation, disabling fields for PK's where the database should be assigning the next value, etc.) but I am at a place where I feel like I need to check in before I start adding complexity to the design. Here's the code:



"""
A simple TKinter GUI to enter data into a given table in a database.

This program will build a small sample table into a given database
and then build a simple TKinter window with label and entry widgets
for each column in the table.
"""
import sqlite3
import tkinter as tk
from tkinter import N, S, E, W
from tkinter import TOP, BOTTOM, LEFT, RIGHT, END, ALL


def main():
"""Main function for demo."""
# define some variables for demo only.
# In full app, these will come programmatically.
db = 'foo.sqlite'
tbl = 'bar'
columns = 'ID integer primary key', 'bizz text', 'bam text'
create_table(db, tbl, *columns)

root = tk.Tk()
demo_window = EntryWindow(root, *[db, tbl])
root.mainloop()


# create a sample table for demo purposes only.
# in full app the database schema would be created elsewhere.
def create_table(database, table, *col_defs):
"""
Insert a simple table into sqlite3 database.

Args:
database (string):
Name of database function will be creating table in.

table (string):
Name of table to be created in given database.

*col_defs (tuple of strings):
A tuple of strings containing the SQL column definitions for the
given table being created in given database.
"""
stmnt = (('create table {}('+('{},'*len(col_defs))[:-1]+');')
.format(table, *col_defs))
with sqlite3.connect(database) as conn:
c = conn.cursor()
c.execute('drop table if exists {};'.format(table))
c.execute(stmnt)
conn.commit()


class EntryWindow(tk.Frame):

"""
Provides a simple data entry window for a given table in given database.

Automatically generates labels and entry fields based on the column
headers for the given table. Provides a button to submit the row of data
into the table and a button to close window.
"""

def __init__(self, master=None, *args):
tk.Frame.__init__(self, master)
self.master = master
self.database = args[0]
self.table = args[1]
self.init_window()

def init_window(self):
"""Build the entry window."""
self.master.title('Enter data into {}'.format(self.table.upper()))
self.grid(column=0, row=0, sticky=(N, W, E, S), padx=10, pady=5)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)

def get_col_names(self):
"""Retrieve column names for given table in database."""
with sqlite3.connect(self.database) as conn:
c = conn.cursor()
c.execute("PRAGMA table_info('{}')".format(self.table))
# Currently only uses one value from returned tuple.
# TODO: Add logic to utilize type, not null and PK fields.
self.col_names = [x[1] for x in c.fetchall()]
return self.col_names

self.column_names = get_col_names(self)

# Add a label and entry box for each column in table.
# TODO: Add functionality to gray out primary key fields where the
# database should be assigning the next value.
# TODO: Add some validation logic.
self.item_entry = []
for item in self.column_names:
num = len(self.item_entry)
# print(num, ' --> '+item)
tk.Label(self, text=item).grid(row=num, column=0,
pady=1, sticky=E)
self.item_entry.append(tk.Entry(self))
self.item_entry[num].grid(row=num, column=1, pady=1, padx=5)

def add_item(self):
"""Get entries from input fields and insert into database table."""
entries = [e.get() for e in self.item_entry]
# Build the SQL statement
stmnt = ('insert into {0}({1}) values ({2})'
.format(self.table, ','.join(self.column_names),
':'+',:'.join(self.column_names)))
# print(stmnt, entries)
with sqlite3.connect(self.database) as conn:
c = conn.cursor()
c.execute(stmnt, entries)
conn.commit()
clear_fields(self)

def clear_fields(self):
"""Clear fields of entry windo and return focus to first field."""
for e in self.item_entry:
e.delete(0, END)
self.item_entry[0].focus()

# Add button to submit user inputs into database.
submit_button = tk.Button(self, text='Add Item', width=8,
command=lambda: add_item(self))
submit_button.grid(row=3, column=0, sticky=E, pady=10, padx=1)

# Add a cancel button which closes window.
quit_button = tk.Button(self, text='Cancel', width=8,
command=self.quit)
quit_button.grid(row=3, column=1, sticky=W, pady=10, padx=1)

if __name__ == '__main__':
main()


Some specific questions I have are:




  • Is my class structure proper? As I mentioned above, this is my first venture into OOP, and I was a little unclear as to what functionality should be in the EntryWindow class and what should be upper level functions.

  • I have read in multiple places on SE (like here) that caution against classes engaging in IO, which obvioulsy (I think?) doesn't apply to a gui class, but got me thinking, should the database interactions (like the get_col_names method) be in a seperate database class?

  • Something is screwey with the way I have the args defined for the __init__ method. I don't think I should be using *args notation here as: def __init__(self, master=None, *args): and instantiating like demo_window = EntryWindow(root, *[db, tbl]), but when I change them to explicit like def __init__(self, database, table, master=None): and instantiate like demo_window = EntryWindow(root, db, tbl) (which seems proper to me), I get an error AttributeError: 'str' object has no attribute 'tk'










share|improve this question











$endgroup$












  • $begingroup$
    Please keep in mind that you should not ask a question on Code Review @ SE to fix programming issues. codereview.stackexchange.com/help/on-topic (seeing your Attribute Error) this should be asked at stackoverflow.com
    $endgroup$
    – R4PH43L
    Nov 16 '15 at 6:44










  • $begingroup$
    @R4PH43L The code for review does not throw the error.
    $endgroup$
    – Christopher Pearson
    Dec 2 '15 at 2:17
















3












3








3


1



$begingroup$


I would like to offer for review a simple tkinter GUI window in Python 3 to be used for data entry into an SQLite database table. As a noob, this is my first attempt at OOP and my first experience with tkinter, therefore, I was hoping for a thoughough review before I got too carried away.



The script below builds a simple table bar in a sqlite database foo.sqlite. This is for demo purposes. In reality, the database schema would be built elsewhere.



An instance of the class EntryWindow provides the GUI for the window. Upon initialization, the window will read the column names of the given table (bar) from the sqlite database (foo.sqlite) and the build TK labels from the column names as well as entry fields for each column. Finally, there is a button added which, when pressed will get the values from the entry fields and add a row to the database.



There is obviously a lot of additional logic which needs to be added (i.e. some data validation, disabling fields for PK's where the database should be assigning the next value, etc.) but I am at a place where I feel like I need to check in before I start adding complexity to the design. Here's the code:



"""
A simple TKinter GUI to enter data into a given table in a database.

This program will build a small sample table into a given database
and then build a simple TKinter window with label and entry widgets
for each column in the table.
"""
import sqlite3
import tkinter as tk
from tkinter import N, S, E, W
from tkinter import TOP, BOTTOM, LEFT, RIGHT, END, ALL


def main():
"""Main function for demo."""
# define some variables for demo only.
# In full app, these will come programmatically.
db = 'foo.sqlite'
tbl = 'bar'
columns = 'ID integer primary key', 'bizz text', 'bam text'
create_table(db, tbl, *columns)

root = tk.Tk()
demo_window = EntryWindow(root, *[db, tbl])
root.mainloop()


# create a sample table for demo purposes only.
# in full app the database schema would be created elsewhere.
def create_table(database, table, *col_defs):
"""
Insert a simple table into sqlite3 database.

Args:
database (string):
Name of database function will be creating table in.

table (string):
Name of table to be created in given database.

*col_defs (tuple of strings):
A tuple of strings containing the SQL column definitions for the
given table being created in given database.
"""
stmnt = (('create table {}('+('{},'*len(col_defs))[:-1]+');')
.format(table, *col_defs))
with sqlite3.connect(database) as conn:
c = conn.cursor()
c.execute('drop table if exists {};'.format(table))
c.execute(stmnt)
conn.commit()


class EntryWindow(tk.Frame):

"""
Provides a simple data entry window for a given table in given database.

Automatically generates labels and entry fields based on the column
headers for the given table. Provides a button to submit the row of data
into the table and a button to close window.
"""

def __init__(self, master=None, *args):
tk.Frame.__init__(self, master)
self.master = master
self.database = args[0]
self.table = args[1]
self.init_window()

def init_window(self):
"""Build the entry window."""
self.master.title('Enter data into {}'.format(self.table.upper()))
self.grid(column=0, row=0, sticky=(N, W, E, S), padx=10, pady=5)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)

def get_col_names(self):
"""Retrieve column names for given table in database."""
with sqlite3.connect(self.database) as conn:
c = conn.cursor()
c.execute("PRAGMA table_info('{}')".format(self.table))
# Currently only uses one value from returned tuple.
# TODO: Add logic to utilize type, not null and PK fields.
self.col_names = [x[1] for x in c.fetchall()]
return self.col_names

self.column_names = get_col_names(self)

# Add a label and entry box for each column in table.
# TODO: Add functionality to gray out primary key fields where the
# database should be assigning the next value.
# TODO: Add some validation logic.
self.item_entry = []
for item in self.column_names:
num = len(self.item_entry)
# print(num, ' --> '+item)
tk.Label(self, text=item).grid(row=num, column=0,
pady=1, sticky=E)
self.item_entry.append(tk.Entry(self))
self.item_entry[num].grid(row=num, column=1, pady=1, padx=5)

def add_item(self):
"""Get entries from input fields and insert into database table."""
entries = [e.get() for e in self.item_entry]
# Build the SQL statement
stmnt = ('insert into {0}({1}) values ({2})'
.format(self.table, ','.join(self.column_names),
':'+',:'.join(self.column_names)))
# print(stmnt, entries)
with sqlite3.connect(self.database) as conn:
c = conn.cursor()
c.execute(stmnt, entries)
conn.commit()
clear_fields(self)

def clear_fields(self):
"""Clear fields of entry windo and return focus to first field."""
for e in self.item_entry:
e.delete(0, END)
self.item_entry[0].focus()

# Add button to submit user inputs into database.
submit_button = tk.Button(self, text='Add Item', width=8,
command=lambda: add_item(self))
submit_button.grid(row=3, column=0, sticky=E, pady=10, padx=1)

# Add a cancel button which closes window.
quit_button = tk.Button(self, text='Cancel', width=8,
command=self.quit)
quit_button.grid(row=3, column=1, sticky=W, pady=10, padx=1)

if __name__ == '__main__':
main()


Some specific questions I have are:




  • Is my class structure proper? As I mentioned above, this is my first venture into OOP, and I was a little unclear as to what functionality should be in the EntryWindow class and what should be upper level functions.

  • I have read in multiple places on SE (like here) that caution against classes engaging in IO, which obvioulsy (I think?) doesn't apply to a gui class, but got me thinking, should the database interactions (like the get_col_names method) be in a seperate database class?

  • Something is screwey with the way I have the args defined for the __init__ method. I don't think I should be using *args notation here as: def __init__(self, master=None, *args): and instantiating like demo_window = EntryWindow(root, *[db, tbl]), but when I change them to explicit like def __init__(self, database, table, master=None): and instantiate like demo_window = EntryWindow(root, db, tbl) (which seems proper to me), I get an error AttributeError: 'str' object has no attribute 'tk'










share|improve this question











$endgroup$




I would like to offer for review a simple tkinter GUI window in Python 3 to be used for data entry into an SQLite database table. As a noob, this is my first attempt at OOP and my first experience with tkinter, therefore, I was hoping for a thoughough review before I got too carried away.



The script below builds a simple table bar in a sqlite database foo.sqlite. This is for demo purposes. In reality, the database schema would be built elsewhere.



An instance of the class EntryWindow provides the GUI for the window. Upon initialization, the window will read the column names of the given table (bar) from the sqlite database (foo.sqlite) and the build TK labels from the column names as well as entry fields for each column. Finally, there is a button added which, when pressed will get the values from the entry fields and add a row to the database.



There is obviously a lot of additional logic which needs to be added (i.e. some data validation, disabling fields for PK's where the database should be assigning the next value, etc.) but I am at a place where I feel like I need to check in before I start adding complexity to the design. Here's the code:



"""
A simple TKinter GUI to enter data into a given table in a database.

This program will build a small sample table into a given database
and then build a simple TKinter window with label and entry widgets
for each column in the table.
"""
import sqlite3
import tkinter as tk
from tkinter import N, S, E, W
from tkinter import TOP, BOTTOM, LEFT, RIGHT, END, ALL


def main():
"""Main function for demo."""
# define some variables for demo only.
# In full app, these will come programmatically.
db = 'foo.sqlite'
tbl = 'bar'
columns = 'ID integer primary key', 'bizz text', 'bam text'
create_table(db, tbl, *columns)

root = tk.Tk()
demo_window = EntryWindow(root, *[db, tbl])
root.mainloop()


# create a sample table for demo purposes only.
# in full app the database schema would be created elsewhere.
def create_table(database, table, *col_defs):
"""
Insert a simple table into sqlite3 database.

Args:
database (string):
Name of database function will be creating table in.

table (string):
Name of table to be created in given database.

*col_defs (tuple of strings):
A tuple of strings containing the SQL column definitions for the
given table being created in given database.
"""
stmnt = (('create table {}('+('{},'*len(col_defs))[:-1]+');')
.format(table, *col_defs))
with sqlite3.connect(database) as conn:
c = conn.cursor()
c.execute('drop table if exists {};'.format(table))
c.execute(stmnt)
conn.commit()


class EntryWindow(tk.Frame):

"""
Provides a simple data entry window for a given table in given database.

Automatically generates labels and entry fields based on the column
headers for the given table. Provides a button to submit the row of data
into the table and a button to close window.
"""

def __init__(self, master=None, *args):
tk.Frame.__init__(self, master)
self.master = master
self.database = args[0]
self.table = args[1]
self.init_window()

def init_window(self):
"""Build the entry window."""
self.master.title('Enter data into {}'.format(self.table.upper()))
self.grid(column=0, row=0, sticky=(N, W, E, S), padx=10, pady=5)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)

def get_col_names(self):
"""Retrieve column names for given table in database."""
with sqlite3.connect(self.database) as conn:
c = conn.cursor()
c.execute("PRAGMA table_info('{}')".format(self.table))
# Currently only uses one value from returned tuple.
# TODO: Add logic to utilize type, not null and PK fields.
self.col_names = [x[1] for x in c.fetchall()]
return self.col_names

self.column_names = get_col_names(self)

# Add a label and entry box for each column in table.
# TODO: Add functionality to gray out primary key fields where the
# database should be assigning the next value.
# TODO: Add some validation logic.
self.item_entry = []
for item in self.column_names:
num = len(self.item_entry)
# print(num, ' --> '+item)
tk.Label(self, text=item).grid(row=num, column=0,
pady=1, sticky=E)
self.item_entry.append(tk.Entry(self))
self.item_entry[num].grid(row=num, column=1, pady=1, padx=5)

def add_item(self):
"""Get entries from input fields and insert into database table."""
entries = [e.get() for e in self.item_entry]
# Build the SQL statement
stmnt = ('insert into {0}({1}) values ({2})'
.format(self.table, ','.join(self.column_names),
':'+',:'.join(self.column_names)))
# print(stmnt, entries)
with sqlite3.connect(self.database) as conn:
c = conn.cursor()
c.execute(stmnt, entries)
conn.commit()
clear_fields(self)

def clear_fields(self):
"""Clear fields of entry windo and return focus to first field."""
for e in self.item_entry:
e.delete(0, END)
self.item_entry[0].focus()

# Add button to submit user inputs into database.
submit_button = tk.Button(self, text='Add Item', width=8,
command=lambda: add_item(self))
submit_button.grid(row=3, column=0, sticky=E, pady=10, padx=1)

# Add a cancel button which closes window.
quit_button = tk.Button(self, text='Cancel', width=8,
command=self.quit)
quit_button.grid(row=3, column=1, sticky=W, pady=10, padx=1)

if __name__ == '__main__':
main()


Some specific questions I have are:




  • Is my class structure proper? As I mentioned above, this is my first venture into OOP, and I was a little unclear as to what functionality should be in the EntryWindow class and what should be upper level functions.

  • I have read in multiple places on SE (like here) that caution against classes engaging in IO, which obvioulsy (I think?) doesn't apply to a gui class, but got me thinking, should the database interactions (like the get_col_names method) be in a seperate database class?

  • Something is screwey with the way I have the args defined for the __init__ method. I don't think I should be using *args notation here as: def __init__(self, master=None, *args): and instantiating like demo_window = EntryWindow(root, *[db, tbl]), but when I change them to explicit like def __init__(self, database, table, master=None): and instantiate like demo_window = EntryWindow(root, db, tbl) (which seems proper to me), I get an error AttributeError: 'str' object has no attribute 'tk'







python object-oriented gui sqlite tkinter






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 13 '17 at 12:40









Community

1




1










asked Apr 18 '15 at 21:57









Christopher PearsonChristopher Pearson

2342519




2342519












  • $begingroup$
    Please keep in mind that you should not ask a question on Code Review @ SE to fix programming issues. codereview.stackexchange.com/help/on-topic (seeing your Attribute Error) this should be asked at stackoverflow.com
    $endgroup$
    – R4PH43L
    Nov 16 '15 at 6:44










  • $begingroup$
    @R4PH43L The code for review does not throw the error.
    $endgroup$
    – Christopher Pearson
    Dec 2 '15 at 2:17




















  • $begingroup$
    Please keep in mind that you should not ask a question on Code Review @ SE to fix programming issues. codereview.stackexchange.com/help/on-topic (seeing your Attribute Error) this should be asked at stackoverflow.com
    $endgroup$
    – R4PH43L
    Nov 16 '15 at 6:44










  • $begingroup$
    @R4PH43L The code for review does not throw the error.
    $endgroup$
    – Christopher Pearson
    Dec 2 '15 at 2:17


















$begingroup$
Please keep in mind that you should not ask a question on Code Review @ SE to fix programming issues. codereview.stackexchange.com/help/on-topic (seeing your Attribute Error) this should be asked at stackoverflow.com
$endgroup$
– R4PH43L
Nov 16 '15 at 6:44




$begingroup$
Please keep in mind that you should not ask a question on Code Review @ SE to fix programming issues. codereview.stackexchange.com/help/on-topic (seeing your Attribute Error) this should be asked at stackoverflow.com
$endgroup$
– R4PH43L
Nov 16 '15 at 6:44












$begingroup$
@R4PH43L The code for review does not throw the error.
$endgroup$
– Christopher Pearson
Dec 2 '15 at 2:17






$begingroup$
@R4PH43L The code for review does not throw the error.
$endgroup$
– Christopher Pearson
Dec 2 '15 at 2:17












1 Answer
1






active

oldest

votes


















1












$begingroup$

There are a few things that need looking at.



There seems to be an error in the def add_item method. The 'Build the SQL' section joins sections for table, column names and new values from the entry boxes but the last two items in the .format method BOTH insert 'column_names' whereas I would expect the last one to be 'entries'.



You seem to have gotten confused with the use of *args.



In 'main' you have



create_table(db, tbl, *columns)


and



demo_window = EntryWindow(root, *[db, tbl])


The asterisks (i.e. *) is used in the method DEFINITION as a place holder for the arguments that may not appear in the method call. If they do appear then they will be accessible as a tuple in the body of the method definition.



So



create_table(db, tbl, columns)  # no *


would pass the columns list as the first item of the *col_defs in the create_table method and be accessible as



col_defs[0].


Also



demo_window = EntryWindow(root, [db, tbl])  # no *


would pass the database and table list as the first item of the *args in the EntryWindow method to be accessible as



args[0][0] 


and



args[0][1]. 


Note the double indices. The first accesses the first item in the *args tuple (even if there is only one!) and the second accesses the item within your list.



You could change the call to



demo_window = EntryWindow(root, db, tbl)  # no list and still no *


and then use



args[0] 


and



args[1]


as you have done but to access the items within the *args tuple not items within a list.






share|improve this answer










New contributor




Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$













    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f87319%2fpython-tkinter-data-entry-window-gui-for-sqlite3-table%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1












    $begingroup$

    There are a few things that need looking at.



    There seems to be an error in the def add_item method. The 'Build the SQL' section joins sections for table, column names and new values from the entry boxes but the last two items in the .format method BOTH insert 'column_names' whereas I would expect the last one to be 'entries'.



    You seem to have gotten confused with the use of *args.



    In 'main' you have



    create_table(db, tbl, *columns)


    and



    demo_window = EntryWindow(root, *[db, tbl])


    The asterisks (i.e. *) is used in the method DEFINITION as a place holder for the arguments that may not appear in the method call. If they do appear then they will be accessible as a tuple in the body of the method definition.



    So



    create_table(db, tbl, columns)  # no *


    would pass the columns list as the first item of the *col_defs in the create_table method and be accessible as



    col_defs[0].


    Also



    demo_window = EntryWindow(root, [db, tbl])  # no *


    would pass the database and table list as the first item of the *args in the EntryWindow method to be accessible as



    args[0][0] 


    and



    args[0][1]. 


    Note the double indices. The first accesses the first item in the *args tuple (even if there is only one!) and the second accesses the item within your list.



    You could change the call to



    demo_window = EntryWindow(root, db, tbl)  # no list and still no *


    and then use



    args[0] 


    and



    args[1]


    as you have done but to access the items within the *args tuple not items within a list.






    share|improve this answer










    New contributor




    Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






    $endgroup$


















      1












      $begingroup$

      There are a few things that need looking at.



      There seems to be an error in the def add_item method. The 'Build the SQL' section joins sections for table, column names and new values from the entry boxes but the last two items in the .format method BOTH insert 'column_names' whereas I would expect the last one to be 'entries'.



      You seem to have gotten confused with the use of *args.



      In 'main' you have



      create_table(db, tbl, *columns)


      and



      demo_window = EntryWindow(root, *[db, tbl])


      The asterisks (i.e. *) is used in the method DEFINITION as a place holder for the arguments that may not appear in the method call. If they do appear then they will be accessible as a tuple in the body of the method definition.



      So



      create_table(db, tbl, columns)  # no *


      would pass the columns list as the first item of the *col_defs in the create_table method and be accessible as



      col_defs[0].


      Also



      demo_window = EntryWindow(root, [db, tbl])  # no *


      would pass the database and table list as the first item of the *args in the EntryWindow method to be accessible as



      args[0][0] 


      and



      args[0][1]. 


      Note the double indices. The first accesses the first item in the *args tuple (even if there is only one!) and the second accesses the item within your list.



      You could change the call to



      demo_window = EntryWindow(root, db, tbl)  # no list and still no *


      and then use



      args[0] 


      and



      args[1]


      as you have done but to access the items within the *args tuple not items within a list.






      share|improve this answer










      New contributor




      Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      $endgroup$
















        1












        1








        1





        $begingroup$

        There are a few things that need looking at.



        There seems to be an error in the def add_item method. The 'Build the SQL' section joins sections for table, column names and new values from the entry boxes but the last two items in the .format method BOTH insert 'column_names' whereas I would expect the last one to be 'entries'.



        You seem to have gotten confused with the use of *args.



        In 'main' you have



        create_table(db, tbl, *columns)


        and



        demo_window = EntryWindow(root, *[db, tbl])


        The asterisks (i.e. *) is used in the method DEFINITION as a place holder for the arguments that may not appear in the method call. If they do appear then they will be accessible as a tuple in the body of the method definition.



        So



        create_table(db, tbl, columns)  # no *


        would pass the columns list as the first item of the *col_defs in the create_table method and be accessible as



        col_defs[0].


        Also



        demo_window = EntryWindow(root, [db, tbl])  # no *


        would pass the database and table list as the first item of the *args in the EntryWindow method to be accessible as



        args[0][0] 


        and



        args[0][1]. 


        Note the double indices. The first accesses the first item in the *args tuple (even if there is only one!) and the second accesses the item within your list.



        You could change the call to



        demo_window = EntryWindow(root, db, tbl)  # no list and still no *


        and then use



        args[0] 


        and



        args[1]


        as you have done but to access the items within the *args tuple not items within a list.






        share|improve this answer










        New contributor




        Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






        $endgroup$



        There are a few things that need looking at.



        There seems to be an error in the def add_item method. The 'Build the SQL' section joins sections for table, column names and new values from the entry boxes but the last two items in the .format method BOTH insert 'column_names' whereas I would expect the last one to be 'entries'.



        You seem to have gotten confused with the use of *args.



        In 'main' you have



        create_table(db, tbl, *columns)


        and



        demo_window = EntryWindow(root, *[db, tbl])


        The asterisks (i.e. *) is used in the method DEFINITION as a place holder for the arguments that may not appear in the method call. If they do appear then they will be accessible as a tuple in the body of the method definition.



        So



        create_table(db, tbl, columns)  # no *


        would pass the columns list as the first item of the *col_defs in the create_table method and be accessible as



        col_defs[0].


        Also



        demo_window = EntryWindow(root, [db, tbl])  # no *


        would pass the database and table list as the first item of the *args in the EntryWindow method to be accessible as



        args[0][0] 


        and



        args[0][1]. 


        Note the double indices. The first accesses the first item in the *args tuple (even if there is only one!) and the second accesses the item within your list.



        You could change the call to



        demo_window = EntryWindow(root, db, tbl)  # no list and still no *


        and then use



        args[0] 


        and



        args[1]


        as you have done but to access the items within the *args tuple not items within a list.







        share|improve this answer










        New contributor




        Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.









        share|improve this answer



        share|improve this answer








        edited 11 hours ago









        Sᴀᴍ Onᴇᴌᴀ

        9,72262165




        9,72262165






        New contributor




        Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.









        answered 18 hours ago









        ArturianArturian

        112




        112




        New contributor




        Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.





        New contributor





        Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






        Arturian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f87319%2fpython-tkinter-data-entry-window-gui-for-sqlite3-table%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            is 'sed' thread safeWhat should someone know about using Python scripts in the shell?Nexenta bash script uses...

            How do i solve the “ No module named 'mlxtend' ” issue on Jupyter?

            Pilgersdorf Inhaltsverzeichnis Geografie | Geschichte | Bevölkerungsentwicklung | Politik | Kultur...