Данные и контекст¶
Данные, необходимые для рендеринга текста, клавиатур и медиа в окне, берутся из словаря (контекста).
Геттеры (Getters)¶
Геттер - это функция, возвращающая словарь с данными для шаблонов и форматов. Геттер можно повесить как на всё окно (Window), так и на весь диалог (Dialog). Словари объединяются.
Геттер на окно¶
from maxo.dialogs import Window
from maxo.dialogs.widgets.text import Format
from maxo.fsm import State, StatesGroup
class SG(StatesGroup):
main = State()
async def get_user_data(**kwargs):
return {"name": "Иван", "balance": 100}
Window(
Format("Пользователь {name}, баланс: {balance}"),
state=SG.main,
getter=get_user_data,
)
Геттер на диалог¶
Если один и тот же набор данных нужен во всех окнах диалога, удобнее повесить геттер на весь Dialog. Он будет вызван для каждого окна, а его результат объединится со словарём локального геттера окна.
from maxo.dialogs import Dialog, Window
from maxo.dialogs.widgets.text import Const, Format
from maxo.fsm import State, StatesGroup
class SG(StatesGroup):
main = State()
details = State()
async def common_getter(**kwargs):
"""Общий геттер - данные доступны во всех окнах."""
return {"app_name": "МойБот", "version": "1.0"}
async def details_getter(**kwargs):
"""Локальный геттер - только для окна details."""
return {"info": "Подробная информация"}
dialog = Dialog(
Window(
Format("{app_name} v{version}"),
Const("Главное окно"),
state=SG.main,
),
Window(
Format("{app_name}: {info}"),
state=SG.details,
getter=details_getter, # локальный геттер
),
getter=common_getter, # общий геттер для всех окон
)
Данные из Middleware¶
Геттеры поддерживают Dependency Injection (как и обычные хэндлеры maxo). Данные из мидлварей автоматически доступны в геттерах.
Например, если у вас есть мидлварь, которая по каждому событию достаёт из базы объект текущего пользователя:
from typing import Any
from maxo.routing.ctx import Ctx
from maxo.routing.interfaces.middleware import BaseMiddleware, NextMiddleware
from maxo.routing.updates import MessageCreated
class UserMiddleware(BaseMiddleware[MessageCreated]):
async def __call__(
self,
update: MessageCreated,
ctx: Ctx,
next: NextMiddleware[MessageCreated],
) -> Any:
user = await get_user_from_db(update.message.unsafe_sender.user_id)
ctx["user"] = user # кладём в контекст
return await next(ctx)
То в геттере вы можете принять user через аргумент:
async def get_user_data(user: User, **kwargs):
# user подставляется из мидлвари автоматически
return {"name": user.full_name, "balance": user.balance}
См. также
Подробнее о создании и регистрации мидлварей: Мидлвари.
DialogData и StartData¶
Помимо геттеров, у DialogManager есть доступ к состоянию диалога через два ключевых словаря.
start_data - данные между диалогами¶
start_data - это неизменяемые данные, переданные при запуске диалога через manager.start(state, data={...}). Используются для передачи начальных параметров из одного диалога в другой (или из хэндлера в диалог).
Пример 1: Запуск диалога из хэндлера с данными
from maxo.dialogs import DialogManager
from maxo.routing.filters import Command
from maxo.routing.updates import MessageCreated
@router.message_created(Command("profile"))
async def show_profile(message: MessageCreated, dialog_manager: DialogManager):
await dialog_manager.start(
ProfileSG.main,
data={"user_id": message.message.sender.user_id},
)
Пример 2: Чтение start_data в геттере
from maxo.dialogs import DialogManager
async def profile_getter(dialog_manager: DialogManager, **kwargs):
user_id = dialog_manager.start_data["user_id"]
user = await get_user_from_db(user_id)
return {"name": user.name, "age": user.age}
Пример 3: Запуск вложенного диалога с данными
from maxo.dialogs import DialogManager
from maxo.dialogs.widgets.kbd import Button
from maxo.routing.updates import MessageCallback
async def on_edit_click(
callback: MessageCallback,
button: Button,
dialog_manager: DialogManager,
) -> None:
# Передаём данные из текущего диалога в дочерний
await dialog_manager.start(
EditSG.main,
data={"item_id": dialog_manager.dialog_data["selected_item"]},
)
dialog_data - данные между окнами¶
dialog_data - это мутируемый словарь для хранения промежуточных данных внутри одного диалога, между переходами окон. Аналог FSM-хранилища, но привязан к конкретному диалогу.
from maxo.dialogs import DialogManager
from maxo.dialogs.widgets.input import MessageInput
from maxo.routing.updates import MessageCreated
async def on_name_input(message: MessageCreated, widget: MessageInput, manager: DialogManager):
manager.dialog_data["name"] = message.message.body.text
await manager.next()
async def on_age_input(message: MessageCreated, widget: MessageInput, manager: DialogManager):
manager.dialog_data["age"] = message.message.body.text
await manager.next()
async def summary_getter(dialog_manager: DialogManager, **kwargs):
return {
"name": dialog_manager.dialog_data.get("name", "-"),
"age": dialog_manager.dialog_data.get("age", "-"),
}
Важно
Главное отличие:
start_data- передаётся извне при запуске и не изменяется. Для связи между диалогами.dialog_data- создаётся внутри диалога и свободно мутируется. Для связи между окнами одного диалога.