Как в Aiogram 3 сохранить свое значение в состоянии (state) FSM или получить callback и записать его в состояние?

Как получить callback и сохранить его в состоянии aiogram 3.x? Вместо этого я решил поступить примитивным способом, так как есть всего 4 варианта, и обрабатываю каждый из них. Но после этого мне необходимо сохранить полученную категорию, чтобы потом использовать ее в следующей функции для расчета стоимости.
  • 6 октября 2023 г. 10:37
Ответы на вопрос 2
В Aiogram 3.x для сохранения своего значения в состоянии FSM можно использовать метод `context.get()` для получения значения из контекста сообщения и метод `context.set()` для сохранения значения в контексте соответствующего состояния.

Пример использования:

```python
from aiogram import types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Command

from aiogram import Bot, Dispatcher
from aiogram.contrib.fsm_storage.memory import MemoryStorage

from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup

from aiogram import types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Command

from typing import List
import logging
import json

from aiogram import types
from aiogram.dispatcher import FSMContext

bot = Bot(token="TOKEN")
dp = Dispatcher(bot, storage=MemoryStorage())

class OrderStates(StatesGroup):
    CATEGORY = State()

@dp.message_handler(Command("start"))
async def cmd_start(message: types.Message):
    await message.reply("Выберите категорию:", reply_markup=types.ReplyKeyboardMarkup(
        keyboard=[
            [
                types.KeyboardButton(text="Категория 1")
            ],
            [
                types.KeyboardButton(text="Категория 2")
            ],
            [
                types.KeyboardButton(text="Категория 3")
            ]
        ], resize_keyboard=True))

    await OrderStates.CATEGORY.set()

@dp.message_handler(content_types=["text"], state=OrderStates.CATEGORY)
async def process_category(message: types.Message, state: FSMContext):
    # Получение значения callback_data
    category = message.text

    # Сохранение значения в состоянии FSM
    await state.update_data(category=category)

    # Пример расчета стоимости на основе полученной категории
    # ...
    # Отправка сообщения с результатом расчета
    await message.reply(f"Стоимость для категории '{category}' равна 100")

    # Переход к следующему состоянию
    await state.finish()

if __name__ == '__main__':
    from aiogram import executor
    executor.start_polling(dp, skip_updates=True)
```

В данном примере при выборе категории пользователем, значение сохраняется в состоянии `CATEGORY` с помощью метода `state.update_data()`. Затем можно использовать это значение в следующей функции для расчета стоимости или для других нужд.

Обратите внимание, что в данном примере используется модуль `aiogram.contrib.fsm_storage.memory.MemoryStorage` для хранения состояний FSM в оперативной памяти. Более продвинутые варианты хранения состояний, такие как RedisStorage, также могут быть использованы вместо этого.
Уберите глобальную переменную `choosed_category` и прокиньте нужные данные в объект `state` в функции `ss`:

```python
@router.callback_query(F.data == 'shirt_shorts')
async def ss(callback: CallbackQuery, state: FSMContext):
    await state.set_data({"choosed_category": shirt_shorts})
    await callback.answer()
    await callback.message.answer('Ты выбрал(а) категорию Футболка / Шорты \n' + txt.calculation)
    await state.set_state(CalculateCost.choosing_cost)
```

```python
@router.message(CalculateCost.choosing_cost)
async def calculate(message: Message, state: FSMContext):
    state_data = await state.get_data()
    choosed_category = state_data["choosed_category]
    # остальной код функции
```

По хорошему, все 4 функции с обработкой колбеков можно сократить в одну, но это уже не тема вопроса.
Похожие вопросы