Skip to content

Commit

Permalink
Add graphql characters filter
Browse files Browse the repository at this point in the history
  • Loading branch information
koldakov committed Jan 13, 2024
1 parent 8f88335 commit 2a6438c
Showing 1 changed file with 77 additions and 0 deletions.
77 changes: 77 additions & 0 deletions app/graphql/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
Season as SeasonModel,
SeasonDoesNotExist,
)
from app.repositories.models import (
CharacterGenderFilter,
CharacterSpeciesFilter,
CharacterStatusFilter,
)
from app.repositories.sessions import get_async_session_ctx
from app.services.base import EpisodeBase as EpisodeBaseSchema
from app.services.characters import Character as CharacterSchema
Expand All @@ -26,6 +31,22 @@
)


class BaseQueryException(Exception):
...


class CharacterQueryException(BaseQueryException):
...


class LimitViolation(CharacterQueryException):
...


class OffsetViolation(CharacterQueryException):
...


@strawberry.experimental.pydantic.type(model=CharacterSchema)
class Character:
id: strawberry.auto
Expand All @@ -37,6 +58,26 @@ class Character:
image: strawberry.auto


@strawberry.type
class Characters:
limit: int
offset: int
total: int
edges: List[Character]

@classmethod
def from_params(cls, characters, limit: int, offset: int, total: int, /):
return cls(
limit=limit,
offset=offset,
total=total,
edges=[
Character.from_pydantic(CharacterSchema.model_validate(character))
for character in characters
],
)


@strawberry.experimental.pydantic.type(model=SeasonEpisodeSchema, all_fields=True)
class SeasonEpisode:
...
Expand Down Expand Up @@ -84,6 +125,42 @@ async def character(self, character_id: int) -> Character | None:
return None
return Character.from_pydantic(CharacterSchema.model_validate(character))

@strawberry.field()
async def characters(
self,
*,
limit: int | None = 50,
offset: int | None = 0,
gender: strawberry.enum(CharacterGenderFilter) | None = None,
status: strawberry.enum(CharacterStatusFilter) | None = None,
species: strawberry.enum(CharacterSpeciesFilter) | None = None,
) -> Characters:
# For some reason self does not work under strawberry decorator,
# so class attrs can't be used. Please find another way.
_min_l: int = 1
_max_l: int = 50
_min_offset: int = 0
if not _min_l <= limit <= _max_l:
raise LimitViolation(
f"Limit can be more than {_min_l} and less than {_max_l}"
) from None

async with get_async_session_ctx() as session:
total: int = await CharacterModel.count(session)
if not _min_offset <= offset <= total:
raise LimitViolation(
f"Offset can't be less than {_min_offset} more than {total}"
) from None
characters = await CharacterModel.filter(
session,
limit=limit,
offset=offset,
gender=gender,
character_status=status,
species=species,
)
return Characters.from_params(characters, limit, offset, total)

@strawberry.field()
async def episode(self, episode_id: int) -> Episode | None:
async with get_async_session_ctx() as session:
Expand Down

0 comments on commit 2a6438c

Please sign in to comment.