我正在制作一个日程通知机器人,我必须接触它们классы
,但我从未遇到过它们:
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 说原则上一切都很好,但我有点不确定他的话。 (此代码出现在与主程序分开的文件中,我从主程序导入此类,并且每次调用时我都会创建此类的对象(实例),我不确定这是否也是正确的)
SQL注入
最危险的错误是使用直接字符串替换。攻击者可以轻松扩展他们的查询并从数据库中获取几乎所有数据。
要安全地将参数传递给请求,您可以通过
sqlite3
以下方式使用库的检测:文档
每次请求时关闭连接
斯坦尼斯拉夫·沃洛达尔斯基指出
对象允许您创建一次并在整个代码中使用。因此,不断地创建和删除数据库连接是没有意义的。
_commit_and_close_bd
(或者更确切地说_commit_and_close_db
)最好将其分为两种方法:commit
并close
相应地。现在,在每个查询结束时,您可以使用 将更改数据保存到数据库
commit
,但继续对新查询使用相同的连接:好消息是,在您的情况下,您只需要在程序的最开始创建连接并仅在最后关闭它。
此外,这些方法也不应该接受参数,因为连接已经可以通过
self
命名
首先,不是
bd
,但是db
,从字面上看DataBase
。其次,我会将其重命名
RequestsInBD
为UsersDatabase
.好吧,
return_user_grade
最好将函数重命名为get_user_grade
,将函数重命名add_grade
为set_grade
多功能性
您的数据库当前仅从名为的文件导入
datebase_of_users.db
但是,如果您想更改它、在配置中显示它,甚至需要同时连接到多个实例,该怎么办?
初始化时最好传递参数:
模块化
我不确定你是否将所有内容都放在一个文件中,但以防万一......
建议将带有数据库的类放在您自己的文件中,然后通过以下方式导入
import file_name
:文件
database/users_database.py
:文件
main.py
:优化
在该方法中,
check
与其id
从数据库中获取所有ID并搜索自己的ID(其数量可以达到数千个),不如立即使用以下工具检查该ID是否在数据库中SQL
:全部的
这会产生以下代码:
应该这样使用:
如果什么都没有怎么办? grade = self.cursor.fetchone()[1] 如果没有的话会返回什么?如果本身没有grade_of_users表怎么办?为什么不将与数据库的连接(打开和关闭)放在上下文管理器中?