sqlite 如何修复此错误?self. category_id. set(行[1]),索引错误:字符串索引超出范围

j91ykkif  于 2023-01-02  发布在  SQLite
关注(0)|答案(1)|浏览(119)

我添加数据到sqlite表,当我试图更新表,我得到这个错误'字符串索引不在范围内'.
同样,当我执行update命令时,除了identity列之外,所有列都被更新,但我的目的只是更新选定的行。
下面的代码中我没有做什么〉
您的协助将不胜感激。
错误发生在函数update_record(self)中。
这是我的代码:

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

root =Tk()
root.title('Accounting App')
root.config(bg='#3d6466')
root.geometry("520x400")
root.resizable(False, False)

style = ttk.Style()
style.theme_use('alt')
style.configure("TCombobox", fieldbackground="Grey", background="Grey")

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

        #self.conn.execute("""DROP TABLE IF EXISTS account_type""")

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

        self.conn.commit()
        # elf.conn.close()

    # =========Account Type======
    class Account_type():

        def insert_account_type(self, category_id, category_type):
            self.conn = sqlite3.connect('accounting.db')
            self.cur = self.conn.cursor()
            self.cur.execute("""INSERT INTO  account_type(category_id,category_type) VALUES(?,?);""",
                             (category_id, category_type,))
            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")
            rows = self.cur.fetchall()
            self.conn.close()
            return rows

acc_type = Backend.Account_type()
tb = Backend()

class Front_end():
    def __init__(self, master):
        # Frames

        global cur
        global conn
        conn = sqlite3.connect('accounting.db')
        cur = conn.cursor()
        # Frames
        self.left_frame = LabelFrame(master,bg='#3d6466', relief=SUNKEN,width=200)
        self.left_frame.pack(fill = 'both',expand = YES , padx = 5,side=LEFT,anchor=NW)
        self.right_frame = LabelFrame(master, bg='#3d6466', relief=SUNKEN)
        self.right_frame.pack(fill = 'both',expand = YES ,side=LEFT,anchor=NW)

        self.top_right_frame = LabelFrame(self.right_frame, bg='#3d6466', relief=SUNKEN,text='Details',fg='maroon')
        self.top_right_frame.pack(fill=BOTH,side=TOP, anchor=NW,expand=YES)

        self.top_r_inner_frame = LabelFrame(self.right_frame, bg='#3d6466', relief=SUNKEN, text='...', fg='maroon',height=10)
        self.top_r_inner_frame.pack(fill=BOTH, side=TOP, anchor=SW, expand=YES)

        self.bottom_right_frame = LabelFrame(self.right_frame, bg='#3d6466', relief=SUNKEN, text='Field View', fg='maroon')
        self.bottom_right_frame.pack(fill=BOTH,side=TOP, anchor=SW, expand=YES)

        self.my_canvas = Canvas(self.top_right_frame,bg='#3d6466')
        self.my_canvas.pack(side=LEFT,fill='both', expand=YES)

        # vertical configuration of scrollbar
        self.yscrollbar = ttk.Scrollbar(self.top_right_frame, orient=VERTICAL, command = self.my_canvas.yview)
        self.yscrollbar.pack(side=RIGHT,fill='both')

        self.my_canvas.config(yscrollcommand = self.yscrollbar.set)

        self.top_right_frame = Frame(self.my_canvas, bg='#3d6466', relief=SUNKEN)
        self.my_canvas.create_window((0,0),window=self.top_right_frame, anchor=NW)
        self.my_canvas.bind('<Configure>',lambda e:self.my_canvas.configure(scrollregion = self.my_canvas.bbox('all')))

        self.side_frame = LabelFrame(self.left_frame,bg='#3d6466',relief=SUNKEN,text='Menu Buttons',fg='maroon',)
        self.side_frame.pack(side=TOP,anchor=NW,expand=YES )

        # Side Buttons
        self.btn1 = Button(self.side_frame, text='Main Account Types', bg='#3d6466', font=('cambria', 12), anchor=W,
                           fg='white', width=18,height=2,command=self.main_account)
        self.btn1.grid(row=0, column=0, sticky=W)

    def main_account(self):

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

        self.category_search =StringVar()

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

                tkinter.messagebox.showinfo('Entry successful')

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

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

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

        def clear(self):
            self.category_id.set("")
            self.category_type.set("")

        **def update_record(self):
            selected = self.trv.focus()
            self.trv.item(selected, values=(
                self.category_id.get(), self.category_type.get()))
            conn = sqlite3.connect("accounting.db")
            cur = conn.cursor()
            if self.category_id.get() == "" or self.category_type.get() == "" :
                tkinter.messagebox.showinfo('All fields are required!')
                return
            update_record = tkinter.messagebox.askyesno('Confirm please',
                                                        'Do you want to update records?')
            if update_record > 0:
                cur.execute(
                    "UPDATE account_type SET category_id=:cat_id, category_type=:type",
                     {'cat_id': self.category_id.get(), 'type': self.category_type.get()})
                tkinter.messagebox.showinfo('Record update successful!')
            conn.commit()**

            # call the function for Clearing the fields
            clear(self)
            conn.close()

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

        scroll_x = Scrollbar(self.bottom_right_frame, orient = HORIZONTAL)
        scroll_x.pack(side = BOTTOM, fill = X)
        scroll_y = Scrollbar(self.bottom_right_frame, orient = VERTICAL)
        scroll_y.pack(side = RIGHT, fill = Y)

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

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

        # 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 = 50)
        self.trv.column('category_id', width = 70)
        self.trv.column('category_type', width = 90)

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

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

        # Account Types Labels
        self.lbl1 = Label(self.top_right_frame,text = 'Category ID',anchor = W,width=12,font = ('cambria',13,),bg = '#3d6466')
        self.lbl1.grid(row = 0,column = 0,pady = 5)

        self.lbl1 = Label(self.top_right_frame, text='Category Type', anchor=W, width=12, font=('cambria', 13,),  bg='#3d6466')
        self.lbl1.grid(row=1, column=0, pady=5)

        self.lbl2 = Label(self.top_right_frame, text='Search Account', anchor=W, width=12, font=('cambria', 13,),
                          bg='#3d6466')
        self.lbl2.grid(row=6, column=0, pady=5)

        # Account Type Entries
        self.entry1 = Entry(self.top_right_frame,textvariable = self.category_id,font = ('cambria',13,),bg = 'Grey',width=14)
        self.entry1.grid(row = 0,column=1,sticky = W,padx = 4,columnspan=2)
        self.entry1 = Entry(self.top_right_frame, textvariable=self.category_type, font=('cambria', 13,), bg='Grey', width=14)
        self.entry1.grid(row=1, column=1, sticky=W, padx=4, columnspan=2)
        self.entry2 = Entry(self.top_right_frame, textvariable=self.category_search, font=('cambria', 13,), bg='Grey', width=14)
        self.entry2.grid(row=6, column=1, sticky=W, padx=4, columnspan=2)

        # Buttons
        self.btn_1 = Button(self.top_right_frame,text='Add',font=('cambria',12,'bold'),bg='#3d6466',
                            activebackground='green', fg = 'white',width=12,height = 1,relief=RAISED,
                            command = lambda :[add_main_accounts(self),display_account_types(self),clear(self)])
        self.btn_1.grid(row = 3,column = 0,pady=6, padx=6)
        self.btn_2 = Button(self.top_right_frame, text = 'View',command=lambda :[display_account_types(self),clear(self)],
                            font=('cambria', 12, 'bold'), bg = '#3d6466', activebackground='green',
                           fg ='white', width=12, height = 1, relief=RAISED)
        self.btn_2.grid(row = 3, column=1,padx=0)
        self.btn_3 = Button(self.top_right_frame, text = 'Update', command= lambda :[update_record(self),
                                display_account_types(self)],font=('cambria', 12, 'bold'), bg = '#3d6466',
                           activebackground = 'green', fg='white', width = 12, height = 1, relief=RAISED)
        self.btn_3.grid(row = 4, column = 0,pady=6,padx=10)

