Flask example — Dependency Injector 4.46.0 documentation (original) (raw)
This example shows how to use Dependency Injector
with Flask.
The example application helps to search for repositories on the Github.
The source code is available on the Github.
Flask tutorial demonstrates how to build this application step-by-step.
Application structure¶
Application has next structure:
./ ├── githubnavigator/ │ ├── templates │ │ ├── base.html │ │ └── index.py │ ├── init.py │ ├── application.py │ ├── containers.py │ ├── services.py │ ├── tests.py │ └── views.py ├── config.yml └── requirements.txt
Container¶
Declarative container is defined in githubnavigator/containers.py
:
"""Containers module."""
from dependency_injector import containers, providers from github import Github
from . import services
class Container(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(modules=[".views"])
config = providers.Configuration(yaml_files=["config.yml"])
github_client = providers.Factory(
Github,
login_or_token=config.github.auth_token,
timeout=config.github.request_timeout,
)
search_service = providers.Factory(
services.SearchService,
github_client=github_client,
)
Views¶
View has dependencies on search service and some config options. The dependencies are injected using Wiring feature.
Listing of githubnavigator/views.py
:
"""Views module."""
from flask import request, render_template from dependency_injector.wiring import inject, Provide
from .services import SearchService from .containers import Container
@inject def index( search_service: SearchService = Provide[Container.search_service], default_query: str = Provide[Container.config.default.query], default_limit: int = Provide[Container.config.default.limit.as_int()], ): query = request.args.get("query", default_query) limit = request.args.get("limit", default_limit, int)
repositories = search_service.search_repositories(query, limit)
return render_template(
"index.html",
query=query,
limit=limit,
repositories=repositories,
)
Application factory¶
Application factory creates container, wires it with the views
module, createsFlask
app and setup routes.
Listing of githubnavigator/application.py
:
"""Application module."""
from flask import Flask from flask_bootstrap import Bootstrap4
from .containers import Container from . import views
def create_app() -> Flask: container = Container() container.config.github.auth_token.from_env("GITHUB_TOKEN")
app = Flask(__name__)
app.container = container
app.add_url_rule("/", "index", views.index)
bootstrap = Bootstrap4()
bootstrap.init_app(app)
return app
Tests¶
Tests use Provider overriding feature to replace github client with a mock githubnavigator/tests.py
:
"""Tests module."""
from unittest import mock
import pytest from github import Github from flask import url_for
from .application import create_app
@pytest.fixture def app(): app = create_app() yield app app.container.unwire()
def test_index(client, app): github_client_mock = mock.Mock(spec=Github) github_client_mock.search_repositories.return_value = [ mock.Mock( html_url="repo1-url", name="repo1-name", owner=mock.Mock( login="owner1-login", html_url="owner1-url", avatar_url="owner1-avatar-url", ), get_commits=mock.Mock(return_value=[mock.Mock()]), ), mock.Mock( html_url="repo2-url", name="repo2-name", owner=mock.Mock( login="owner2-login", html_url="owner2-url", avatar_url="owner2-avatar-url", ), get_commits=mock.Mock(return_value=[mock.Mock()]), ), ]
with app.container.github_client.override(github_client_mock):
response = client.get(url_for("index"))
assert response.status_code == 200
assert b"Results found: 2" in response.data
assert b"repo1-url" in response.data
assert b"repo1-name" in response.data
assert b"owner1-login" in response.data
assert b"owner1-url" in response.data
assert b"owner1-avatar-url" in response.data
assert b"repo2-url" in response.data
assert b"repo2-name" in response.data
assert b"owner2-login" in response.data
assert b"owner2-url" in response.data
assert b"owner2-avatar-url" in response.data
def test_index_no_results(client, app): github_client_mock = mock.Mock(spec=Github) github_client_mock.search_repositories.return_value = []
with app.container.github_client.override(github_client_mock):
response = client.get(url_for("index"))
assert response.status_code == 200
assert b"Results found: 0" in response.data
Sources¶
Explore the sources on the Github.
Sponsor the project on GitHub: |
---|