Starlette¶
Warning
- The integration has been moved to the starlette-dishka package and will be removed in future versions.
pip install starlette-dishka
Though it is not required, you can use dishka-starlette integration. It features:
automatic REQUEST and SESSION scope management using middleware
passing
Requestobject as a context data to providers for both Websockets and HTTP requestsautomatic injection of dependencies into handler function.
How to use¶
Import
from dishka.integrations.starlette import (
FromDishka,
StarletteProvider,
inject,
setup_dishka,
)
from dishka import make_async_container, Provider, provide, Scope
Create provider. You can use
starlette.requests.Requestas a factory parameter to access on REQUEST-scope, andstarlette.websockets.WebSocketon SESSION-scope
class YourProvider(Provider):
@provide(scope=Scope.REQUEST)
def create_x(self, request: Request) -> X:
...
Mark those of your handlers parameters which are to be injected with
FromDishka[]and decorate them using@inject
@inject
async def endpoint(
request: Request,
*,
gateway: FromDishka[Gateway],
) -> ResponseModel:
...
(optional) Use
StarletteProvider()when creating container if you are going to usestarlette.Requestorstarlette.WebSocketin providers
container = make_async_container(YourProvider(), StarletteProvider())
Setup
dishkaintegration.
setup_dishka(container=container, app=app)
Websockets¶
For most cases we operate single events like HTTP-requests. In this case we operate only 2 scopes: APP and REQUEST.
Websockets are different: for one application you have multiple connections (one per client) and each connection delivers multiple messages.
To support this we use additional scope: SESSION:
APP→SESSION→REQUEST
In starlette your view function is called once per connection and then you retrieve messages in loop.
So, inject decorator can be only used to retrieve SESSION-scoped objects.
To achieve REQUEST-scope you can enter in manually:
@inject
async def get_with_request(
websocket: WebSocket,
a: FromDishka[A], # object with Scope.SESSION
container: FromDishka[AsyncContainer], # container for Scope.SESSION
) -> None:
await websocket.accept()
while True:
data = await websocket.receive_text()
# enter the nested scope, which is Scope.REQUEST
async with container() as request_container:
b = await request_container.get(B) # object with Scope.REQUEST