sqlitepython-classnested-function

Why do I get error "missing 1 required positional argument"?


Why I continue getting the error :

missing 1 required positional argument: 'category_id'

when the argument is already passed within query function in Backend class? I also don't understand the error of unfilled self or missing positional argument self:

missing 1 required positional argument: 'self'

I tried passing self to display_account_types() in Frontend class but it doesn't reflect. Do I need to pass self within the inner nested functions within a class?

import tkinter
from tkinter import *
from tkinter import ttk
import tkinter.messagebox
import sqlite3

root =Tk()
root.title('Simple  Application')
root.config(bg='SlateGrey')
root.geometry("")

# BackEnd
class Backend():
    def __init__(self):
        self.conn = sqlite3.connect('accounting.db')
        self.cur = self.conn.cursor()

        self.conn.execute("""CREATE TABLE IF NOT EXISTS account_type(
         id             INTEGER      PRIMARY KEY,
         category_type    INTEGER      NOT NULL,
         category_id      TEXT         NOT NULL
         )"""),

        self.conn.commit()
        self.conn.close()

    def insert_account_type(self, category_type, category_id):
        self.conn = sqlite3.connect('accounting.db')
        self.cur = self.conn.cursor()
        self.cur.execute("""INSERT INTO  account_type(category_id, category_type) VALUES(?,?);""",
                         (self,category_type, category_id,))
        self.conn.commit()
        self.conn.close()

    def view_account_type(self):
        self.conn = sqlite3.connect('accounting.db')
        self.cur = self.conn.cursor()
        self.cur.execute("SELECT * FROM account_type")
        self.rows = self.cur.fetchall()
        self.conn.close()
        return self.rows

# calling the class
tb = Backend()

