From 531211ae03be8bd08cc443a12b2e749632f68ac6 Mon Sep 17 00:00:00 2001 From: Bulat Kurbanov Date: Fri, 8 Apr 2022 11:02:50 +0300 Subject: [PATCH] Add genres api --- docker/build.dockerfile | 2 +- fastapi_book_server/app/models.py | 1 - fastapi_book_server/app/serializers/genre.py | 42 +++++++++++++++ fastapi_book_server/app/views/__init__.py | 2 + fastapi_book_server/app/views/genre.py | 54 ++++++++++++++++++++ 5 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 fastapi_book_server/app/serializers/genre.py create mode 100644 fastapi_book_server/app/views/genre.py diff --git a/docker/build.dockerfile b/docker/build.dockerfile index 32dd4c4..f57fd08 100644 --- a/docker/build.dockerfile +++ b/docker/build.dockerfile @@ -7,7 +7,7 @@ RUN apt-get update \ WORKDIR /root/poetry COPY pyproject.toml poetry.lock /root/poetry/ -RUN pip install poetry --no-cache-dir \ +RUN pip install poetry wheel --no-cache-dir \ && poetry export --without-hashes > requirements.txt ENV VENV_PATH=/opt/venv diff --git a/fastapi_book_server/app/models.py b/fastapi_book_server/app/models.py index 957e820..3f60328 100644 --- a/fastapi_book_server/app/models.py +++ b/fastapi_book_server/app/models.py @@ -16,7 +16,6 @@ class Source(ormar.Model): tablename = "sources" id: int = ormar.SmallInteger(primary_key=True, nullable=False) # type: ignore - name: str = ormar.String(max_length=32, nullable=False, unique=True) # type: ignore diff --git a/fastapi_book_server/app/serializers/genre.py b/fastapi_book_server/app/serializers/genre.py new file mode 100644 index 0000000..a3ad0a8 --- /dev/null +++ b/fastapi_book_server/app/serializers/genre.py @@ -0,0 +1,42 @@ +from pydantic import BaseModel, constr + +from app.serializers.orjson_config import ORJSONConfig + + +class GenreSource(BaseModel): + id: int + name: str + + +class Genre(BaseModel): + id: int + source: GenreSource + remote_id: int + code: str + description: str + meta: str + + class Config(ORJSONConfig): + pass + + +class CreateGenre(BaseModel): + source: int + remote_id: int + code: constr(max_length=45) # type: ignore + description: constr(max_length=99) # type: ignore + meta: constr(max_length=45) # type: ignore + + class Config(ORJSONConfig): + pass + + +class UpdateGenre(BaseModel): + source: int + remote_id: int + code: constr(max_length=45) # type: ignore + description: constr(max_length=99) # type: ignore + meta: constr(max_length=45) # type: ignore + + class Config(ORJSONConfig): + pass diff --git a/fastapi_book_server/app/views/__init__.py b/fastapi_book_server/app/views/__init__.py index 5aae682..c8067a8 100644 --- a/fastapi_book_server/app/views/__init__.py +++ b/fastapi_book_server/app/views/__init__.py @@ -2,6 +2,7 @@ from app.views.author import author_router, translator_router from app.views.author_annotation import author_annotation_router from app.views.book import book_router from app.views.book_annotation import book_annotation_router +from app.views.genre import genre_router from app.views.healthcheck import healtcheck_router from app.views.sequence import sequence_router from app.views.source import source_router @@ -17,5 +18,6 @@ routers = [ book_annotation_router, translation_router, sequence_router, + genre_router, healtcheck_router, ] diff --git a/fastapi_book_server/app/views/genre.py b/fastapi_book_server/app/views/genre.py new file mode 100644 index 0000000..aff5f8a --- /dev/null +++ b/fastapi_book_server/app/views/genre.py @@ -0,0 +1,54 @@ +from fastapi import APIRouter, Depends, HTTPException, status + +from fastapi_pagination import Params, Page +from fastapi_pagination.ext.ormar import paginate + +from app.depends import check_token +from app.models import Genre as GenreDB +from app.serializers.genre import Genre, CreateGenre, UpdateGenre + + +genre_router = APIRouter( + prefix="/api/v1/genres", tags=["genres"], dependencies=[Depends(check_token)] +) + + +PREFETCH_RELATED_FIELDS = ["source"] + + +@genre_router.get("/", response_model=Page[Genre], dependencies=[Depends(Params)]) +async def get_genres(): + return await paginate(GenreDB.objects.prefetch_related(PREFETCH_RELATED_FIELDS)) + + +@genre_router.get("/{id}", response_model=Genre) +async def get_genre(id: int): + genre = await GenreDB.objects.prefetch_related(PREFETCH_RELATED_FIELDS).get_or_none( + id=id + ) + + if genre is None: + raise HTTPException(status.HTTP_404_NOT_FOUND) + + return genre + + +@genre_router.post("/", response_model=Genre) +async def create_genre(data: CreateGenre): + return await GenreDB.objects.prefetch_related(PREFETCH_RELATED_FIELDS).create( + **data.dict() + ) + + +@genre_router.put("/{id}", response_model=Genre) +async def update_genre(id: int, data: UpdateGenre): + genre = await GenreDB.objects.prefetch_related(PREFETCH_RELATED_FIELDS).get_or_none( + id=id + ) + + if genre is None: + raise HTTPException(status.HTTP_404_NOT_FOUND) + + genre.update_from_dict(data.dict()) + + return await genre.save()