Add search service section + table of contents

This commit is contained in:
Roman Mogylatov 2020-07-20 11:06:00 -04:00
parent ee7bc163a0
commit b1b2379280

View File

@ -3,6 +3,15 @@ Flask tutorial
This tutorials shows how to build ``Flask`` application following dependency injection principle. This tutorials shows how to build ``Flask`` application following dependency injection principle.
Start from the scratch or jump to the section:
.. contents::
:local:
:backlinks: none
You can find complete project on the
`Github <https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/ghnav-flask>`_.
What are we going to build? What are we going to build?
--------------------------- ---------------------------
@ -62,7 +71,7 @@ Initial project layout::
Now it's time to install ``Flask`` and ``Dependency Injector``. Now it's time to install ``Flask`` and ``Dependency Injector``.
Put next lines to the ``requirements.txt`` file:: Put next lines into the ``requirements.txt`` file::
dependency-injector dependency-injector
flask flask
@ -91,7 +100,7 @@ Hello world!
Let's create minimal application. Let's create minimal application.
Put next to the ``views.py``: Put next into the ``views.py``:
.. code-block:: python .. code-block:: python
@ -107,7 +116,7 @@ Now let's create the heart of our application - the container. Container will ke
application components and their dependencies. First two providers we need to add are application components and their dependencies. First two providers we need to add are
the ``Flask`` application provider and the view provider. the ``Flask`` application provider and the view provider.
Put next to the ``containers.py``: Put next into the ``containers.py``:
.. code-block:: python .. code-block:: python
@ -132,7 +141,7 @@ Finally we need to create the Flask application factory. It is traditionally cal
the Flask application. Last step is to configure the routing - we will assign ``index_view`` from the the Flask application. Last step is to configure the routing - we will assign ``index_view`` from the
container to handle user requests to the root ``/`` if our web application. container to handle user requests to the root ``/`` if our web application.
Put next to the ``application.py``: Put next into the ``application.py``:
.. code-block:: python .. code-block:: python
@ -279,7 +288,7 @@ Create ``templates`` folder and put two empty files into it ``base.html`` and ``
Now let's fill in the layout. Now let's fill in the layout.
Put next to the ``base.html``: Put next into the ``base.html``:
.. code-block:: html .. code-block:: html
@ -312,7 +321,7 @@ Put next to the ``base.html``:
And put something to the index page. And put something to the index page.
Put next to the ``index.html``: Put next into the ``index.html``:
.. code-block:: html .. code-block:: html
@ -541,6 +550,123 @@ That's it.
Github API client setup is done. Github API client setup is done.
Search service
--------------
Now it's time to add ``SearchService``. It will:
- Perform the search.
- Fetch commit extra data for each result.
- Format result data
``SearchService`` will use ``Github`` API client.
Create empty file ``services.py`` in the ``githubnavigator`` package:
.. code-block::
:emphasize-lines: 9
./
├── githubnavigator/
│ ├── templates/
│ │ ├── base.html
│ │ └── index.html
│ ├── __init__.py
│ ├── application.py
│ ├── containers.py
│ ├── services.py
│ └── views.py
├── venv/
├── config.yml
└── requirements.txt
and put next into it:
.. code-block:: python
"""Services module."""
from github import Github
from github.Repository import Repository
from github.Commit import Commit
class SearchService:
"""Search service performs search on Github."""
def __init__(self, github_client: Github):
self._github_client = github_client
def search_repositories(self, term, limit):
"""Search for repositories and return formatted data."""
repositories = self._github_client.search_repositories(term, **{'in': 'name'})
return [
self._format_repo(repository)
for repository in repositories[:limit]
]
def _format_repo(self, repository: Repository):
commits = repository.get_commits()
return {
'url': repository.html_url,
'name': repository.name,
'owner': {
'login': repository.owner.login,
'url': repository.owner.html_url,
'avatar_url': repository.owner.avatar_url,
},
'latest_commit': self._format_commit(commits[0]) if commits else {},
}
def _format_commit(self, commit: Commit):
return {
'sha': commit.sha,
'url': commit.html_url,
'message': commit.commit.message,
'author_name': commit.commit.author.name,
}
Now let's add ``SearchService`` to the container.
Edit ``containers.py``:
.. code-block:: python
:emphasize-lines: 9,27-30
"""Application containers module."""
from dependency_injector import containers, providers
from dependency_injector.ext import flask
from flask import Flask
from flask_bootstrap import Bootstrap
from github import Github
from . import services, views
class ApplicationContainer(containers.DeclarativeContainer):
"""Application container."""
app = flask.Application(Flask, __name__)
bootstrap = flask.Extension(Bootstrap)
config = providers.Configuration()
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,
)
index_view = flask.View(views.index)
Tests Tests
----- -----