Не получается переписать код дискорд бота с использованием PostgreSQL
Я пишу дискород бота, который при включении или присоединении пользователя к серверу должен добавлять его в бд. В начале в качестве бд я использовал sqlite3, но после того как залил бота на Heroku и столкнулся с тем, что данные стираются спустя какое-то время, узнал что Heroku не использует sqlite3, и поэтому мне нужно использовать PostgreSQL. Вот мой старый код с sqlite3:
connect = sqlite3.connect("server.dp")
cursor = connect.cursor()
@bot.event
async def on_ready():
"""Функция on_ready выполняется при запуске бота и создаёт таблицу users
в бд, также добавляет в бд имена, id, количество xp и сервер всех
участников, которых нет в бд.
"""
DiscordComponents(bot)
cursor.execute("""CREATE TABLE IF NOT EXISTS users (
name TEXT,
id INT,
xp INT
)""")
for guild in bot.guilds:
for member in guild.members:
if cursor.execute(f"SELECT id FROM users WHERE id = {member.id}").fetchone() is None:
if member.id not in bots:
cursor.execute(f"INSERT INTO users VALUES ('{member}', {member.id}, 0)")
connect.commit()
print("Bot connected!")
@bot.event
async def on_member_join(member):
"""Функция on_member_join добавляет в бд имя, id, количество
xp и сервер пользователя, если его ещё нет в бд.
"""
if cursor.execute(f"SELECT id from users WHERE id = {member.id}").fetchone()[0] is None:
cursor.execute(f"INSERT INTO users VALUES ('{member}', {member.id}, 0, {member.guild.id})")
connect.commit()
А вот моя попытка переделать это на PostgreSQL:
connect = psycopg2.connect(db_uri, sslmode="require")
cursor = connect.cursor()
@bot.event
async def on_ready():
"""Функция on_ready выполняется при запуске бота и создаёт таблицу users
в бд, также добавляет в бд имена, id, количество xp и сервер всех
участников, которых нет в бд.
"""
DiscordComponents(bot)
cursor.execute("""CREATE TABLE IF NOT EXISTS users (
name TEXT,
id INT,
xp INT
)""")
for guild in bot.guilds:
for member in guild.members:
if cursor.execute(f"SELECT id FROM users WHERE id = {member.id}").fetchone() is None:
if member.id not in bots:
cursor.execute(f"INSERT INTO users VALUES ('{member}', {member.id}, 0)")
connect.commit()
print("Bot connected!")
@bot.event
async def on_member_join(member):
"""Функция on_member_join добавляет в бд имя, id, количество
xp и сервер пользователя, если его ещё нет в бд.
"""
if cursor.execute(f"SELECT id from users WHERE id = {member.id}").fetchone()[0] is None:
cursor.execute(f"INSERT INTO users VALUES ('{member}', {member.id}, 0, {member.guild.id})")
connect.commit()
В connect = psycopg2.connect(db_uri, sslmode="require") я подключаю бд из Heroku (созданной с помощью аддона Heroku Postgres)
Но при попытке запуска бота получаю такую ошибку:
Ignoring exception in on_ready
Traceback (most recent call last):
File "C:\Users\belog\hat_dispenser\venv\lib\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "C:\Users\belog\hat_dispenser\main.py", line 56, in on_ready
if cursor.execute(f"SELECT id FROM users WHERE id = {member.id}").fetchone() is None:
AttributeError: 'NoneType' object has no attribute 'fetchone'
Как это исправить?
Ответы (1 шт):
Выдержка из документации.
execute(query, vars=None)
Execute a database operation (query or command).
Parameters may be provided as sequence or mapping and will be bound to variables in the operation. Variables are specified either with positional (%s) or named (%(name)s) placeholders. See Passing parameters to SQL queries.
The method returns None. If a query was executed, the returned values can be retrieved using fetch*() methods.
Это значит, что Вы должны сначала выполнить запрос cursor.execute(). А потом отдельно получить результат через cursor.fetchone() ссылка.
Пример из документации:
>>> cur.execute("SELECT * FROM test WHERE id = %s", (3,))
>>> cur.fetchone()
(3, 42, 'bar')