S
S
Sergey2021-10-25 20:03:19
Python
Sergey, 2021-10-25 20:03:19

How to get access to the message to which the inline button is attached in aiogram?

In general, I am writing a bot using the aiogram library, initially I implemented all the functions using commands, now I decided to implement some of the functions using inline buttons.

Perhaps it's important to note that I register handlers separately.

Here is the code for the 'list' command handler, which parses the database and displays records, each record has its own id, according to which certain operations are performed with them, and I attached these same inline buttons to each record.

spoiler

from aiogram import Dispatcher, types
from ..base import get_list_tasks, del_task


def get_keyboard():
    buttons: list = [
        types.InlineKeyboardButton(text='Редактировать', callback_data='edit'),
        types.InlineKeyboardButton(text='Удалить', callback_data='del')
    ]
    keyboard = types.InlineKeyboardMarkup(row_width=2)
    keyboard.add(*buttons)
    return keyboard


async def list_tasks(message: types.Message):
    keyboard = get_keyboard()
    user_id: int = message.from_user.id
    lt: list = get_list_tasks(user_id)
    if len(lt) == 0:
        await message.answer('Ни одного таска ещё не создано.')
    else:
        for task in lt:
            await message.answer(f'{task[0]}\n\n{task[1]}\n\nid: {task[-1]}', reply_markup=keyboard)


async def inline_del_handler(call: types.CallbackQuery, message: types.Message):
    # метод заглушка
    pass 


def register_handlers_list_task(dp: Dispatcher, admin_id: int):
    dp.register_message_handler(list_tasks, commands=['list'])



Here is the code for the original edit command:
spoiler

from aiogram import Dispatcher, types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from Tasker_bot.app.base import edit_task


class StateEdit(StatesGroup):
    edit_id = State()
    edit_title = State()
    edit_body = State()


async def editing_start(message: types.Message):
    await message.answer('Введите id редактируемого таска:')
    await StateEdit.edit_id.set()


async def editing_title(message: types.Message, state: FSMContext):
    await state.update_data(id=message.text)
    await StateEdit.next()
    await message.answer('Введите новый заголовок:')


async def editing_body(message: types.Message, state: FSMContext):
    await state.update_data(title=message.text)
    await StateEdit.next()
    await message.answer('Введите новый текст:')


async def editing_task(message: types.Message, state: FSMContext):
    await state.update_data(body=message.text)
    task_edit: dict = await state.get_data()
    try:
        edit_id: int = int(task_edit['id'])
        title: str = task_edit['title']
        body: str = task_edit['body']
        edit_task(edit_id, title, body)
        await message.answer('Запись успешно отредактирована.')

    except ValueError:
        await message.answer('id может содержать только цифры.')

    finally:
        await state.finish()


def register_handler_edit_task(dp: Dispatcher):
    dp.register_message_handler(editing_start, commands='edit', state='*')
    dp.register_message_handler(editing_title, state=StateEdit.edit_id)
    dp.register_message_handler(editing_body, state=StateEdit.edit_title)
    dp.register_message_handler(editing_task, state=StateEdit.edit_body)



In general, the question is:
1. How to pull out the id of the record with which the button worked?
2. How to pass this id to another handler?

Thank you.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mikhail Krostelev, 2021-10-26
@Arniss472

When you register a method that will launch a chain of actions for editing a post, you will pass the call parameter with the CallbackQuery type to this method. This parameter contains the data you put into the button (call.data) as well as the message object itself (call.message).
But as I understand it, you don't really need this message. You can slightly modify the get_keyboard() function

def get_keyboard(id: str):
    buttons: list = [
        types.InlineKeyboardButton(text='Редактировать', callback_data=f'edit|{id}'),
        types.InlineKeyboardButton(text='Удалить', callback_data=f'del|{id}')
    ]
    keyboard = types.InlineKeyboardMarkup(row_width=2)
    keyboard.add(*buttons)
    return keyboard

.....

async def list_tasks(message: types.Message):
    user_id: int = message.from_user.id
    lt: list = get_list_tasks(user_id)
    if len(lt) == 0:
        await message.answer('Ни одного таска ещё не создано.')
    else:
        for task in lt:
            id = task[-1] # Ну или под каким индексом тут должен скрываться ID записи? Скорректируешь
            await message.answer(f'{task[0]}\n\n{task[1]}\n\nid: {task[-1]}', reply_markup=get_keyboard(id))

now the ID of the required record is passed there and when you click on the button, you simply parse the command and the ID of the record in the database: and then I think it’s clear
command, id = call.data.split('|')

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question