Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,68 @@

Зависимости
===========
Установите требуемое ПО:

1. Docker для контейнеризации – |link_docker|

.. |link_docker| raw:: html

<a href="https://www.docker.com" target="_blank">Docker Desktop</a>

2. Для работы с системой контроля версий – |link_git|

.. |link_git| raw:: html

<a href="https://github.com/git-guides/install-git" target="_blank">Git</a>

3. IDE для работы с исходным кодом – |link_pycharm|

.. |link_pycharm| raw:: html

<a href="https://www.jetbrains.com/ru-ru/pycharm/download" target="_blank">PyCharm</a>

Установка
=========

1. Клонируйте репозиторий проекта в свою рабочую директорию:

.. code-block:: console

git clone https://github.com/ctpemho7/python-course-favorite-places.git

Перед началом использования приложения необходимо его сконфигурировать.

.. note::

Для конфигурации выполните команды, описанные ниже, находясь в корневой директории проекта (на уровне с директорией `src`).

2. Скопируйте файл настроек `.env.sample`, создав файл `.env`:
.. code-block:: console

cp .env.sample .env

Этот файл содержит преднастроенные переменные окружения, значения которых будут общими для всего приложения.
Файл примера (`.env.sample`) содержит набор переменных со значениями по умолчанию.
Созданный файл `.env` можно настроить в зависимости от окружения.

.. warning::

Никогда не добавляйте в систему контроля версий заполненный файл `.env` для предотвращения компрометации информации о конфигурации приложения.

3. Соберите Docker-контейнер с помощью Docker Compose:
.. code-block:: console

docker compose build

Данную команду необходимо выполнять повторно в случае обновления зависимостей в файле `requirements.txt`.

4. После сборки контейнеров можно их запустить командой:
.. code-block:: console

docker compose up

Данная команда запустит собранные контейнеры для приложения и базы данных.
Когда запуск завершится, сервер начнет работать по адресу `http://0.0.0.0:8010`.


Использование
Expand All @@ -20,15 +76,153 @@

Работа с базой данных
---------------------
Для правильной работы приложения необходимо настроить базу данных (создать в ней таблицы).
Для этого нужно применить миграции внутри контейнера приложения.
Данная команда позволит зайти в контейнер приложения:

.. code-block:: console

docker compose exec favorite-places-app bash

Для применения миграций выполните команду:

.. code-block:: console

alembic upgrade head

После выполнения команды в базе данных будут созданы все нужные таблицы.



Автоматизация
=============

Проект содержит специальный файл (`Makefile`) для автоматизации выполнения команд:

1. Сборка Docker-контейнера.
2. Генерация документации.
3. Запуск форматирования кода.
4. Запуск статического анализа кода (выявление ошибок типов и форматирования кода).
5. Запуск автоматических тестов.
6. Запуск всех функций поддержки качества кода (форматирование, линтеры, автотесты).

Инструкция по запуску этих команд находится в файле `README.md`.


Тестирование
============

Для запуска автоматических тестов выполните команду:

.. code-block:: console

make test

Отчет о тестировании находится в файле `src/htmlcov/index.html`.


Документация к исходному коду
=============================

Клиенты
=======

Базовый клиент
--------------
.. automodule:: clients.base.base
:members:

Geo-клиент
----------
.. automodule:: clients.geo
:members:

Описание моделей данных
-----------------------
.. automodule:: clients.schemas
:members:


Интеграции
==========

База данных
-----------
.. automodule:: integrations.db.session
:members:

Шина событий
------------
.. automodule:: integrations.events
:members:

.. automodule:: integrations.events.schemas
:members:


Модели
======

Миксины
-------

.. automodule:: models.mixins
:members:

Модель места
------------

.. automodule:: models.places
:members:

Репозитории
===========

Базовый репозиторий
-------------------

.. automodule:: repositories.base_repository
:members:

Репозиторий для работы с местом
-------------------------------

.. automodule:: repositories.places_repository
:members:


Настройки проекта
=================
.. automodule:: settings
:members:


Схемы запросов и ответов
========================

Базовая схема
-------------
.. automodule:: schemas.base
:members:

Схемы для мест
--------------
.. automodule:: schemas.places
:members:

Схемы для маршрутов
-------------------
.. automodule:: schemas.routes
:members:


Сервисный слой
==============
.. automodule:: services.places_service
:members:


Маршруты
========
.. automodule:: transport.handlers.places
:members:
2 changes: 2 additions & 0 deletions src/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from exceptions import setup_exception_handlers
from routes import metadata_tags, setup_routes
from settings import settings
from fastapi_pagination import add_pagination


def build_app() -> FastAPI:
Expand All @@ -19,5 +20,6 @@ def build_app() -> FastAPI:

setup_routes(app)
setup_exception_handlers(app)
add_pagination(app)

return app
6 changes: 6 additions & 0 deletions src/schemas/places.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ class PlacesListResponse(ListResponse):
"""

data: list[Place]


class DescriptionRequest(BaseModel):
"""Модель для описания"""

description: str = Field(title="Описание", min_length=2, max_length=255)
41 changes: 35 additions & 6 deletions src/services/places_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,46 @@ async def update_place(self, primary_key: int, place: PlaceUpdate) -> Optional[i
:return:
"""

# при изменении координат – обогащение данных путем получения дополнительной информации от API
# todo
original_place = await self.places_repository.find(primary_key)
only_description_updated = (original_place.latitude == place.latitude
and original_place.longitude == place.longitude)

if only_description_updated:
updated_place = original_place
updated_place.description = place.description

else:
updated_place = Place(
latitude=place.latitude,
longitude=place.longitude,
description=place.description,
)
# при изменении координат – обогащение данных путем получения дополнительной информации от API
if location := await LocationClient().get_location(
latitude=place.latitude, longitude=place.longitude
):
updated_place.country = location.alpha2code
updated_place.city = location.city
updated_place.locality = location.locality

matched_rows = await self.places_repository.update_model(
primary_key, **place.dict(exclude_unset=True)
primary_key, **updated_place.dict(exclude_unset=True)
)
await self.session.commit()

# публикация события для попытки импорта информации
# по обновленному объекту любимого места в сервисе Countries Informer
# todo
try:
place_data = CountryCityDTO(
city=updated_place.city,
alpha2code=updated_place.country,
)
EventProducer().publish(
queue_name=settings.rabbitmq.queue.places_import, body=place_data.json()
)
except ValidationError:
logger.warning(
"The message was not well-formed during publishing event.",
exc_info=True,
)

return matched_rows

Expand Down
Loading