# Front End
class Frontend():
    def __init__(self, master):
        # Frames

        self.top_frame = LabelFrame(master,bg ='SlateGrey', relief=SUNKEN)
        self.top_frame.pack()

        self.bottom_frame = LabelFrame(master, bg = 'SlateGrey', relief=SUNKEN)
        self.bottom_frame.pack()

        self.right_frame = LabelFrame(self.top_frame, bg = 'SlateGrey', relief = FLAT,
                                      text = 'Details Entry',fg = 'maroon')
        self.right_frame.pack(side = RIGHT, anchor = NE)

        self.side_frame = LabelFrame(self.top_frame,bg ='SlateGrey',relief=SUNKEN,text = 'Menu Buttons',fg = 'maroon')
        self.side_frame.pack(side = LEFT,anchor = NW)

        self.bot_frame = LabelFrame(self.bottom_frame, bg='Grey',relief = SUNKEN,text = 'Field View',fg = 'maroon')
        self.bot_frame.pack(side = BOTTOM,anchor = SW)

        # Side Buttons
        self.btn1 = Button(self.side_frame,
                           text='Main Account Types',
                           bg='SteelBlue4',
                           font=('cambria', 11),
                           anchor=W,
                           fg='white',
                           width=18,height=2,
                           command=lambda :[self.main_account()])
        self.btn1.grid(row=0, column=0, pady=0, sticky=W)

    def main_account(self):

        # variables
        self.category_type = StringVar()
        self.category_id = StringVar()

        # functions
        def add_main_accounts():
            if self.category_type.get() == "" or self.category_id.get() == "":
                tkinter.messagebox.showinfo('All fields are required')
            else:
                Backend.insert_account_type(
                    self.category_type.get(),
                    self.category_id.get(),)   # category type unfilled

                tkinter.messagebox.showinfo('Entry successful')

        def display_account_types(self):
            self.trv.delete(*self.trv.get_children())
            for self.rows in Backend.view_account_type(self):
                self.trv.insert("", END, values=self.rows)

        def get_account_type(e):
            self.selected_row = self.trv.focus()
            self.data = self.trv.item(self.selected_row)
            global row
            row = self.data["values"]

            """Grab items and send them to entry fields"""
            self.category_id.set(row[1])
            self.category_type.set(row[2])

        """=================TreeView==============="""
        # Scrollbars
        ttk.Style().configure("Treeview", background = "SlateGrey", foreground = "white", fieldbackground = "grey")

        scroll_x = Scrollbar(self.bot_frame, orient = HORIZONTAL)
        scroll_x.pack(side = BOTTOM, fill = X)

        scroll_y = Scrollbar(self.bot_frame, orient = VERTICAL)
        scroll_y.pack(side = RIGHT, fill = Y)

        # Treeview columns & setting scrollbars
        self.trv = ttk.Treeview(self.bot_frame, height=3, columns=
        ('id', 'category_id', 'category_type'), xscrollcommand = scroll_x.set, yscrollcommand = scroll_y.set)

        # Treeview style configuration
        ttk.Style().configure("Treeview", background = "SlateGrey", foreground = "white", fieldbackground = "grey")

        # Configure vertical and Horizontal scroll
        scroll_x.config(command = self.trv.xview)
        scroll_y.config(command = self.trv.yview)

        # Treeview Headings/columns
        self.trv.heading('id', text = "No.")
        self.trv.heading('category_id', text = 'Category ID')
        self.trv.heading('category_type', text = 'Category Type')

        self.trv['show'] = 'headings'

        # Treeview columns width
        self.trv.column('id', width = 23)
        self.trv.column('category_id', width = 70)
        self.trv.column('category_type', width = 100)

        self.trv.pack(fill = BOTH, expand = YES)

        # Binding Treeview with data
        self.trv.bind('<ButtonRelease-1>',get_account_type)

        # Account Types Labels
        self.lbl1 = Label(self.right_frame,text = 'Category ID',anchor = W,
                          width=10,font = ('cambria',11,),bg = 'SlateGrey')
        self.lbl1.grid(row = 0,column = 0,pady = 5)

        self.lbl2 = Label(self.right_frame, text = 'Category Type', anchor = W,
                          width = 10,font = ('cambria',11,),bg = 'SlateGrey')
        self.lbl2.grid(row = 1, column = 0,pady = 5,padx=5)

        self.blank_label = Label(self.right_frame, bg='SlateGrey')
        self.blank_label.grid(row=2, columnspan=2, pady=10)

        # Account Type Entries
        self.entry1 = Entry(self.right_frame,textvariable = self.category_id,
                            font = ('cambria',11,),bg = 'Grey',width=14)
        self.entry1.grid(row = 0,column=1,sticky = W,padx = 5)

        self.entry2 = Entry(self.right_frame, textvariable = self.category_type,
                            font = ('cambria', 11,), bg = 'Grey',width = 14)
        self.entry2.grid(row = 1, column = 1, sticky = W,pady = 5,padx = 5)

        # Buttons
        self.btn_1 = Button(self.right_frame,text = 'Add',font = ('cambria',12,'bold'),bg = 'SlateGrey',
                            activebackground='green', fg = 'white',width=12,height = 2,relief=RIDGE,
                            command = lambda :[add_main_accounts()])
        self.btn_1.grid(row = 3,column = 0,pady = 15)

        self.btn_2 = Button(self.right_frame, text = 'View', font = ('cambria', 12, 'bold'),
                            bg = 'SlateGrey',command=lambda :[display_account_types()],
                           activebackground='green', fg ='white', width=12, height = 2, relief = RIDGE)
        self.btn_2.grid(row = 3, column = 1)

# calling the class
app = Frontend(root)

root.mainloop()

Solution

  • I got and answer to this question,

    I just passed in the 'self' argument to the inner nested functions of the class as below and it worked.

     # functions
            def add_main_accounts(self):
                if self.category_id.get() == "" or self.category_type.get() == "":
                    tkinter.messagebox.showinfo('All fields are required')
                else:
                    Backend.insert_account_type(self,
                        self.category_id.get(),
                        self.category_type.get())   # category type unfilled
    
                    tkinter.messagebox.showinfo('Entry successful')
    
            def display_account_types(self):
                self.trv.delete(*self.trv.get_children())
                for rows in Backend.view_account_type(self):
                    self.trv.insert("", END, values = rows)
                return
    
            def get_account_type(e):
                self.selected_row = self.trv.focus()
                self.data = self.trv.item(self.selected_row)
                global row
                self.row = self.data["values"]
    
                """Grab items and send them to entry fields"""
                self.category_id.set(row[1])
                self.category_type.set(row[2])