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
43 changes: 43 additions & 0 deletions src/geo/clients/currency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Функции для взаимодействия с внешним сервисом-провайдером данных о курсах валют.
"""
from http import HTTPStatus
from typing import Optional

import httpx

from app.settings import REQUESTS_TIMEOUT, API_KEY_APILAYER
from base.clients.base import BaseClient


class CurrencyClient(BaseClient):
"""
Реализация функций для взаимодействия с внешним сервисом-провайдером данных о курсах валют.
"""

def get_base_url(self) -> str:
return "https://api.apilayer.com/fixer/latest"

def _request(self, endpoint: str) -> Optional[dict]:

# формирование заголовков запроса
headers = {"apikey": API_KEY_APILAYER}

with httpx.Client(timeout=REQUESTS_TIMEOUT) as client:
# получение ответа
response = client.get(endpoint, headers={'apikey': API_KEY_APILAYER})

if response.status_code == HTTPStatus.OK:
return response.json()

return None

def get_rates(self, base: str = 'rub') -> Optional[dict]:
"""
Получение данных о курсах валют.

:param base: Базовая валюта
:return:
"""

return self._request(f"{self.get_base_url()}?base={base}")
22 changes: 22 additions & 0 deletions src/geo/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,25 @@ class Meta:
"longitude",
"country",
]


class WeatherSerializer(serializers.Serializer):
"""
Сериализатор для данных о погоде.
"""

temp = serializers.FloatField()
pressure = serializers.IntegerField()
humidity = serializers.IntegerField()
wind_speed = serializers.FloatField()
description = serializers.CharField()


class CurrencySerializer(serializers.Serializer):
"""
Cериализатор для данных о курсах валют.
"""

base = serializers.CharField()
date = serializers.DateField()
rates = serializers.DictField()
29 changes: 29 additions & 0 deletions src/geo/services/currency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import Optional

from geo.clients.shemas import CountryDTO, CurrencyRatesDTO
from geo.clients.currency import CurrencyClient
from geo.models import Country


class CurrencyService:
"""
Сервис для работы с данными о курсах валют.
"""

def get_currency(self, base: str) -> Optional[CurrencyRatesDTO]:
"""
Получение списка курсов валют для базовой валюты.
:param base: Базовая валюта
:return:
"""

data = CurrencyClient().get_rates(base)

if data:
return CurrencyRatesDTO(
base=data["base"],
date=data["date"],
rates=data["rates"],
)

return None
192 changes: 191 additions & 1 deletion src/geo/services/shemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Описание моделей данных (DTO).
"""

from pydantic import Field
from pydantic import Field, BaseModel

from base.clients.shemas import HashableBaseModel

Expand All @@ -22,3 +22,193 @@ class CountryCityDTO(HashableBaseModel):

city: str
alpha2code: str = Field(min_length=2, max_length=2)


class LocationDTO(HashableBaseModel):
"""
Модель локации для получения сведений о погоде.

.. code-block::

LocationDTO(
capital="Mariehamn",
alpha2code="AX",
)
"""

capital: str
alpha2code: str = Field(min_length=2, max_length=2) # country alpha‑2 code


class CurrencyInfoDTO(HashableBaseModel):
"""
Модель данных о валюте.

.. code-block::

CurrencyInfoDTO(
code="EUR",
)
"""

code: str


class LanguagesInfoDTO(HashableBaseModel):
"""
Модель данных о языке.

.. code-block::

LanguagesInfoDTO(
name="Swedish",
native_name="svenska"
)
"""

name: str
native_name: str


class CountryDTO(BaseModel):
"""
Модель данных о стране.

.. code-block::

CountryDTO(
capital="Mariehamn",
alpha2code="AX",
alt_spellings=[
"AX",
"Aaland",
"Aland",
"Ahvenanmaa"
],
currencies={
CurrencyInfoDTO(
code="EUR",
)
},
flag="http://assets.promptapi.com/flags/AX.svg",
languages={
LanguagesInfoDTO(
name="Swedish",
native_name="svenska"
)
},
name="\u00c5land Islands",
population=28875,
subregion="Northern Europe",
timezones=[
"UTC+02:00",
],
)
"""

