RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1604640
Accepted
wanderer
wanderer
Asked:2025-01-12 17:51:08 +0000 UTC2025-01-12 17:51:08 +0000 UTC 2025-01-12 17:51:08 +0000 UTC

代码检查:数据库查询

  • 772

我正在制作一个日程通知机器人,我必须接触它们классы,但我从未遇到过它们:

import sqlite3

class RequestsInBD:
    def __init__(self):
        self.connection = sqlite3.Connection('datebase_of_users.db')
        self.cursor = self.connection.cursor()

    def _commit_and_close_bd(self, connection):
        connection.commit()
        connection.close()
    
    def check(self, user_id):
        all_id = self.cursor.execute('SELECT id FROM grade_of_users').fetchall()
        self._commit_and_close_bd(self.connection)
        for item in all_id:
            if user_id in item:
                return False
        return True
    
    def add_user(self, user_id, grade):
        self.cursor.execute(f'INSERT INTO grade_of_users (id, grade, notifications) VALUES (?, ?, ?)', (user_id, grade, 1))
        self._commit_and_close_bd(self.connection)

    def return_user_grade(self, user_id):
        self.cursor.execute(f'SELECT id, grade FROM grade_of_users WHERE id = {user_id}')
        grade = self.cursor.fetchone()[1]
        self._commit_and_close_bd(self.connection)
        return grade if grade else False
    
    def get_users(self):
        self.cursor.execute('SELECT id, grade, notifications FROM grade_of_users')
        res = self.cursor.fetchall()
        self._commit_and_close_bd(self.connection)
        return res
    
    def new_grade(self, grade, user_id):
        self.cursor.execute(f'UPDATE grade_of_users SET grade = ? WHERE id = ?', (grade, user_id))
        self._commit_and_close_bd(self.connection)

代码看起来可以工作,但是写得正确吗? Chatgpt 说原则上一切都很好,但我有点不确定他的话。 (此代码出现在与主程序分开的文件中,我从主程序导入此类,并且每次调用时我都会创建此类的对象(实例),我不确定这是否也是正确的)

python
  • 2 2 个回答
  • 51 Views

2 个回答

  • Voted
  1. Best Answer
    Швеев Алексей
    2025-01-12T18:50:35Z2025-01-12T18:50:35Z

    SQL注入

    最危险的错误是使用直接字符串替换。攻击者可以轻松扩展他们的查询并从数据库中获取几乎所有数据。

    要安全地将参数传递给请求,您可以通过sqlite3以下方式使用库的检测:

    self.cursor.execute(f'INSERT INTO grade_of_users (id, grade, notifications) VALUES (?, ?, 1)', (user_id, grade))
    

    文档

    每次请求时关闭连接

    斯坦尼斯拉夫·沃洛达尔斯基指出

    对象允许您创建一次并在整个代码中使用。因此,不断地创建和删除数据库连接是没有意义的。

    _commit_and_close_bd(或者更确切地说_commit_and_close_db)最好将其分为两种方法:

    commit并close相应地。

    现在,在每个查询结束时,您可以使用 将更改数据保存到数据库commit,但继续对新查询使用相同的连接:

    db = RequestsInBD()
    
    db.add_user(5325, "other")
    db.add_user(1241, "something")
    ...
    # Завершение работы приложения:
    db.close()
    

    好消息是,在您的情况下,您只需要在程序的最开始创建连接并仅在最后关闭它。

    此外,这些方法也不应该接受参数,因为连接已经可以通过self

    命名

    首先,不是bd,但是db,从字面上看DataBase。

    其次,我会将其重命名RequestsInBD为UsersDatabase.

    好吧,return_user_grade最好将函数重命名为get_user_grade,将函数重命名add_grade为set_grade

    多功能性

    您的数据库当前仅从名为的文件导入datebase_of_users.db

    但是,如果您想更改它、在配置中显示它,甚至需要同时连接到多个实例,该怎么办?

    初始化时最好传递参数:

    class UsersDatabase:
        def __init__(self, file):
            self.connection = sqlite3.Connection(file)
            self.cursor = self.connection.cursor()
    
    ...
    
    users_db = UsersDatabase("database_of_users.db")
    

    模块化

    我不确定你是否将所有内容都放在一个文件中,但以防万一......

    建议将带有数据库的类放在您自己的文件中,然后通过以下方式导入import file_name:

    文件database/users_database.py:

    import sqlite3
    
    class UsersDatabase:
        ...
    

    文件main.py:

    from database.users_database import UsersDatabase
    
    users_db = UsersDatabase("database.db")
    
    # Основное приложение
    ...
    
    # Конец приложения:
    db.close()
    

    优化

    在该方法中,check与其id从数据库中获取所有ID并搜索自己的ID(其数量可以达到数千个),不如立即使用以下工具检查该ID是否在数据库中SQL:

    def check(self, user_id):
        result = self.cursor.execute('SELECT 1 FROM grade_of_users WHERE id = ?', (user_id,)).fetchone()
        
        self.commit() # А нужен ли вообще?
        
        return result is None
    

    全部的

    这会产生以下代码:

    import sqlite3
    
    class UsersDatabase:
        def __init__(self, path):
            self.connection = sqlite3.Connection(path)
            self.cursor = self.connection.cursor()
    
        def commit(self):
            self.connection.commit()
            
        def close(self):
            self.connection.close()
        
        def check(self, user_id):
            result = self.cursor.execute('SELECT 1 FROM grade_of_users WHERE id = ?', (user_id,)).fetchone()
        
            self.commit() # А нужен ли вообще?
        
            return result is None
        
        def add_user(self, user_id, grade):
            self.cursor.execute('INSERT INTO grade_of_users (id, grade, notifications) VALUES (?, ?, 1)', (user_id, grade))
            self.commit()
    
        def get_user_grade(self, user_id):
            self.cursor.execute('SELECT id, grade FROM grade_of_users WHERE id = ?', (user_id,))
            grade = self.cursor.fetchone()[1]
            self.commit()
            return grade if grade else False
        
        def get_users(self):
            self.cursor.execute('SELECT id, grade, notifications FROM grade_of_users')
            res = self.cursor.fetchall()
            self.commit()
            return res
        
        def set_grade(self, grade, user_id):
            self.cursor.execute(f'UPDATE grade_of_users SET grade = ? WHERE id = ?', (grade, user_id))
            self.commit()
    

    应该这样使用:

    from users_database import UsersDatabase
    
    users_db = UsersDatabase("datebase_of_users.db")
    
    users_db.add_user(1324, "abc")
    users_db.set_grade(1324, "other")
    ...
    
    # в конце:
    users_db.close()
    
    • 3
  2. Noskill
    2025-01-12T22:04:59Z2025-01-12T22:04:59Z
    def get_user_grade(self, user_id):
            self.cursor.execute('SELECT id, grade FROM grade_of_users WHERE id = ?', (user_id,))
            grade = self.cursor.fetchone()[1]
            self.commit()
            return grade if grade else False
    

    如果什么都没有怎么办? grade = self.cursor.fetchone()[1] 如果没有的话会返回什么?如果本身没有grade_of_users表怎么办?为什么不将与数据库的连接(打开和关闭)放在上下文管理器中?

    • 0

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5