【问题标题】:simple CLI todo manager with sqlite3 database storing problem带有 sqlite3 数据库存储问题的简单 CLI 待办事项管理器
【发布时间】:2020-04-07 17:56:09
【问题描述】:

我目前正在尝试制作一个命令行待办事项管理器,它允许用户输入任务、删除它并列出任务。从我尝试可视化的结果来看,它并没有像我想象的那样做,这是我第一次使用 sqlite3。

我想要达到的目标:

  • 将任务存储在数据库中,这将自动为其添加递增的 ID。

例子:

python todo.py -add do the laundry on Sunday

[in the database]
Id   Task
1    do the laundry on Sunday

我的代码。

import sqlite3
import argparse


def parse_args():
    desc = 'Todo manager for storing and removing tasks'
    parser = argparse.ArgumentParser(description=desc)
    parser.add_argument("-a", "--add", "-add", help="To add a new item to the list",
                        type=str, nargs="+")
    parser.add_argument("-r", "-remove", "--remove", help="To remove an item from the list",
                        type=int)
    parser.add_argument("-l", "-list", "--list", help="displays the tasks or task in the list",
                        nargs="*")
    args = parser.parse_args()
    return args


@staticmethod
def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d


def get_todo_list():
    database_connection.row_factory = dict_factory
    cursor = database_connection.cursor()
    cursor.execute("select rowid, * FROM todo_list")
    return cursor.fetchall()


def add_to_todo_list(num,task):
    cursor = database_connection.cursor()
    cursor.execute("INSERT INTO todo_list VALUES (?)", (str(task),))
    database_connection.commit()


def remove_from_todo_list(rowid):
    cursor = database_connection.cursor()
    cursor.execute("DELETE FROM todo_list WHERE rowid = ?", (rowid,))
    database_connection.commit()


if __name__ == '__main__':
    commands = parse_args()
    # Creating table for database using sqlite
    database_connection = sqlite3.connect('todo_list.db')
    cursor = database_connection.cursor()
    cursor.execute('''CREATE TABLE if not exists todo_list(
                  description TEXT);''')
    database_connection.commit()

    if commands.add:
        # Stops accepting tasks when there is a blank task as input. 
        if not commands.add == ' ':
           add_to_todo_list(commands.add)
    elif commands.remove:
        remove_from_todo_list(commands.remove)
    elif commands.list:
        get_todo_list()

但是,当我尝试存储数据时,我的数据库不接受任何值。通过在创建表时将 Id 设置为 Id INTEGER PRIMARY KEY,即

cursor.execute('''CREATE TABLE if not exists todo_list(
                      Id INTEGER PRIMARY KEY
                      description TEXT);''')

当我将数据添加到数据库时,Id 会增加吗?

【问题讨论】:

  • 试试cursor.execute("INSERT INTO todo_list VALUES (?,?)", (int(num), task,))。您来自argparse 的输入以strs 的形式出现,但您在数据库中将ID 列定义为INTEGER。
  • @FelipeFaria 是的,这很好!我尝试删除 num 变量,因为我意识到对于任务中的每个空间,对于 for 循环来说,这将是一个单独的东西。我会在帖子中编辑我的代码。但是,数据库似乎没有改变,因为我尝试获取其中的数据。
  • 我会在您编辑帖子时回复并编辑它,这样我们就不会在这里来回走动。更新帖子时向我发送更新评论

标签: python sqlite command-line argparse


【解决方案1】:

sqlite3.InterfaceError: Error binding parameter 1 - probably unsupported type.

您来自argparse 的输入以str 的形式出现,但您在数据库中将ID 列定义为INTEGER。修复是:

cursor.execute("INSERT INTO todo_list VALUES (?,?)", (int(num), task,))

将任务存储在数据库中,这将自动为其添加一个递增的 ID。

根据 sqlite 文档 here,定义 INTEGER PRIMARYKEY 将自动递增。只需将 null 值传递给它,sqlite 会为您处理其余的事情。


在显示和添加任务时,您的代码存在一些问题。首先,初始化数据库:

cursor.execute(
        """CREATE TABLE if not exists todo_list(
                      id INTEGER PRIMARY KEY,
                      description TEXT);"""
    )

在你的帖子编辑没问题之前你是怎么做到的。然后,add_to_todo_list:

def add_to_todo_list(task):
    cursor = database_connection.cursor()
    cursor.execute("INSERT INTO todo_list VALUES (?,?)", (None, str(task)))
    database_connection.commit()

注意num 从函数输入中被删除,None 被传递给ID 列。在get_todo_list() 中,您可以更轻松地获取它:

def get_todo_list():
    cursor = database_connection.cursor()
    cursor.execute("select * FROM todo_list")
    return cursor.fetchall()

解析参数的方式也需要修复;对于commands.list,您需要执行以下操作:

elif commands.list is not None:
    print(get_todo_list())

这是因为当您执行 app.py -list 时,commands.list 将成为 [],Python 计算结果为 False(空列表是错误的)。您还应该将函数的内容打印到终端——所以不要忘记这一点。通过上面的编辑,我可以在我的终端上进行:

python test.py -add Random Task!
python test.py -add Hello World!

python test.py -list
[(1, "['Random', 'Task!']"), (2, "['Hello', 'World!']")]

【讨论】:

  • 对此我深表歉意,我稍微编辑了我的帖子,您对输入错误是正确的。当我尝试通过命令行输入然后将其列出时,我的数据库似乎不接受任何值。
  • 它确实有效!这对commands.list 来说很有趣。不过我有一个问题,当使用fetchall() 函数时,它是否总是以字典的形式返回给用户?
  • 嗯,它返回一个list 的tuples 和表格的内容,而不是dict。您可以使用\n、" ".join(...) 和for-loops 轻松解析这些结果。在遍历.fetchall() 结果的循环中,从print(get_todo_list()) 中删除print(),而从get_todo_list() 函数中删除print。
  • 另外,应该提到:您在数据库中看到"['Random', 'Task!']" 与简单的Random Task! 相反的原因是因为argparse。如果您在add_to_todo_list() 函数task = " ".join(task) 的第一行添加,您将在下次执行-add 时看到它在数据库中将变为Random Task!。
  • 是的,argparse 将输入作为列表。这实际上允许你用它做一些时髦的事情,比如creating a git like structure。我很高兴听到您发现这很有帮助!祝你在学习冒险中好运。 :)
猜你喜欢
  • 1970-01-01
  • 2018-02-24
  • 2011-08-17
  • 2020-09-02
  • 2011-04-06
  • 1970-01-01
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多