18.11.2020       Выпуск 361 (16.11.2020 - 22.11.2020)       Статьи

FastAPI + Dependency Injector

Статья о интеграции FastAPI и Dependency Injector. Пример использования и тестирования.

Читать>>




Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

Просим обратить внимание, что текст по ссылке и здесь может не совпадать.

Привет,

Я выпустил новую версию

Dependency Injector

4.4. Она позволяет использовать Dependency Injector вместе с

FastAPI

. В этом посте покажу как это работает.

Основная задача интеграции: подружить директиву

Depends

FastAPI c маркерами

Provide

и

Provider

Dependency Injector'a.

Из коробки до версии DI 4.4 это не работало. FastAPI использует типизацию и Pydantic для валидации входных параметров и ответа. Маркеры Dependency Injector'а приводили его в недоумение.

Решение пришло после изучения внутренностей FastAPI. Пришлось сделать нескольких изменений в модуле связывания (wiring) Dependency Injector'а. Директива

Depends

теперь работает вместе с маркерами

Provide

и

Provider

.

Пример

Создайте файл

fastapi_di_example.py

и поместите в него следующие строки:

import sys

from fastapi import FastAPI, Depends
from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide


class Service:
    async def process(self) -> str:
        return 'Ok'


class Container(containers.DeclarativeContainer):

    service = providers.Factory(Service)


app = FastAPI()


@app.api_route('/')
@inject
async def index(service: Service = Depends(Provide[Container.service])):
    result = await service.process()
    return {'result': result}


container = Container()
container.wire(modules=[sys.modules[__name__]])

Для того чтобы запустить пример установите зависимости:

pip install fastapi dependency-injector uvicorn

и запустите

uvicorn

:

uvicorn fastapi_di_example:app --reload

В терминале должно будет появится что-то вроде:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [11910] using watchgod
INFO:     Started server process [11912]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

а

http://127.0.0.1:8000

должен возвращать:

{
    "result": "Ok"
}

Как тестировать?

Создайте рядом файл

tests.py

и поместите в него следующие строки:

from unittest import mock

import pytest
from httpx import AsyncClient

from fastapi_di_example import app, container, Service


@pytest.fixture
def client(event_loop):
    client = AsyncClient(app=app, base_url='http://test')
    yield client
    event_loop.run_until_complete(client.aclose())


@pytest.mark.asyncio
async def test_index(client):
    service_mock = mock.AsyncMock(spec=Service)
    service_mock.process.return_value = 'Foo'

    with container.service.override(service_mock):
        response = await client.get('/')

    assert response.status_code == 200
    assert response.json() == {'result': 'Foo'}

Для того чтобы запустить тесты установите зависимости:

pip install pytest pytest-asyncio httpx

и запустите

pytest

:

pytest tests.py

В терминале должно будет появится:

======= test session starts =======
platform darwin -- Python 3.8.3, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: ...
plugins: asyncio-0.14.0
collected 1 item

tests.py .                                                      [100%]

======= 1 passed in 0.17s =======

Что дает интеграция?

FastAPI — классный фреймворк для построения API. В него встроен базовый механизм dependency injection.

Эта интеграция улучшает работу dependency injection в FastAPI. Она позволяет использовать в нём провайдеры, переопредение, конфиг и ресурсы Dependency Injector'а.

Что дальше?






Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus