Погода

Проект “Погода” #

Веб-приложение для просмотра текущей погоды. Пользователь может зарегистрироваться и добавить в коллекцию один или несколько локаций (городов, сёл, других пунктов), после чего главная страница приложения начинает отображать список локаций с их текущей погодой.

Что нужно знать #

Мотивация проекта #

  • Реализация многопользовательского приложения
  • Работа с внешними API

Функционал приложения #

Работа с пользователями:

  • Регистрация
  • Авторизация
  • Logout

Работа с локациями:

  • Поиск
  • Добавление в список
  • Просмотр списка локаций, для каждой локации отображается название и температура
  • Удаление из списка

Интерфейс приложения #

Для вёрстки предлагаю пользоваться Bootstrap 5.

Главная страница #

  • Заголовок
    • Для неавторизованных пользователей - кнопки регистрации и авторизации
    • Для авторизованных пользователей - логин текущего пользователя и кнопка Logout
  • Контент
    • Поле ввода для поиска локации по названию
    • Список добавленных локаций. Каждый элемент списка отображает название, текущую температуру и кнопку “удалить”

Страница результатов поиска локаций по названию #

Переход на эту страницу осуществляется в результате заполнения поля ввода на главной странице, либо на странице результатов поиска.

Содержимое:

  • Заголовок, такой же как на главной странице
  • Поле ввода для поиска по названию - такое же, как на главной странице, чтобы не возвращаться туда для каждого нового поиска
  • Список найденных локаций с кнопкой “добавить”. При нажатии на кнопку происходит переход на главную страницу

Остальное #

  • Страницы с формами регистрации и авторизации

Работа с сессиями и cookies #

Чтобы реализовать авторизацию пользователя и позволить браузеру “запоминать” авторизован ли текущий пользователь, необходимы сессии и cookies. Подразумевается, что студент имеет общее представление об этих понятиях.

За авторизацию, управление доступом к страницам в Django отвечает django.contrib.auth.

За работу с сессиями отвечает SessionMiddleware. По умолчанию Django хранит сессии в базе данных в таблице django_session, так и сделаем. При каждом запросе Django извлекает данные сессии из базы данных по идентификатору сессии, хранящемуся в куках (cookies) запроса. После завершения запроса Django обновляет данные сессии в базе данных, если они были изменены, и обновляет срок действия сессии.

База данных #

В этом проекте предлагаю использовать Postgres, а таблицы создавать с помощью Django Migrations.

Таблица Users #

КолонкаТипКомментарий
IDintАйди пользователя, автоинкремент, первичный ключ
LoginVarcharЛогин пользователя, username или email
PasswordVarcharХранить пароль в открытом виде небезопасно, лучше использовать шифрование, например BCrypt

Таблица Locations #

Локации пользователя, в которых он хочет знать погоду. Одна и та же локация может повторяться для нескольких пользователей.

КолонкаТипКомментарий
IDintАйди локации, автоинкремент, первичный ключ
NameVarcharНазвание
UserIdintПользователь, добавивший эту локацию
LatitudeDecimalШирота локации
LongitudeDecimalДолгота локации

Получение информации о погоде с помощью OpenWeatherMap API #

В предыдущих проектах мы писали своё API, в этом будем пользоваться чужим. Нам нужно искать локации по названию и получать погоду для локации.

OpenWeather #

Существует множество сервисов, предоставляющих API с таким функционалом, один из них - https://openweathermap.org/. Я выбрал этот вариант, потому что он позволяет бесплатно совершать 60 запросов в минуту.

Для выполнения запросов к API нужен ключ, для его получения необходимо:

  • Зарегистрироваться на https://openweathermap.org/
  • Создать бесплатный ключ с лимитом 60 запросов в минуту
  • Дождаться активации ключа (

Работа с API #

Документация - https://openweathermap.org/api.

Нам нужно 2 метода API:

Первым делом следует поэкспериментировать с API вручную, чтобы понять как делать запросы, и что приходит в ответе. Сделать это можно в HTTP клиенте встроенном в Intellij IDEA, либо воспользоваться отдельным приложением, например Postman или https://insomnia.rest/.

Интеграция OpenWeather API с приложением #

Шаги:

  • Делаем запрос
  • Получаем ответ
  • Десериализуем ответ в объект

Для работы с API потребуется HTTP Client, например Requests.

С десериализацией поможет встроенный в Requests JSON decoder - https://requests.readthedocs.io/en/latest/user/quickstart/#json-response-content.

Тесты #

Интеграционные тесты сервисов по работе с пользователями и сессиями #

❗️ TODO адаптировать под Python ❗️

Покроем тестами связку слоя данных с классами-сервисами, отвечающими за пользователей и сессии.

Пример - вызов метода регистрации в классе-сервисе, отвечающем за работу с пользователями, должен привести к тому, что в таблице Users появляется новая запись. Если при регистрации автоматически создается сессия, так же можем проверить, что она была создана.

Что ещё стоит проверить тестами:

  • Регистрация юзера с неуникальным логином приводит к exception
  • Истекание сессии

Детали:

  • Для тестов должна использоваться БД, отдельная от основной (in-memory БД или независимая schema в основной БД), которая пересоздается (или очищается) перед каждым тест кейсом
  • Понадобится 2 конфигурации приложения - основная (для разработки и деплоя) и для прогона тестов. Конфигурации могут отличаться настройками доступа к БД для DjangoORM, настройками приложения (длительность сессии, например)

Интеграционные тесты для сервиса по работе с OpenWeather API #

Покроем тестами связку HTTP клиента и класса-сервиса, который пользуется этим клиентом для получения данных. Для того чтобы не делать настоящие запросы к API во время прогона тестов, следует использовать мок HTTP клиента и его ответов.

Пример - запрашиваем список локаций у сервиса, мок HTTP клиента возвращает заданный в тесте ответ (в виде строки, например), сервис его парсит и возвращает коллекцию объектов-моделей. Проверяем, что коллеция содержит ожидаемую локацию.

Что ещё стоит проверить тестами:

  • В случай ошибки (статусы 4xx, 5xx) от OpenWeather API сервис выбрасывает ожидаемый тип исключения

Деплой #

Будем вручную деплоить приложение на удалённый сервер. Потребуется установка внешней SQL DB - Postgres.

Шаги:

  • В хостинг-провайдере по выбору арендовать облачный сервер на Linux
  • Установить Python, Postgres
  • Скопировать код приложения
  • Установить зависимости
  • Запустить приложение

Ожидаемый результат - приложение доступно по адресу http://$server_ip:$port/$app_root_path.

План работы над приложением #

  • Создать заготовку Django приложения
  • Написать модели сущностей БД - User, Location
  • Реализовать работу с сессиями
  • С помощью Jinja2 создать страницы авторизации и регистрации
  • Написать сервис для работы с OpenWeather API
  • Интеграционные тесты для OpenWeather API
  • Реализовать бизнес логику приложения - поиск, добавление, удаление локаций, просмотр погоды
  • Создать интерфейс главной страницы и страницы поиска локаций
  • Деплой

Ресурсы для работы над ошибками #