diff --git a/app/graphql/schemas.py b/app/graphql/schemas.py index 14a0289..a607d4f 100644 --- a/app/graphql/schemas.py +++ b/app/graphql/schemas.py @@ -1,8 +1,5 @@ -from datetime import date, datetime -from typing import List, Optional -from uuid import UUID +from typing import List -from fastapi_storages.base import StorageImage import strawberry from app.repositories.models import ( @@ -17,75 +14,66 @@ SeasonDoesNotExist, ) from app.repositories.sessions import get_async_session_ctx -from app.services.characters import build_url - - -_Status = strawberry.enum(CharacterStatus) -_Gender = strawberry.enum(CharacterGender) -_Species = strawberry.enum(CharacterSpecies) - - -@strawberry.type -class CharacterResponse: - id: int - name: str - status: _Status - created_at: datetime - gender: _Gender - species: _Species - uuid: UUID - image: Optional[str] - +from app.services.base import EpisodeBase as EpisodeBaseSchema +from app.services.characters import Character as CharacterSchema +from app.services.episodes import ( + Episode as EpisodeSchema, + SeasonEpisode as SeasonEpisodeSchema, +) +from app.services.seasons import ( + Season as SeasonSchema, + EpisodeSeason as EpisodeSeasonSchema, +) -@strawberry.type -class SeasonBase: - id: int - created_at: datetime - uuid: UUID +@strawberry.experimental.pydantic.type(model=CharacterSchema) +class Character: + id: strawberry.auto + name: strawberry.auto + gender: strawberry.enum(CharacterGender) + status: strawberry.enum(CharacterStatus) + species: strawberry.enum(CharacterSpecies) + created_at: strawberry.auto + image: strawberry.auto -@strawberry.type -class EpisodeSeason(SeasonBase): - """Season model for episode response. - We don't need to return episodes in season on episode request. - """ +@strawberry.experimental.pydantic.type(model=SeasonEpisodeSchema, all_fields=True) +class SeasonEpisode: + ... -@strawberry.type +@strawberry.experimental.pydantic.type(model=EpisodeBaseSchema, all_fields=True) class EpisodeBase: - id: int - name: str - created_at: datetime - uuid: UUID - air_date: Optional[date] - duration: Optional[int] - production_code: str - broadcast_number: int + ... -@strawberry.type -class EpisodeResponse(EpisodeBase): - season: EpisodeSeason +@strawberry.experimental.pydantic.type(model=EpisodeSchema) +class Episode(EpisodeBase): + air_date: strawberry.auto + duration: strawberry.auto + created_at: strawberry.auto + season: SeasonEpisode + broadcast_code: str -@strawberry.type -class SeasonEpisode(EpisodeBase): - """Episode model for season response. +@strawberry.experimental.pydantic.type(model=EpisodeSeasonSchema) +class EpisodeSeason(EpisodeBase): + id: strawberry.auto + name: strawberry.auto + broadcast_number: strawberry.auto + production_code: strawberry.auto - We don't need to return season in episode on season request. - """ - -@strawberry.type -class SeasonResponse(SeasonBase): - episodes: List[SeasonEpisode] +@strawberry.experimental.pydantic.type(model=SeasonSchema) +class Season: + id: strawberry.auto + episodes: List[EpisodeSeason] @strawberry.type class Query: - @strawberry.field - async def character(self, character_id: int) -> Optional[CharacterResponse]: + @strawberry.field() + async def character(self, character_id: int) -> Character | None: async with get_async_session_ctx() as session: try: character: CharacterModel = await CharacterModel.get( @@ -94,27 +82,25 @@ async def character(self, character_id: int) -> Optional[CharacterResponse]: ) except CharacterDoesNotExist: return None - data: dict = character.to_dict() - image: StorageImage = data.pop("image") - return CharacterResponse( - **data, - image=build_url(path=image._name), # noqa - ) - - @strawberry.field - async def episode(self, episode_id: int) -> Optional[EpisodeResponse]: + return Character.from_pydantic(CharacterSchema.model_validate(character)) + + @strawberry.field() + async def episode(self, episode_id: int) -> Episode | None: async with get_async_session_ctx() as session: try: - episode: EpisodeModel = await EpisodeModel.get(session, episode_id) + episode: EpisodeModel = await EpisodeModel.get( + session, + episode_id, + ) except EpisodeDoesNotExist: return None - return EpisodeResponse(**episode.to_dict(exclude=["season_id"])) + return Episode.from_pydantic(EpisodeSchema.model_validate(episode)) - @strawberry.field - async def season(self, season_id: int) -> Optional[SeasonResponse]: + @strawberry.field() + async def season(self, season_id: int) -> Season | None: async with get_async_session_ctx() as session: try: season: SeasonModel = await SeasonModel.get(session, season_id) except SeasonDoesNotExist: return None - return SeasonResponse(**season.to_dict()) + return Season.from_pydantic(SeasonSchema.model_validate(season))