# calling the class

app = Front_end(root)

root.mainloop()
toe95027

toe950271#

你的update函数会更新所有存在的记录。为了避免这种情况,你应该使用WHERE。这里是它的修正版本

def update_record(self):
    selected = self.trv.focus()
    
    oldValues = self.trv.item(selected)["values"]

    self.trv.item(selected, values=(oldValues[0],
        self.category_id.get(), self.category_type.get()))
    conn = sqlite3.connect("accounting.db")
    cur = conn.cursor()
    if self.category_id.get() == "" or self.category_type.get() == "" :
        tkinter.messagebox.showinfo('All fields are required!')
        return
    update_record = tkinter.messagebox.askyesno('Confirm please',
                                                'Do you want to update employee records?')
    if update_record > 0:
        cur.execute(
            "UPDATE account_type SET category_id=:cat_id, category_type=:type WHERE id=:id_value",
             {'cat_id': self.category_id.get(), 'type': self.category_type.get(), "id_value": oldValues[0]})
        tkinter.messagebox.showinfo('Record update successful!')
    conn.commit()

    # call the function for Clearing the fields
    clear(self)
    conn.close()

我们使用了选定的行idx等。然而,您的错误字符串索引超出范围不是关于这个。上面的函数将修复您的记录更新问题。您的错误是因为它试图显示一个记录值,但刷新表后,没有选择任何内容。所以它返回空。

def get_account_type(e):
    selected_row = self.trv.focus()
    data = self.trv.item(selected_row)
    row = data["values"]
    if(row == ""):
        return
    """Grab items and send them to entry fields"""
    self.category_id.set(row[1])
    self.category_type.set(row[2])

现在,如果row只是一个空字符串,函数将停止执行,并且不会出现错误。

相关问题