capital: str
alpha2code: str
alt_spellings: list[str]
currencies: set[CurrencyInfoDTO]
flag: str
languages: set[LanguagesInfoDTO]
name: str
population: int
subregion: str
timezones: list[str]


class CurrencyRatesDTO(BaseModel):
"""
Модель данных о курсах валют.

.. code-block::

CurrencyRatesDTO(
base="RUB",
date="2022-09-14",
rates={
"EUR": 0.016503,
}
)
"""

base: str
date: str
rates: dict[str, float]


class WeatherInfoDTO(BaseModel):
"""
Модель данных о погоде.

.. code-block::

WeatherInfoDTO(
temp=13.92,
pressure=1023,
humidity=54,
wind_speed=4.63,
description="scattered clouds",
)
"""

temp: float
pressure: int
humidity: int

wind_speed: float
description: str


class LocationInfoDTO(BaseModel):
"""
Модель данных для представления общей информации о месте.

.. code-block::

LocationInfoDTO(
location=CountryDTO(
capital="Mariehamn",
alpha2code="AX",
alt_spellings=[
"AX",
"Aaland",
"Aland",
"Ahvenanmaa"
],
currencies={
CurrencyInfoDTO(
code="EUR",
)
},
flag="http://assets.promptapi.com/flags/AX.svg",
languages={
LanguagesInfoDTO(
name="Swedish",
native_name="svenska"
)
},
name="\u00c5land Islands",
population=28875,
subregion="Northern Europe",
timezones=[
"UTC+02:00",
],
),
weather=WeatherInfoDTO(
temp=13.92,
pressure=1023,
humidity=54,
wind_speed=4.63,
description="scattered clouds",
),
currency_rates={
"EUR": 0.016503,
},
)
"""

location: CountryDTO
weather: WeatherInfoDTO
currency_rates: dict[str, float]
16 changes: 12 additions & 4 deletions src/geo/services/weather.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Optional

from geo.clients.shemas import CountryDTO
from geo.clients.shemas import CountryDTO, WeatherInfoDTO
from geo.clients.weather import WeatherClient
from geo.models import Country

Expand All @@ -10,7 +10,7 @@ class WeatherService:
Сервис для работы с данными о погоде.
"""

def get_weather(self, alpha2code: str, city: str) -> Optional[dict]:
def get_weather(self, alpha2code: str, city: str) -> Optional[WeatherInfoDTO]:
"""
Получение списка стран по названию.

Expand All @@ -19,8 +19,16 @@ def get_weather(self, alpha2code: str, city: str) -> Optional[dict]:
:return:
"""

if data := WeatherClient().get_weather(f"{city},{alpha2code}"):
return data
data = WeatherClient().get_weather(f"{city},{alpha2code}")

if data:
return WeatherInfoDTO(
temp=data["main"]["temp"],
pressure=data["main"]["pressure"],
humidity=data["main"]["humidity"],
wind_speed=data["wind"]["speed"],
description=data["weather"][0]["description"],
)

return None

Expand Down
3 changes: 2 additions & 1 deletion src/geo/urls.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from django.urls import path

from geo.views import get_city, get_cities, get_countries, get_country, get_weather
from geo.views import get_city, get_cities, get_countries, get_country, get_weather, get_currency

urlpatterns = [
path("city", get_cities, name="cities"),
path("city/<str:name>", get_city, name="city"),
path("country", get_countries, name="countries"),
path("country/<str:name>", get_country, name="country"),
path("weather/<str:alpha2code>/<str:city>", get_weather, name="weather"),
path("currency/<str:currency>", get_currency, name="currency"),
]
Loading