Как записать текст с кнопки aiogram в SQL?

Рейтинг: 1Ответов: 1Опубликовано: 19.02.2023

Как записать текст, который содержит кнопка в БД? Неужели нужно писать под каждую кнопку свой обработчик?

У меня есть код:

@dp.callback_query_handler(text="True")
async def is_got_acquainted(message: types.Message):
    await bot.delete_message(message.from_user.id, message.message.message_id)
    await bot.send_message(message.from_user.id, "Спасибо! Мы ценим ваше внимание!\nОтветьте на 3 вопроса, и получи скидку на продление!")
    db.is_acquainted_True(message.from_user.id)  # добавляет в бд
    await asyncio.sleep(1)  # тут рельно 1 секунда должна быть
    await Survey.experience.set()
    await bot.send_message(message.from_user.id, "Какой у вас опыт в трейдниге?", reply_markup=keybards.FirstQMenu)

@dp.message_handler(state=Survey.experience)
async def deposit_question(message: types.Message, state: Survey):
    db.add_experience(message.text, message.from_user.id)
    await Survey.next()
    await bot.send_message(message.from_user.id, "Какой у вас размер депозита?", reply_markup=keybards.SecondQMenu)

Благодаря функции add_experience я добавляю данные в SQL. Но проблема в том, что она не добавляет текст с кнопки, а только тот, который пользователь напишет сам. Мне нужно чтобы в бд попадал текст именно с кнопки, при нажатии на нее. Я понимаю что использование message.text в данном случае не верно, но как тогда это сделать?

# добавление ответов на вопросы
def add_experience(self, message, user_id):
    with self.connection:
        return self.cursor.execute("UPDATE clientdata SET (experience)=(?) WHERE user_id = (?)",
                                   (message, user_id,))

После исправлений получился следующий код

# СОСТОЯНИЯ

# Ловим ответ на первый вопрос. Кнопки к первому вопросу
@dp.message_handler(state=Survey.experience)
@dp.callback_query_handler(text="1_1")
async def experience_handler_depo1(callback_query: types.CallbackQuery, state: Survey):
    db.add_experience("Менее 1 года", callback_query.from_user.id)
    await Survey.next()
    await bot.send_message(callback_query.from_user.id, "Какой у вас размер депозита?", reply_markup=keybards.SecondQMenu)

@dp.message_handler(state=Survey.experience)
@dp.callback_query_handler(text="1_2")
async def experience_handler_depo2(callback_query: types.CallbackQuery, state: Survey):
    db.add_experience("От 1 года до 2 лет", callback_query.from_user.id)
    await Survey.next()
    await bot.send_message(callback_query.from_user.id, "Какой у вас размер депозита?", reply_markup=keybards.SecondQMenu)

@dp.message_handler(state=Survey.experience)
@dp.callback_query_handler(text="1_3")
async def experience_handler_depo3(callback_query: types.CallbackQuery, state: Survey):
    db.add_experience("От 2 лет до 3 лет", callback_query.from_user.id)
    await Survey.next()
    await bot.send_message(callback_query.from_user.id, "Какой у вас размер депозита?", reply_markup=keybards.SecondQMenu)

@dp.message_handler(state=Survey.experience)
@dp.callback_query_handler(text="1_4")
async def experience_handler_depo4(callback_query: types.CallbackQuery, state: Survey):
    db.add_experience("Более 3 лет", callback_query.from_user.id)
    await Survey.next()
    await bot.send_message(callback_query.from_user.id, "Какой у вас размер депозита?", reply_markup=keybards.SecondQMenu)

Как оставляя состояния сделать все верно?

Ответы

▲ 1Принят

Чтобы в базу данных попадал текст с кнопки, нужно передавать не только text при обработке колбэка, но и параметр callback_data в аргументах кнопки. Этот параметр будет содержать данные, которые вы хотите добавить в базу данных. Примерно так

# Создание кнопки с callback_data
button = InlineKeyboardButton(text='Нажми меня', callback_data='some_data')

# Обработка колбэка с callback_data
@dp.callback_query_handler(lambda callback_query: callback_query.data == 'some_data')
async def some_callback_handler(callback_query: types.CallbackQuery):
    await bot.send_message(callback_query.from_user.id, 'Вы нажали на кнопку')
    db.add_button_clicked('Нажми меня', callback_query.from_user.id)

# Добавление данных в базу данных с callback_data
def add_button_clicked(self, button_text, user_id):
    with self.connection:
        return self.cursor.execute("UPDATE clientdata SET (button_clicked)=(?) WHERE user_id = (?)",
                                   (button_text, user_id,))

Так ну можно попробовать вынести общую логику из обработчиков колбеков в отдельную функцию. Также, можно использовать фабрику декораторов для уменьшения дублирования кода.

def add_answer_and_ask_next_question(answer_text, question_text, callback_query):
    db.add_experience(answer_text, callback_query.from_user.id)
    await Survey.next()
    await bot.send_message(callback_query.from_user.id, question_text, reply_markup=keybards.SecondQMenu)

def experience_handler_factory(answer_text, question_text):
    @dp.callback_query_handler(text=answer_text)
    async def experience_handler(callback_query: types.CallbackQuery, state: Survey):
        await add_answer_and_ask_next_question(answer_text, question_text, callback_query)

    @dp.message_handler(state=Survey.experience)
    async def message_handler(message: types.Message, state: Survey):
        db.add_experience(message.text, message.from_user.id)
        await Survey.next()
        await bot.send_message(message.from_user.id, question_text, reply_markup=keybards.SecondQMenu)

    return experience_handler, message_handler

experience_handler_depo1, _ = experience_handler_factory("1_1", "Какой у вас опыт в трейдинге?")
experience_handler_depo2, _ = experience_handler_factory("1_2", "Какой у вас опыт в трейдинге?")
experience_handler_depo3, _ = experience_handler_factory("1_3", "Какой у вас опыт в трейдинге?")
experience_handler_depo4, _ = experience_handler_factory("1_4", "Какой у вас опыт в трейдинге?")

Еще один вариант решения использовать callback_data вместо text. Можно будет передавать не только текст, который будет отображаться на кнопке, но и доп инфу

# создание кнопок
keyboard = types.InlineKeyboardMarkup()
button1 = types.InlineKeyboardButton(text="Менее 1 года", callback_data="experience_1")
button2 = types.InlineKeyboardButton(text="От 1 года до 2 лет", callback_data="experience_2")
button3 = types.InlineKeyboardButton(text="От 2 лет до 3 лет", callback_data="experience_3")
button4 = types.InlineKeyboardButton(text="Более 3 лет", callback_data="experience_4")
keyboard.row(button1, button2)
keyboard.row(button3, button4)

# обработка нажатия на кнопку
@dp.callback_query_handler(lambda c: c.data and c.data.startswith('experience_'))
async def experience_handler(callback_query: types.CallbackQuery, state: Survey):
    experience = callback_query.data.split('_')[1]
    db.add_experience(experience, callback_query.from_user.id)
    await Survey.next()
    await bot.send_message(callback_query.from_user.id, "Какой у вас размер депозита?", reply_markup=keybards.SecondQMenu)