Files
book_library_server/fastapi_book_server/app/services/book.py
2022-01-01 20:54:59 +03:00

81 lines
2.2 KiB
Python

from typing import Union
from fastapi import HTTPException, status
from app.models import Author as AuthorDB
from app.models import Book as BookDB
from app.serializers.book import CreateBook, CreateRemoteBook
from app.services.common import TRGMSearchService, GetRandomService
GET_OBJECT_IDS_QUERY = """
SELECT ARRAY(
WITH filtered_books AS (
SELECT id, similarity(title, :query) as sml FROM books
WHERE books.title % :query AND books.is_deleted = 'f'
)
SELECT fbooks.id FROM filtered_books as fbooks
ORDER BY fbooks.sml DESC, fbooks.id
LIMIT 210
);
"""
class BookTGRMSearchService(TRGMSearchService):
MODEL_CLASS = BookDB
PREFETCH_RELATED = ["source", "authors", "translators", "annotations"]
GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY
class BookCreator:
@classmethod
def _raise_bad_request(cls):
raise HTTPException(status.HTTP_404_NOT_FOUND)
@classmethod
async def _create_book(cls, data: CreateBook) -> BookDB:
data_dict = data.dict()
author_ids = data_dict.pop("authors", [])
authors = await AuthorDB.objects.filter(id__in=author_ids).all()
if len(author_ids) != len(authors):
cls._raise_bad_request()
book = await BookDB.objects.create(**data_dict)
for author in authors:
await book.authors.add(author)
return book
@classmethod
async def _create_remote_book(cls, data: CreateRemoteBook) -> BookDB:
data_dict = data.dict()
author_ids = data_dict.pop("remote_authors", [])
authors = await AuthorDB.objects.filter(
source__id=data.source, remote_id__in=author_ids
).all()
if len(author_ids) != len(authors):
cls._raise_bad_request()
book = await BookDB.objects.create(**data_dict)
for author in authors:
await book.authors.add(author)
return book
@classmethod
async def create(cls, data: Union[CreateBook, CreateRemoteBook]) -> BookDB:
if isinstance(data, CreateBook):
return await cls._create_book(data)
if isinstance(data, CreateRemoteBook):
return await cls._create_remote_book(data)
class GetRandomBookService(GetRandomService):
MODEL_CLASS = BookDB