Ін’єкція залежностей¶
Ін’єкція залежностей — це техніка програмування, яка робить класи незалежними від їхніх залежностей. Вона досягається шляхом відділення використання об’єкта від його створення. Це допомагає дотримуватися принципів інверсії залежностей та єдиної відповідальності за SOLID.
Як це працює в aiogram¶
Для кожного оновлення aiogram.dispatcher.dispatcher.Dispatcher
передає дані контексту обробки. Фільтри та проміжне програмне забезпечення також можуть вносити зміни до контексту.
Щоб отримати доступ до контекстних даних, ви повинні вказати відповідний параметр ключового слова в обробнику або фільтрі. Наприклад, щоб отримати aiogram.fsm.context.FSMContext
, ми робимо це так:
@router.message(ProfileCompletion.add_photo, F.photo)
async def add_photo(
message: types.Message, bot: Bot, state: FSMContext
) -> Any:
... # do something with photo
Ін’єкція власних залежностей¶
Aiogram надає кілька способів для доповнення/модифікації контекстних даних.
Перший і найпростіший спосіб — це просто вказати іменовані аргументи під час ініціалізації aiogram.dispatcher.dispatcher.Dispatcher
, запуску методів опитування або ініціалізації aiogram.webhook.aiohttp_server.SimpleRequestHandler
, якщо ви використовуєте вебхуки.
async def main() -> None:
dp = Dispatcher(..., foo=42)
return await dp.start_polling(
bot, bar="Bazz"
)
Аналогія для вебхука:
async def main() -> None:
dp = Dispatcher(..., foo=42)
handler = SimpleRequestHandler(dispatcher=dp, bot=bot, bar="Bazz")
... # starting webhook
Дані робочого процесу aiogram.dispatcher.dispatcher.Dispatcher
також можуть доповнюватися шляхом встановлення значень, як у словнику:
dp = Dispatcher(...)
dp["eggs"] = Spam()
Проміжне програмне забезпечення досить часто оновлює контекст. Ви можете прочитати про це більше на цій сторінці:
Останній спосіб — повернути словник із фільтра:
from typing import Any, Dict, Optional, Union
from aiogram import Router
from aiogram.filters import Filter
from aiogram.types import Message, User
router = Router(name=__name__)
class HelloFilter(Filter):
def __init__(self, name: Optional[str] = None) -> None:
self.name = name
async def __call__(
self,
message: Message,
event_from_user: User,
# Filters also can accept keyword parameters like in handlers
) -> Union[bool, Dict[str, Any]]:
if message.text.casefold() == "hello":
# Returning a dictionary that will update the context data
return {"name": event_from_user.mention_html(name=self.name)}
return False
@router.message(HelloFilter())
async def my_handler(
message: Message, name: str # Now we can accept "name" as named parameter
) -> Any:
return message.answer("Hello, {name}!".format(name=name))
…або використовуючи MagicFilter з методом .as_(...)
.
Використання підказок типів¶
Примітка
Використання підказок типів для даних проміжного програмного забезпечення необов’язкове й не потрібне для правильної роботи диспетчера. Проте рекомендується використовувати їх для покращення читабельності коду.
Ви можете використовувати підказки типів для визначення типу контекстних даних у проміжному ПЗ, фільтрах та обробниках.
Словник типів даних за замовчуванням для проміжного ПЗ можна знайти в aiogram.dispatcher.middlewares.data.MiddlewareData
.
Якщо ви розширили контекстні дані, ви можете використовувати aiogram.dispatcher.middlewares.data.MiddlewareData
як базовий клас та вказати підказки типів для нових полів.
Попередження
Якщо ви використовуєте інструменти перевірки типів, такі як mypy, ви можете отримати попередження про те, що ці підказки типів порушують принцип підстановки Лісков через те, що суворіший тип не є підкласом dict[str, Any]
. Це відома проблема, і це не є помилкою. Ви можете проігнорувати це попередження або використати коментар # type: ignore
.
Приклад використання підказок типів:
from aiogram.dispatcher.middlewares.data import MiddlewareData
class MyMiddlewareData(MiddlewareData, total=False):
my_custom_value: int
class MyMessageMiddleware(BaseMiddleware):
async def __call__(
self,
handler: Callable[[Message, MyMiddlewareData], Awaitable[Any]],
event: Message,
data: MyMiddlewareData,
) -> Any:
bot = data["bot"] # <-- IDE will show you that data has `bot` key and its type is `Bot`
data["my_custom_value"] = bot.id * 42 # <-- IDE will show you that you can set `my_custom_value` key with int value and warn you if you try to set it with other type
return await handler(event, data)
Доступні помічники для типів контекстних даних¶
- class aiogram.dispatcher.middlewares.data.MiddlewareData[source]¶
Дані, передані обробнику проміжним ПЗ.
Ви можете додати власні дані, розширивши цей клас.
- dispatcher: Dispatcher¶
- bot: Bot¶
- bots: NotRequired[list[Bot]]¶
- handler: NotRequired[HandlerObject]¶
- event_context: EventContext¶
- event_thread_id: NotRequired[int]¶
- event_business_connection_id: NotRequired[str]¶
- fsm_storage: BaseStorage¶
- state: NotRequired[FSMContext]¶
- raw_state: NotRequired[str | None]¶
- class aiogram.dispatcher.middlewares.data.I18nData[source]¶
Дані, пов’язані з I18n.
За замовчуванням не включено, вам потрібно додати це до власного класу Даних, якщо це необхідно.
- i18n: I18n¶
Об’єкт I18n.
- i18n_middleware: I18nMiddleware¶
Проміжне ПЗ для I18n.