Skip to content

Lab 7 #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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
2 changes: 1 addition & 1 deletion src/clients/countries.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def get_list_by_codes(self, alpha2codes: set[str]) -> Optional[list[CountryModel
currencies=country.get("currencies"),
languages=country.get("languages"),
)
for country in response
for country in response.get("results", [])
]

return None
29 changes: 25 additions & 4 deletions src/clients/places.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from urllib.parse import urlencode, urljoin

from src.clients.base.base import BaseClient
from src.models.places import PlaceModel
from src.models.places import PlaceModel, UpdatePlaceModel
from src.settings import settings


Expand Down Expand Up @@ -33,20 +33,23 @@ def get_place(self, place_id: int) -> Optional[PlaceModel]:

return None

def get_list(self) -> Optional[list[PlaceModel]]:
def get_list(self, page: int, size: int) -> Optional[list[PlaceModel]]:
"""
Получение списка любимых мест.
TODO: добавить пагинацию.
:param page: Номер страницы.
:param size: Количество объектов на странице.
:return:
"""

endpoint = "/api/v1/places"
query_params = {
"limit": 20,
"page": page,
"size": size,
}
url = urljoin(self.base_url, f"{endpoint}?{urlencode(query_params)}")
if response := self._request(self.GET, url):
return [self.__build_model(place) for place in response.get("data", [])]
return [self.__build_model(place) for place in response.get("items", [])]

return None

Expand All @@ -66,6 +69,24 @@ def create_place(self, place: PlaceModel) -> Optional[PlaceModel]:

return None

def update_place(
self, place_id: int, place: UpdatePlaceModel
) -> tuple[bool, PlaceModel | None]:
"""
Обновление объекта любимого места по его идентификатору.
:param place_id: Идентификатор объекта.
:param place: Объект любимого места для обновления.
:return:
"""

endpoint = f"/api/v1/places/{place_id}"
url = urljoin(self.base_url, endpoint)
if response := self._request(self.PATCH, url, body=place.dict()):
if place_data := response.get("data"):
return True, self.__build_model(place_data)

return False, None

def delete_place(self, place_id: int) -> bool:
"""
Удаление объекта любимого места по его идентификатору.
Expand Down
10 changes: 10 additions & 0 deletions src/models/places.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ class PlaceModel(TimeStampMixin, BaseModel):
country: Optional[str] = Field(title="ISO Alpha2-код страны")
city: Optional[str] = Field(title="Название города")
locality: Optional[str] = Field(title="Местонахождение")


class UpdatePlaceModel(TimeStampMixin, BaseModel):
"""
Модель для обновления места.
"""

latitude: float | None = Field(title="Широта")
longitude: float | None = Field(title="Долгота")
description: str | None = Field(title="Описание")
38 changes: 37 additions & 1 deletion src/schema/mutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import graphene
from graphql import ResolveInfo

from src.models.places import PlaceModel
from src.models.places import PlaceModel, UpdatePlaceModel
from src.schema.query import Place
from src.services.places import PlacesService

Expand Down Expand Up @@ -48,6 +48,42 @@ def mutate(
return CreatePlace(place=place, result=bool(place))


class UpdatePlace(graphene.Mutation):
"""
Функции для обновления объекта любимого места.
"""

class Arguments:
place_id = graphene.Int()
latitude = graphene.Float()
longitude = graphene.Float()
description = graphene.String()

result = graphene.Boolean()
place = graphene.Field(Place)

@staticmethod
def mutate(parent: Optional[dict], info: ResolveInfo, place_id: int, latitude: float | None = None, longitude: float | None = None, description: str | None = None) -> "UpdatePlace":
"""
Обработка запроса для обновления объекта по его идентификатору.
:param parent: Информация о родительском объекте (при наличии).
:param info: Объект с метаинформацией и данных о контексте запроса.
:param place_id: Идентификатор объекта для обновления.
:param latitude: Широта.
:param longitude: Долгота.
:param description: Описание.
:return:
"""

# получение результата обновления объекта
model = UpdatePlaceModel(
latitude=latitude, longitude=longitude, description=description
)
result, place = PlacesService().update_place(place_id, model)

return UpdatePlace(result=result, place=place)


class DeletePlace(graphene.Mutation):
"""
Функции для удаления объекта любимого места.
Expand Down
12 changes: 9 additions & 3 deletions src/schema/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,26 +69,32 @@ class Query(graphene.ObjectType):
"""

#: запрос для получения списка объектов любимых мест
places = graphene.List(Place)
places = graphene.List(Place, page=graphene.Int(), size=graphene.Int())

#: запрос для получения конкретного объекта любимого места по идентификатору
place = Field(Place, place_id=ID(required=True))

@staticmethod
def resolve_places(
parent: Optional[dict], info: ResolveInfo
parent: Optional[dict], info: ResolveInfo, page: int | None = None, size: int | None = None,
) -> Optional[list[PlaceModel]]:
"""
Получение списка объектов любимых мест.

:param parent: Объект любимого места.
:param info: Объект с метаинформацией и данных о контексте запроса.
:param page: Номер страницы.
:param size: Количество объектов на странице.
:return:
"""

# pylint: disable=unused-argument

return PlacesService().get_places()
if page is None:
page = 1
if size is None:
size = 20
return PlacesService().get_places(page=page, size=size)

@staticmethod
def resolve_place(
Expand Down
9 changes: 6 additions & 3 deletions src/services/places.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Optional

from src.clients.places import PlacesClient
from src.models.places import PlaceModel
from src.models.places import PlaceModel, UpdatePlaceModel


class PlacesService:
Expand All @@ -18,14 +18,14 @@ def get_place(self, place_id: int) -> Optional[PlaceModel]:

return PlacesClient().get_place(place_id)

def get_places(self) -> Optional[list[PlaceModel]]:
def get_places(self, page: int, size: int) -> Optional[list[PlaceModel]]:
"""
Получение списка любимых мест.

:return:
"""

return PlacesClient().get_list()
return PlacesClient().get_list(page=page, size=size)

def create_place(self, place: PlaceModel) -> Optional[PlaceModel]:
"""
Expand All @@ -37,6 +37,9 @@ def create_place(self, place: PlaceModel) -> Optional[PlaceModel]:

return PlacesClient().create_place(place)

def update_place(self, place_id: int, model: UpdatePlaceModel) -> tuple[bool, PlaceModel | None]:
return PlacesClient().update_place(place_id, model)

def delete_place(self, place_id: int) -> bool:
"""
Удаление объекта любимого места по его идентификатору.
Expand Down