Я использую Aiogram и FSM (Finite State Machine) для создания бота. У меня есть несколько полей, которые собираются последовательно (например, имя, ID, возраст). После ввода всех данных они показываются пользователю с возможностью редактирования через кнопки InlineKeyboard. Проблема возникает, когда пользователь редактирует одно поле, например, имя. После редактирования бот начинает автоматически запрашивать все остальные поля (ID, возраст) заново, хотя пользователь этого не просил.
Мне нужно, чтобы после изменения только одного поля, бот показывал обновленные данные с кнопками "Подтвердить" и "Редактировать", не запрашивая остальные поля.
Что я пробовал:
Сбрасывать состояние FSM через await state.clear() после обновления поля.
Использовать универсальную функцию для отображения итоговых данных после редактирования.
Проверил, что состояние корректно сбрасывается, но FSM все равно продолжает запрашивать следующие поля.
Код:
class Form(StatesGroup):
name = State()
user_id = State()
age = State()
@router.message(Command("start"))
async def start(message: types.Message, state: FSMContext):
await state.set_state(Form.name)
await message.answer("Введите ваше имя:")
# Обработка имени
@router.message(Form.name)
async def process_name(message: types.Message, state: FSMContext):
await state.update_data(name=message.text.strip())
await state.set_state(Form.user_id)
await message.answer("Введите ваш ID:")
# Обработка ID
@router.message(Form.user_id)
async def process_user_id(message: types.Message, state: FSMContext):
if not message.text.isdigit():
await message.answer("ID должен быть числом. Попробуйте снова.")
return
await state.update_data(user_id=message.text.strip())
await state.set_state(Form.age)
await message.answer("Введите ваш возраст:")
# Обработка возраста
@router.message(Form.age)
async def process_age(message: types.Message, state: FSMContext):
if not message.text.isdigit():
await message.answer("Возраст должен быть числом. Попробуйте снова.")
return
await state.update_data(age=message.text.strip())
await show_summary(message, state)
async def show_summary(message_or_callback: types.Message | types.CallbackQuery, state: FSMContext):
user_data = await state.get_data()
summary_message = (
f"*Ваши данные:*\n"
f"*Имя:* {user_data.get('name', 'Не указано')}\n"
f"*ID:* {user_data.get('user_id', 'Не указано')}\n"
f"*Возраст:* {user_data.get('age', 'Не указано')}\n"
)
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Изменить имя", callback_data="edit_name")],
[InlineKeyboardButton(text="Изменить ID", callback_data="edit_id")],
[InlineKeyboardButton(text="Изменить возраст", callback_data="edit_age")],
[InlineKeyboardButton(text="Подтвердить", callback_data="confirm_data")],
])
if isinstance(message_or_callback, types.CallbackQuery):
await message_or_callback.message.edit_text(summary_message, reply_markup=keyboard, parse_mode="Markdown")
else:
await message_or_callback.answer(summary_message, reply_markup=keyboard, parse_mode="Markdown")
# Обработчики редактирования данных
@router.callback_query(F.data == "edit_name")
async def edit_name(callback: types.CallbackQuery, state: FSMContext):
await state.set_state(Form.name)
await callback.message.answer("Введите новое имя:")
await callback.answer()
@router.message(Form.name)
async def process_new_name(message: types.Message, state: FSMContext):
await state.update_data(name=message.text.strip())
await state.set_state(None)
await show_summary(message, state)
@router.callback_query(F.data == "edit_id")
async def edit_id(callback: types.CallbackQuery, state: FSMContext):
await state.set_state(Form.user_id)
await callback.message.answer("Введите новый ID:")
await callback.answer()
@router.message(Form.user_id)
async def process_new_id(message: types.Message, state: FSMContext):
if not message.text.isdigit():
await message.answer("ID должен быть числом. Попробуйте снова.")
return
await state.update_data(user_id=message.text.strip())
await state.clear()
await show_summary(message, state)
@router.callback_query(F.data == "edit_age")
async def edit_age(callback: types.CallbackQuery, state: FSMContext):
await state.set_state(Form.age)
await callback.message.answer("Введите новый возраст:")
await callback.answer()
@router.message(Form.age)
async def process_new_age(message: types.Message, state: FSMContext):
if not message.text.isdigit():
await message.answer("Возраст должен быть числом. Попробуйте снова.")
return
await state.update_data(age=message.text.strip())
await state.clear() # Сбрасываем состояние, чтобы не запрашивались другие поля
await show_summary(message, state)
@router.callback_query(F.data == "confirm_data")
async def confirm_data(callback: types.CallbackQuery, state: FSMContext):
user_data = await state.get_data()
await callback.message.answer(
"Спасибо! Ваши данные подтверждены:\n"
f"*Имя:* {user_data['name']}\n"
f"*ID:* {user_data['user_id']}\n"
f"*Возраст:* {user_data['age']}",
parse_mode="Markdown"
)
await state.clear()
await callback.answer()
dp.include_router(router)
async def main():
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())