mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Added a section on Dependency Injection technology in documentation (#1253)
* Added a section on Dependency Injection technology in documentation * Added changelog * Edited comments & titles
This commit is contained in:
parent
068875534b
commit
f87deea4fb
3 changed files with 90 additions and 0 deletions
1
CHANGES/1253.doc.rst
Normal file
1
CHANGES/1253.doc.rst
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Added a section on Dependency Injection technology
|
||||||
56
docs/dispatcher/dependency_injection.rst
Normal file
56
docs/dispatcher/dependency_injection.rst
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
####################
|
||||||
|
Dependency injection
|
||||||
|
####################
|
||||||
|
|
||||||
|
Dependency injection is a programming technique that makes a class independent of its dependencies. It achieves that by decoupling the usage of an object from its creation. This helps you to follow `SOLID's <https://en.wikipedia.org/wiki/SOLID>`_ dependency inversion and single responsibility principles.
|
||||||
|
|
||||||
|
|
||||||
|
How it works in aiogram
|
||||||
|
=======================
|
||||||
|
For each update :class:`Dispatcher` passes handling context data. Filters and middleware can also make changes to the context.
|
||||||
|
|
||||||
|
To access contextual data you should specify corresponding keyword parameter in handler or filter. For example, to get :class:`FSMContext` we do it like that:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
@router.message(ProfileCompletion.add_photo, F.photo)
|
||||||
|
async def add_photo(
|
||||||
|
message: types.Message, bot: Bot, state: FSMContext
|
||||||
|
) -> Any:
|
||||||
|
... # do something with photo
|
||||||
|
|
||||||
|
|
||||||
|
Injecting own dependencies
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Aiogram provides several ways to complement / modify contextual data.
|
||||||
|
|
||||||
|
The first and easiest way is to simply specify the named arguments in :class:`Dispatcher` initialization, polling start methods or :class:`SimpleRequestHandler` initialization if you use webhooks.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
async def main() -> None:
|
||||||
|
dp = Dispatcher(..., foo=42)
|
||||||
|
return await dp.start_polling(
|
||||||
|
bot, allowed_updates=dp.resolve_used_update_types(), bar="Bazz"
|
||||||
|
)
|
||||||
|
Analogy for webhook:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
async def main() -> None:
|
||||||
|
dp = Dispatcher(..., foo=42)
|
||||||
|
handler = SimpleRequestHandler(dispatcher=dp, bot=bot, bar="Bazz")
|
||||||
|
... # starting webhook
|
||||||
|
:class:`Dispatcher`'s workflow data also can be supplemented by setting values as in a dictionary:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
dp = Dispatcher(...)
|
||||||
|
dp["eggs"] = Spam()
|
||||||
|
The middlewares updates the context quite often.
|
||||||
|
You can read more about them on this page:
|
||||||
|
|
||||||
|
- `Middlewares <middlewares.html>`__
|
||||||
|
|
||||||
|
The last way is to return a dictionary from the filter:
|
||||||
|
|
||||||
|
.. literalinclude:: ../../../examples/context_addition_from_filter.py
|
||||||
|
|
||||||
|
...or using MagicFilter with :code:`as_()` method. (`Read more <filters/magic_filters.html#get-filter-result-as-handler-argument>`__)
|
||||||
33
examples/context_addition_from_filter.py
Normal file
33
examples/context_addition_from_filter.py
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
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)
|
||||||
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue