Tkinter+sqlite3开发点击任意删除按钮仅删除列表最后一项问题
问题根因
- 核心原因是Python的闭包变量晚绑定机制:你定义的
delete函数内部引用的全局变量i,不会在循环创建按钮时就固定对应每一行的用户数据,只会在按钮点击触发delete执行时才会查找i的实际值。此时循环已经执行完毕,i已经被赋值为用户列表的最后一个元素,所以所有删除操作最终都会删除最后一条用户数据。 - 额外问题:你当前直接拼接SQL语句的写法存在SQL注入风险,需要优化为参数化查询。
修复方案
步骤1:改造delete函数,支持接收用户oid作为入参
def delete(user_oid): conn = sqlite3.connect("database.db") c = conn.cursor() # 使用参数化查询避免SQL注入风险 c.execute("DELETE FROM databasetable WHERE oid = ?", (user_oid,)) conn.commit() conn.close()
步骤2:绑定按钮回调时捕获当前行的oid瞬时值
你可以任选以下两种方法之一实现参数绑定:
方法1:使用lambda默认参数捕获瞬时值
for i in listfromdatabase: label = Label(frameskidlararenamn, text=i[0]) label.pack() # 通过lambda的默认参数在定义时就固定当前轮次的oid值 button = Button(frameskidlarareknapp, text="Delete " + str(i[0]), command=lambda oid=i[5]: delete(oid)) button.pack()
方法2:使用functools.partial绑定参数
from functools import partial # 循环内创建按钮的代码修改为 for i in listfromdatabase: label = Label(frameskidlararenamn, text=i[0]) label.pack() button = Button(frameskidlarareknapp, text="Delete " + str(i[0]), command=partial(delete, i[5])) button.pack()
内容的提问来源于stack exchange,提问作者alexander
相关产品推荐
相关产品推荐

