mirror of
https://github.com/flibusta-apps/book_library_server.git
synced 2025-12-06 15:15:36 +01:00
Add linters configs
This commit is contained in:
@@ -1 +1 @@
|
||||
__version__ = '0.1.0'
|
||||
__version__ = "0.1.0"
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
from logging.config import fileConfig
|
||||
import os
|
||||
import sys
|
||||
|
||||
from alembic import context
|
||||
import sys, os
|
||||
|
||||
from sqlalchemy.engine import create_engine
|
||||
|
||||
from core.db import DATABASE_URL
|
||||
|
||||
|
||||
myPath = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, myPath + '/../../')
|
||||
sys.path.insert(0, myPath + "/../../")
|
||||
|
||||
config = context.config
|
||||
|
||||
|
||||
from app.models import BaseMeta
|
||||
|
||||
|
||||
target_metadata = BaseMeta.metadata
|
||||
|
||||
|
||||
|
||||
@@ -10,35 +10,77 @@ import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '08193b547a80'
|
||||
down_revision = 'b44117a41998'
|
||||
revision = "08193b547a80"
|
||||
down_revision = "b44117a41998"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_index(op.f('ix_books_title'), 'books', ['title'], unique=False)
|
||||
op.create_index(op.f('ix_sequences_name'), 'sequences', ['name'], unique=False)
|
||||
op.create_index(op.f('tgrm_books_title'), 'books', ['title'], postgresql_using='gin', postgresql_ops={'description': 'gin_trgm_ops'})
|
||||
op.create_index(op.f('tgrm_sequences_name'), 'sequences', ['name'], postgresql_using='gin', postgresql_ops={'description': 'gin_trgm_ops'})
|
||||
op.create_index(op.f('tgrm_authors_lfm'), 'authors', [sa.text("(last_name || ' ' || first_name || ' ' || middle_name)")] ,postgresql_using='gin', postgresql_ops={'description': 'gin_trgm_ops'})
|
||||
op.create_index(op.f('tgrm_authors_lf'), 'authors', [sa.text("(last_name || ' ' || first_name)")] ,postgresql_using='gin', postgresql_ops={'description': 'gin_trgm_ops'})
|
||||
op.create_index(op.f('tgrm_authors_l'), 'authors', ['last_name'] ,postgresql_using='gin', postgresql_ops={'description': 'gin_trgm_ops'})
|
||||
op.create_index(op.f('book_authors_book'), 'book_authors', ['book'], unique=False, postgresql_using='btree')
|
||||
op.create_index(op.f('book_authors_author'), 'book_authors', ['author'], unique=False, postgresql_using='btree')
|
||||
op.create_index(op.f("ix_books_title"), "books", ["title"], unique=False)
|
||||
op.create_index(op.f("ix_sequences_name"), "sequences", ["name"], unique=False)
|
||||
op.create_index(
|
||||
op.f("tgrm_books_title"),
|
||||
"books",
|
||||
["title"],
|
||||
postgresql_using="gin",
|
||||
postgresql_ops={"description": "gin_trgm_ops"},
|
||||
)
|
||||
op.create_index(
|
||||
op.f("tgrm_sequences_name"),
|
||||
"sequences",
|
||||
["name"],
|
||||
postgresql_using="gin",
|
||||
postgresql_ops={"description": "gin_trgm_ops"},
|
||||
)
|
||||
op.create_index(
|
||||
op.f("tgrm_authors_lfm"),
|
||||
"authors",
|
||||
[sa.text("(last_name || ' ' || first_name || ' ' || middle_name)")],
|
||||
postgresql_using="gin",
|
||||
postgresql_ops={"description": "gin_trgm_ops"},
|
||||
)
|
||||
op.create_index(
|
||||
op.f("tgrm_authors_lf"),
|
||||
"authors",
|
||||
[sa.text("(last_name || ' ' || first_name)")],
|
||||
postgresql_using="gin",
|
||||
postgresql_ops={"description": "gin_trgm_ops"},
|
||||
)
|
||||
op.create_index(
|
||||
op.f("tgrm_authors_l"),
|
||||
"authors",
|
||||
["last_name"],
|
||||
postgresql_using="gin",
|
||||
postgresql_ops={"description": "gin_trgm_ops"},
|
||||
)
|
||||
op.create_index(
|
||||
op.f("book_authors_book"),
|
||||
"book_authors",
|
||||
["book"],
|
||||
unique=False,
|
||||
postgresql_using="btree",
|
||||
)
|
||||
op.create_index(
|
||||
op.f("book_authors_author"),
|
||||
"book_authors",
|
||||
["author"],
|
||||
unique=False,
|
||||
postgresql_using="btree",
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_index(op.f('ix_sequences_name'), table_name='sequences')
|
||||
op.drop_index(op.f('ix_books_title'), table_name='books')
|
||||
op.drop_index(op.f('tgrm_books_title'), table_name='books')
|
||||
op.drop_index(op.f('tgrm_sequences_name'), table_name='books')
|
||||
op.drop_index(op.f('tgrm_authors_lfm'), table_name='books')
|
||||
op.drop_index(op.f('tgrm_authors_lf'), table_name='books')
|
||||
op.drop_index(op.f('tgrm_authors_l'), table_name='books')
|
||||
op.drop_index(op.f('book_authors_book'), table_name='book_authors')
|
||||
op.drop_index(op.f('book_authors_author'), table_name='book_authors')
|
||||
op.drop_index(op.f("ix_sequences_name"), table_name="sequences")
|
||||
op.drop_index(op.f("ix_books_title"), table_name="books")
|
||||
op.drop_index(op.f("tgrm_books_title"), table_name="books")
|
||||
op.drop_index(op.f("tgrm_sequences_name"), table_name="books")
|
||||
op.drop_index(op.f("tgrm_authors_lfm"), table_name="books")
|
||||
op.drop_index(op.f("tgrm_authors_lf"), table_name="books")
|
||||
op.drop_index(op.f("tgrm_authors_l"), table_name="books")
|
||||
op.drop_index(op.f("book_authors_book"), table_name="book_authors")
|
||||
op.drop_index(op.f("book_authors_author"), table_name="book_authors")
|
||||
# ### end Alembic commands ###
|
||||
|
||||
@@ -11,7 +11,7 @@ from sqlalchemy.sql.schema import UniqueConstraint
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'b44117a41998'
|
||||
revision = "b44117a41998"
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
@@ -19,128 +19,203 @@ depends_on = None
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('sources',
|
||||
sa.Column('id', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('name', sa.String(length=32), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('name')
|
||||
op.create_table(
|
||||
"sources",
|
||||
sa.Column("id", sa.SmallInteger(), nullable=False),
|
||||
sa.Column("name", sa.String(length=32), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("name"),
|
||||
)
|
||||
op.create_table('authors',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('source', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('remote_id', sa.Integer(), nullable=False),
|
||||
sa.Column('first_name', sa.String(length=256), nullable=False),
|
||||
sa.Column('last_name', sa.String(length=256), nullable=False),
|
||||
sa.Column('middle_name', sa.String(length=256), nullable=True),
|
||||
sa.ForeignKeyConstraint(['source'], ['sources.id'], name='fk_authors_sources_id_source'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('source', 'remote_id', name='uc_authors_source_remote_id')
|
||||
op.create_table(
|
||||
"authors",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("source", sa.SmallInteger(), nullable=False),
|
||||
sa.Column("remote_id", sa.Integer(), nullable=False),
|
||||
sa.Column("first_name", sa.String(length=256), nullable=False),
|
||||
sa.Column("last_name", sa.String(length=256), nullable=False),
|
||||
sa.Column("middle_name", sa.String(length=256), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["source"], ["sources.id"], name="fk_authors_sources_id_source"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("source", "remote_id", name="uc_authors_source_remote_id"),
|
||||
)
|
||||
op.create_table('books',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('source', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('remote_id', sa.Integer(), nullable=False),
|
||||
sa.Column('title', sa.String(length=256), nullable=False),
|
||||
sa.Column('lang', sa.String(length=3), nullable=False),
|
||||
sa.Column('file_type', sa.String(length=4), nullable=False),
|
||||
sa.Column('uploaded', sa.Date(), nullable=False),
|
||||
sa.Column('is_deleted', sa.Boolean(), server_default=sa.text('false'), nullable=False),
|
||||
sa.ForeignKeyConstraint(['source'], ['sources.id'], name='fk_books_sources_id_source'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('source', 'remote_id', name='uc_books_source_remote_id')
|
||||
op.create_table(
|
||||
"books",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("source", sa.SmallInteger(), nullable=False),
|
||||
sa.Column("remote_id", sa.Integer(), nullable=False),
|
||||
sa.Column("title", sa.String(length=256), nullable=False),
|
||||
sa.Column("lang", sa.String(length=3), nullable=False),
|
||||
sa.Column("file_type", sa.String(length=4), nullable=False),
|
||||
sa.Column("uploaded", sa.Date(), nullable=False),
|
||||
sa.Column(
|
||||
"is_deleted", sa.Boolean(), server_default=sa.text("false"), nullable=False
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["source"], ["sources.id"], name="fk_books_sources_id_source"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("source", "remote_id", name="uc_books_source_remote_id"),
|
||||
)
|
||||
op.create_table('genres',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('source', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('remote_id', sa.Integer(), nullable=False),
|
||||
sa.Column('code', sa.String(length=45), nullable=False),
|
||||
sa.Column('description', sa.String(length=99), nullable=False),
|
||||
sa.Column('meta', sa.String(length=45), nullable=False),
|
||||
sa.ForeignKeyConstraint(['source'], ['sources.id'], name='fk_genres_sources_id_source'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('source', 'remote_id', name='uc_genres_source_remote_id')
|
||||
op.create_table(
|
||||
"genres",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("source", sa.SmallInteger(), nullable=False),
|
||||
sa.Column("remote_id", sa.Integer(), nullable=False),
|
||||
sa.Column("code", sa.String(length=45), nullable=False),
|
||||
sa.Column("description", sa.String(length=99), nullable=False),
|
||||
sa.Column("meta", sa.String(length=45), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["source"], ["sources.id"], name="fk_genres_sources_id_source"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("source", "remote_id", name="uc_genres_source_remote_id"),
|
||||
)
|
||||
op.create_table('sequences',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('source', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('remote_id', sa.Integer(), nullable=False),
|
||||
sa.Column('name', sa.String(length=256), nullable=False),
|
||||
sa.ForeignKeyConstraint(['source'], ['sources.id'], name='fk_sequences_sources_id_source'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('source', 'remote_id', name='uc_sequences_source_remote_id')
|
||||
op.create_table(
|
||||
"sequences",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("source", sa.SmallInteger(), nullable=False),
|
||||
sa.Column("remote_id", sa.Integer(), nullable=False),
|
||||
sa.Column("name", sa.String(length=256), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["source"], ["sources.id"], name="fk_sequences_sources_id_source"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint(
|
||||
"source", "remote_id", name="uc_sequences_source_remote_id"
|
||||
),
|
||||
)
|
||||
op.create_table('author_annotations',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('author', sa.Integer(), nullable=False),
|
||||
sa.Column('title', sa.String(length=256), nullable=False),
|
||||
sa.Column('text', sa.Text(), nullable=False),
|
||||
sa.Column('file', sa.String(length=256), nullable=True),
|
||||
sa.ForeignKeyConstraint(['author'], ['authors.id'], name='fk_author_annotations_authors_id_author'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('author')
|
||||
op.create_table(
|
||||
"author_annotations",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("author", sa.Integer(), nullable=False),
|
||||
sa.Column("title", sa.String(length=256), nullable=False),
|
||||
sa.Column("text", sa.Text(), nullable=False),
|
||||
sa.Column("file", sa.String(length=256), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["author"], ["authors.id"], name="fk_author_annotations_authors_id_author"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("author"),
|
||||
)
|
||||
op.create_table('book_annotations',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('book', sa.Integer(), nullable=False),
|
||||
sa.Column('title', sa.String(length=256), nullable=False),
|
||||
sa.Column('text', sa.Text(), nullable=False),
|
||||
sa.Column('file', sa.String(length=256), nullable=True),
|
||||
sa.ForeignKeyConstraint(['book'], ['books.id'], name='fk_book_annotations_books_id_book'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('book')
|
||||
op.create_table(
|
||||
"book_annotations",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("book", sa.Integer(), nullable=False),
|
||||
sa.Column("title", sa.String(length=256), nullable=False),
|
||||
sa.Column("text", sa.Text(), nullable=False),
|
||||
sa.Column("file", sa.String(length=256), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["book"], ["books.id"], name="fk_book_annotations_books_id_book"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("book"),
|
||||
)
|
||||
op.create_table('book_authors',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('author', sa.Integer(), nullable=True),
|
||||
sa.Column('book', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['author'], ['authors.id'], name='fk_book_authors_authors_author_id', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['book'], ['books.id'], name='fk_book_authors_books_book_id', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('book', 'author', name='uc_book_authors_book_author'),
|
||||
op.create_table(
|
||||
"book_authors",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("author", sa.Integer(), nullable=True),
|
||||
sa.Column("book", sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["author"],
|
||||
["authors.id"],
|
||||
name="fk_book_authors_authors_author_id",
|
||||
onupdate="CASCADE",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["book"],
|
||||
["books.id"],
|
||||
name="fk_book_authors_books_book_id",
|
||||
onupdate="CASCADE",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("book", "author", name="uc_book_authors_book_author"),
|
||||
)
|
||||
op.create_table('book_genres',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('genre', sa.Integer(), nullable=True),
|
||||
sa.Column('book', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['book'], ['books.id'], name='fk_book_genres_books_book_id', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['genre'], ['genres.id'], name='fk_book_genres_genres_genre_id', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('book', 'genre', name='uc_book_genres_book_genre'),
|
||||
op.create_table(
|
||||
"book_genres",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("genre", sa.Integer(), nullable=True),
|
||||
sa.Column("book", sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["book"],
|
||||
["books.id"],
|
||||
name="fk_book_genres_books_book_id",
|
||||
onupdate="CASCADE",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["genre"],
|
||||
["genres.id"],
|
||||
name="fk_book_genres_genres_genre_id",
|
||||
onupdate="CASCADE",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("book", "genre", name="uc_book_genres_book_genre"),
|
||||
)
|
||||
op.create_table('book_sequences',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('position', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('sequence', sa.Integer(), nullable=True),
|
||||
sa.Column('book', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['book'], ['books.id'], name='fk_book_sequences_books_book_id', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['sequence'], ['sequences.id'], name='fk_book_sequences_sequences_sequence_id', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('book', 'sequence', name='uc_book_sequences_book_sequence'),
|
||||
op.create_table(
|
||||
"book_sequences",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("position", sa.SmallInteger(), nullable=False),
|
||||
sa.Column("sequence", sa.Integer(), nullable=True),
|
||||
sa.Column("book", sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["book"],
|
||||
["books.id"],
|
||||
name="fk_book_sequences_books_book_id",
|
||||
onupdate="CASCADE",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["sequence"],
|
||||
["sequences.id"],
|
||||
name="fk_book_sequences_sequences_sequence_id",
|
||||
onupdate="CASCADE",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("book", "sequence", name="uc_book_sequences_book_sequence"),
|
||||
)
|
||||
op.create_table('translations',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('position', sa.SmallInteger(), nullable=False),
|
||||
sa.Column('author', sa.Integer(), nullable=True),
|
||||
sa.Column('book', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['author'], ['authors.id'], name='fk_translations_authors_author_id', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['book'], ['books.id'], name='fk_translations_books_book_id', onupdate='CASCADE', ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('book', 'author', name='uc_translations_book_author'),
|
||||
op.create_table(
|
||||
"translations",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("position", sa.SmallInteger(), nullable=False),
|
||||
sa.Column("author", sa.Integer(), nullable=True),
|
||||
sa.Column("book", sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["author"],
|
||||
["authors.id"],
|
||||
name="fk_translations_authors_author_id",
|
||||
onupdate="CASCADE",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["book"],
|
||||
["books.id"],
|
||||
name="fk_translations_books_book_id",
|
||||
onupdate="CASCADE",
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("book", "author", name="uc_translations_book_author"),
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('translations')
|
||||
op.drop_table('book_sequences')
|
||||
op.drop_table('book_genres')
|
||||
op.drop_table('book_authors')
|
||||
op.drop_table('book_annotations')
|
||||
op.drop_table('author_annotations')
|
||||
op.drop_table('sequences')
|
||||
op.drop_table('genres')
|
||||
op.drop_table('books')
|
||||
op.drop_table('authors')
|
||||
op.drop_table('sources')
|
||||
op.drop_table("translations")
|
||||
op.drop_table("book_sequences")
|
||||
op.drop_table("book_genres")
|
||||
op.drop_table("book_authors")
|
||||
op.drop_table("book_annotations")
|
||||
op.drop_table("author_annotations")
|
||||
op.drop_table("sequences")
|
||||
op.drop_table("genres")
|
||||
op.drop_table("books")
|
||||
op.drop_table("authors")
|
||||
op.drop_table("sources")
|
||||
# ### end Alembic commands ###
|
||||
|
||||
@@ -6,4 +6,6 @@ from core.config import env_config
|
||||
|
||||
async def check_token(api_key: str = Security(default_security)):
|
||||
if api_key != env_config.API_KEY:
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Wrong api key!")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN, detail="Wrong api key!"
|
||||
)
|
||||
|
||||
@@ -5,6 +5,6 @@ def get_book_filter(is_deleted: Optional[bool] = None) -> dict:
|
||||
result = {}
|
||||
|
||||
if is_deleted is not None:
|
||||
result['is_deleted'] = is_deleted
|
||||
result["is_deleted"] = is_deleted
|
||||
|
||||
return result
|
||||
|
||||
@@ -64,9 +64,13 @@ class AuthorAnnotation(ormar.Model):
|
||||
|
||||
id = ormar.Integer(primary_key=True, nullable=False)
|
||||
|
||||
author: Author = ormar.ForeignKey(Author, nullable=False, unique=True, related_name="annotations")
|
||||
author: Author = ormar.ForeignKey(
|
||||
Author, nullable=False, unique=True, related_name="annotations"
|
||||
)
|
||||
|
||||
title: str = ormar.String(max_length=256, nullable=False, default="") # type: ignore
|
||||
title: str = ormar.String(
|
||||
max_length=256, nullable=False, default=""
|
||||
) # type: ignore
|
||||
text: str = ormar.Text(nullable=False, default="") # type: ignore
|
||||
file: str = ormar.String(max_length=256, nullable=True) # type: ignore
|
||||
|
||||
@@ -89,7 +93,7 @@ class Sequence(ormar.Model):
|
||||
class BookAuthors(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "book_authors"
|
||||
|
||||
|
||||
id: int = ormar.Integer(primary_key=True, nullable=False) # type: ignore
|
||||
|
||||
|
||||
@@ -103,7 +107,9 @@ class BookGenres(ormar.Model):
|
||||
class BookSequences(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "book_sequences"
|
||||
orders_by = ["position", ]
|
||||
orders_by = [
|
||||
"position",
|
||||
]
|
||||
|
||||
id: int = ormar.Integer(primary_key=True, nullable=False) # type: ignore
|
||||
|
||||
@@ -113,7 +119,9 @@ class BookSequences(ormar.Model):
|
||||
class Translation(ormar.Model):
|
||||
class Meta(BaseMeta):
|
||||
tablename = "translations"
|
||||
orders_by = ["position", ]
|
||||
orders_by = [
|
||||
"position",
|
||||
]
|
||||
|
||||
id: int = ormar.Integer(primary_key=True, nullable=False) # type: ignore
|
||||
|
||||
@@ -132,21 +140,27 @@ class Book(ormar.Model):
|
||||
source: Source = ormar.ForeignKey(Source, nullable=False)
|
||||
remote_id: int = ormar.Integer(minimum=0, nullable=False) # type: ignore
|
||||
|
||||
title: str = ormar.String(max_length=256, nullable=False, index=True) # type: ignore
|
||||
title: str = ormar.String(
|
||||
max_length=256, nullable=False, index=True
|
||||
) # type: ignore
|
||||
lang: str = ormar.String(max_length=3, nullable=False) # type: ignore
|
||||
file_type: str = ormar.String(max_length=4, nullable=False) # type: ignore
|
||||
uploaded: date = ormar.Date() # type: ignore
|
||||
is_deleted: bool = ormar.Boolean(default=False, server_default=text("false"), nullable=False)
|
||||
is_deleted: bool = ormar.Boolean(
|
||||
default=False, server_default=text("false"), nullable=False
|
||||
)
|
||||
|
||||
authors = ormar.ManyToMany(Author, through=BookAuthors)
|
||||
translators = ormar.ManyToMany(Author, through=Translation, related_name="translated_books")
|
||||
translators = ormar.ManyToMany(
|
||||
Author, through=Translation, related_name="translated_books"
|
||||
)
|
||||
genres = ormar.ManyToMany(Genre, through=BookGenres)
|
||||
sequences = ormar.ManyToMany(Sequence, through=BookSequences)
|
||||
|
||||
@ormar.property_field
|
||||
def available_types(self) -> list[str]:
|
||||
if self.file_type == 'fb2' and self.source.name == 'flibusta':
|
||||
return ['fb2', 'fb2zip', 'epub', 'mobi']
|
||||
if self.file_type == "fb2" and self.source.name == "flibusta":
|
||||
return ["fb2", "fb2zip", "epub", "mobi"]
|
||||
|
||||
return [self.file_type]
|
||||
|
||||
@@ -161,8 +175,12 @@ class BookAnnotation(ormar.Model):
|
||||
|
||||
id = ormar.Integer(primary_key=True, nullable=False)
|
||||
|
||||
book: Book = ormar.ForeignKey(Book, nullable=False, unique=True, related_name="annotations")
|
||||
book: Book = ormar.ForeignKey(
|
||||
Book, nullable=False, unique=True, related_name="annotations"
|
||||
)
|
||||
|
||||
title: str = ormar.String(max_length=256, nullable=False, default="") # type: ignore
|
||||
title: str = ormar.String(
|
||||
max_length=256, nullable=False, default=""
|
||||
) # type: ignore
|
||||
text: str = ormar.Text(nullable=False, default="") # type: ignore
|
||||
file: str = ormar.String(max_length=256, nullable=True) # type: ignore
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from typing import Optional
|
||||
from datetime import date
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from typing import Optional
|
||||
from datetime import date
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.serializers.orjson_config import ORJSONConfig
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
from app.models import Author
|
||||
|
||||
from app.services.common import TRGMSearchService, GetRandomService
|
||||
|
||||
|
||||
GET_OBJECT_IDS_QUERY = """
|
||||
SELECT ARRAY(
|
||||
WITH filtered_authors AS (
|
||||
SELECT
|
||||
WITH filtered_authors AS (
|
||||
SELECT
|
||||
id,
|
||||
GREATEST(
|
||||
similarity((last_name || ' ' || first_name || ' ' || middle_name), :query),
|
||||
similarity(
|
||||
(last_name || ' ' || first_name || ' ' || middle_name),
|
||||
:query
|
||||
),
|
||||
similarity((last_name || ' ' || first_name), :query),
|
||||
similarity((last_name), :query)
|
||||
) as sml,
|
||||
@@ -27,7 +29,7 @@ SELECT ARRAY(
|
||||
EXISTS (
|
||||
SELECT * FROM book_authors
|
||||
LEFT JOIN books ON (books.id = book AND books.is_deleted = 'f')
|
||||
WHERE author = authors.id
|
||||
WHERE author = authors.id
|
||||
)
|
||||
)
|
||||
SELECT fauthors.id FROM filtered_authors as fauthors
|
||||
|
||||
@@ -2,15 +2,15 @@ from typing import Union
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
|
||||
from app.models import Book as BookDB, Author as AuthorDB
|
||||
|
||||
from app.services.common import TRGMSearchService, GetRandomService
|
||||
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 (
|
||||
WITH filtered_books AS (
|
||||
SELECT id, similarity(title, :query) as sml FROM books
|
||||
WHERE books.title % :query AND books.is_deleted = 'f'
|
||||
)
|
||||
@@ -42,9 +42,7 @@ class BookCreator:
|
||||
if len(author_ids) != len(authors):
|
||||
cls._raise_bad_request()
|
||||
|
||||
book = await BookDB.objects.create(
|
||||
**data_dict
|
||||
)
|
||||
book = await BookDB.objects.create(**data_dict)
|
||||
|
||||
for author in authors:
|
||||
await book.authors.add(author)
|
||||
@@ -56,14 +54,14 @@ class BookCreator:
|
||||
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()
|
||||
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
|
||||
)
|
||||
book = await BookDB.objects.create(**data_dict)
|
||||
|
||||
for author in authors:
|
||||
await book.authors.add(author)
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
from typing import Optional, Generic, TypeVar, Union
|
||||
from databases import Database
|
||||
|
||||
import aioredis
|
||||
from databases import Database
|
||||
from fastapi_pagination.api import resolve_params
|
||||
from fastapi_pagination.bases import AbstractParams, RawParams
|
||||
from app.utils.pagination import Page, CustomPage
|
||||
import aioredis
|
||||
import orjson
|
||||
|
||||
from ormar import Model, QuerySet
|
||||
from sqlalchemy import Table
|
||||
|
||||
from app.utils.pagination import Page, CustomPage
|
||||
|
||||
T = TypeVar('T', bound=Model)
|
||||
|
||||
T = TypeVar("T", bound=Model)
|
||||
|
||||
|
||||
class TRGMSearchService(Generic[T]):
|
||||
@@ -48,7 +48,9 @@ class TRGMSearchService(Generic[T]):
|
||||
@classmethod
|
||||
@property
|
||||
def object_ids_query(cls) -> str:
|
||||
assert cls.GET_OBJECT_IDS_QUERY is not None, f"GET_OBJECT_IDS_QUERY in {cls.__name__} don't set!"
|
||||
assert (
|
||||
cls.GET_OBJECT_IDS_QUERY is not None
|
||||
), f"GET_OBJECT_IDS_QUERY in {cls.__name__} don't set!"
|
||||
return cls.GET_OBJECT_IDS_QUERY
|
||||
|
||||
@classmethod
|
||||
@@ -56,9 +58,9 @@ class TRGMSearchService(Generic[T]):
|
||||
row = await cls.database.fetch_one(cls.object_ids_query, {"query": query_data})
|
||||
|
||||
if row is None:
|
||||
raise ValueError('Something is wrong!')
|
||||
raise ValueError("Something is wrong!")
|
||||
|
||||
return row['array']
|
||||
return row["array"]
|
||||
|
||||
@classmethod
|
||||
def get_cache_key(cls, query_data: str) -> str:
|
||||
@@ -66,7 +68,9 @@ class TRGMSearchService(Generic[T]):
|
||||
return f"{model_class_name}_{query_data}"
|
||||
|
||||
@classmethod
|
||||
async def get_cached_ids(cls, query_data: str, redis: aioredis.Redis) -> Optional[list[int]]:
|
||||
async def get_cached_ids(
|
||||
cls, query_data: str, redis: aioredis.Redis
|
||||
) -> Optional[list[int]]:
|
||||
try:
|
||||
key = cls.get_cache_key(query_data)
|
||||
data = await redis.get(key)
|
||||
@@ -80,7 +84,9 @@ class TRGMSearchService(Generic[T]):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def cache_object_ids(cls, query_data: str, object_ids: list[int], redis: aioredis.Redis):
|
||||
async def cache_object_ids(
|
||||
cls, query_data: str, object_ids: list[int], redis: aioredis.Redis
|
||||
):
|
||||
try:
|
||||
key = cls.get_cache_key(query_data)
|
||||
await redis.set(key, orjson.dumps(object_ids), ex=cls.CACHE_TTL)
|
||||
@@ -88,7 +94,9 @@ class TRGMSearchService(Generic[T]):
|
||||
print(e)
|
||||
|
||||
@classmethod
|
||||
async def get_objects(cls, query_data: str, redis: aioredis.Redis) -> tuple[int, list[T]]:
|
||||
async def get_objects(
|
||||
cls, query_data: str, redis: aioredis.Redis
|
||||
) -> tuple[int, list[T]]:
|
||||
params = cls.get_raw_params()
|
||||
|
||||
cached_object_ids = await cls.get_cached_ids(query_data, redis)
|
||||
@@ -99,7 +107,7 @@ class TRGMSearchService(Generic[T]):
|
||||
else:
|
||||
object_ids = cached_object_ids
|
||||
|
||||
limited_object_ids = object_ids[params.offset:params.offset + params.limit]
|
||||
limited_object_ids = object_ids[params.offset : params.offset + params.limit]
|
||||
|
||||
queryset: QuerySet[T] = cls.model.objects
|
||||
|
||||
@@ -117,11 +125,7 @@ class TRGMSearchService(Generic[T]):
|
||||
|
||||
total, objects = await cls.get_objects(query, redis)
|
||||
|
||||
return CustomPage.create(
|
||||
items=objects,
|
||||
total=total,
|
||||
params=params
|
||||
)
|
||||
return CustomPage.create(items=objects, total=total, params=params)
|
||||
|
||||
|
||||
GET_RANDOM_OBJECT_ID_QUERY = """
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
from app.models import Sequence
|
||||
|
||||
from app.services.common import TRGMSearchService, GetRandomService
|
||||
|
||||
|
||||
GET_OBJECT_IDS_QUERY = """
|
||||
SELECT ARRAY (
|
||||
WITH filtered_sequences AS (
|
||||
SELECT
|
||||
SELECT
|
||||
id,
|
||||
similarity(name, :query) as sml,
|
||||
(
|
||||
SELECT count(*) FROM book_sequences
|
||||
LEFT JOIN books ON (books.id = book AND books.is_deleted = 'f')
|
||||
WHERE sequence = sequences.id
|
||||
WHERE sequence = sequences.id
|
||||
) as books_count
|
||||
FROM sequences
|
||||
WHERE name % :query AND
|
||||
|
||||
@@ -2,10 +2,12 @@ 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.models import Source as SourceDB
|
||||
from app.models import Translation as TranslationDB
|
||||
from app.serializers.translation import CreateTranslation, CreateRemoteTranslation
|
||||
|
||||
from app.models import Translation as TranslationDB, Source as SourceDB, Book as BookDB, Author as AuthorDB
|
||||
|
||||
|
||||
class TranslationCreator:
|
||||
@classmethod
|
||||
@@ -14,23 +16,27 @@ class TranslationCreator:
|
||||
|
||||
@classmethod
|
||||
async def _create_translation(cls, data: CreateTranslation) -> TranslationDB:
|
||||
return await TranslationDB.objects.create(
|
||||
**data.dict()
|
||||
)
|
||||
return await TranslationDB.objects.create(**data.dict())
|
||||
|
||||
@classmethod
|
||||
async def _create_remote_translation(cls, data: CreateRemoteTranslation) -> TranslationDB:
|
||||
async def _create_remote_translation(
|
||||
cls, data: CreateRemoteTranslation
|
||||
) -> TranslationDB:
|
||||
source = await SourceDB.objects.get_or_none(id=data.source)
|
||||
|
||||
if source is None:
|
||||
cls._raise_bad_request()
|
||||
|
||||
book = await BookDB.objects.get_or_none(source__id=source.id, remote_id=data.remote_book)
|
||||
book = await BookDB.objects.get_or_none(
|
||||
source__id=source.id, remote_id=data.remote_book
|
||||
)
|
||||
|
||||
if book is None:
|
||||
cls._raise_bad_request()
|
||||
|
||||
translator = await AuthorDB.objects.get_or_none(source__id=source.id, remote_id=data.remote_translator)
|
||||
translator = await AuthorDB.objects.get_or_none(
|
||||
source__id=source.id, remote_id=data.remote_translator
|
||||
)
|
||||
|
||||
if translator is None:
|
||||
cls._raise_bad_request()
|
||||
@@ -42,7 +48,9 @@ class TranslationCreator:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def create(cls, data: Union[CreateTranslation, CreateRemoteTranslation]) -> TranslationDB:
|
||||
async def create(
|
||||
cls, data: Union[CreateTranslation, CreateRemoteTranslation]
|
||||
) -> TranslationDB:
|
||||
if isinstance(data, CreateTranslation):
|
||||
return await cls._create_translation(data)
|
||||
if isinstance(data, CreateRemoteTranslation):
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
from typing import Protocol, TypeVar, Any, Generic, Sequence, runtime_checkable
|
||||
|
||||
from pydantic import conint
|
||||
|
||||
from fastapi_pagination import Page, Params
|
||||
from fastapi_pagination.bases import AbstractParams
|
||||
from pydantic import conint
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
@@ -12,7 +11,7 @@ class ToDict(Protocol):
|
||||
...
|
||||
|
||||
|
||||
T = TypeVar('T', ToDict, Any)
|
||||
T = TypeVar("T", ToDict, Any)
|
||||
|
||||
|
||||
class CustomPage(Page[T], Generic[T]):
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
from app.views.source import source_router
|
||||
|
||||
from app.views.author import author_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.translation import translation_router
|
||||
|
||||
from app.views.sequence import sequence_router
|
||||
from app.views.source import source_router
|
||||
from app.views.translation import translation_router
|
||||
|
||||
|
||||
routers = [
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
from random import choice as random_choice
|
||||
|
||||
from fastapi import APIRouter, Depends, Request, HTTPException, status
|
||||
|
||||
from fastapi_pagination import Params
|
||||
from fastapi_pagination.ext.ormar import paginate
|
||||
from app.utils.pagination import CustomPage
|
||||
|
||||
from app.models import Author as AuthorDB, AuthorAnnotation as AuthorAnnotationDB, Book as BookDB
|
||||
from app.serializers.author import Author, CreateAuthor, UpdateAuthor, AuthorBook, TranslatedBook
|
||||
from app.depends import check_token
|
||||
from app.models import Author as AuthorDB
|
||||
from app.models import AuthorAnnotation as AuthorAnnotationDB
|
||||
from app.models import Book as BookDB
|
||||
from app.serializers.author import (
|
||||
Author,
|
||||
CreateAuthor,
|
||||
UpdateAuthor,
|
||||
AuthorBook,
|
||||
TranslatedBook,
|
||||
)
|
||||
from app.serializers.author_annotation import AuthorAnnotation
|
||||
from app.services.author import AuthorTGRMSearchService, GetRandomAuthorService
|
||||
from app.depends import check_token
|
||||
from app.utils.pagination import CustomPage
|
||||
|
||||
|
||||
author_router = APIRouter(
|
||||
@@ -20,22 +26,19 @@ author_router = APIRouter(
|
||||
)
|
||||
|
||||
|
||||
|
||||
PREFETCH_RELATED = ["source", "annotations"]
|
||||
|
||||
|
||||
@author_router.get("/", response_model=CustomPage[Author], dependencies=[Depends(Params)])
|
||||
@author_router.get(
|
||||
"/", response_model=CustomPage[Author], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def get_authors():
|
||||
return await paginate(
|
||||
AuthorDB.objects.prefetch_related(PREFETCH_RELATED)
|
||||
)
|
||||
return await paginate(AuthorDB.objects.prefetch_related(PREFETCH_RELATED))
|
||||
|
||||
|
||||
@author_router.post("/", response_model=Author, dependencies=[Depends(Params)])
|
||||
async def create_author(data: CreateAuthor):
|
||||
author = await AuthorDB.objects.create(
|
||||
**data.dict()
|
||||
)
|
||||
author = await AuthorDB.objects.create(**data.dict())
|
||||
|
||||
return await AuthorDB.objects.prefetch_related(PREFETCH_RELATED).get(id=author.id)
|
||||
|
||||
@@ -49,7 +52,9 @@ async def get_random_author():
|
||||
|
||||
@author_router.get("/{id}", response_model=Author)
|
||||
async def get_author(id: int):
|
||||
author = await AuthorDB.objects.prefetch_related(PREFETCH_RELATED).get_or_none(id=id)
|
||||
author = await AuthorDB.objects.prefetch_related(PREFETCH_RELATED).get_or_none(
|
||||
id=id
|
||||
)
|
||||
|
||||
if author is None:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
@@ -75,24 +80,32 @@ async def get_author_annotation(id: int):
|
||||
|
||||
if annotation is None:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
|
||||
|
||||
return annotation
|
||||
|
||||
|
||||
@author_router.get("/{id}/books", response_model=CustomPage[AuthorBook], dependencies=[Depends(Params)])
|
||||
@author_router.get(
|
||||
"/{id}/books", response_model=CustomPage[AuthorBook], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def get_author_books(id: int):
|
||||
return await paginate(
|
||||
BookDB.objects.select_related(["source", "annotations", "translators"]).filter(authors__id=id).order_by('title')
|
||||
BookDB.objects.select_related(["source", "annotations", "translators"])
|
||||
.filter(authors__id=id)
|
||||
.order_by("title")
|
||||
)
|
||||
|
||||
|
||||
@author_router.get("/{id}/translated_books", response_model=CustomPage[TranslatedBook])
|
||||
async def get_translated_books(id: int):
|
||||
return await paginate(
|
||||
BookDB.objects.select_related(["source", "annotations", "translators"]).filter(translations__translator__id=id)
|
||||
BookDB.objects.select_related(["source", "annotations", "translators"]).filter(
|
||||
translations__translator__id=id
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@author_router.get("/search/{query}", response_model=CustomPage[Author], dependencies=[Depends(Params)])
|
||||
@author_router.get(
|
||||
"/search/{query}", response_model=CustomPage[Author], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def search_authors(query: str, request: Request):
|
||||
return await AuthorTGRMSearchService.get(query, request.app.state.redis)
|
||||
|
||||
@@ -3,9 +3,13 @@ from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi_pagination import Params, Page
|
||||
from fastapi_pagination.ext.ormar import paginate
|
||||
|
||||
from app.models import AuthorAnnotation as AuthorAnnotationDB
|
||||
from app.serializers.author_annotation import AuthorAnnotation, CreateAuthorAnnotation, UpdateAuthorAnnotation
|
||||
from app.depends import check_token
|
||||
from app.models import AuthorAnnotation as AuthorAnnotationDB
|
||||
from app.serializers.author_annotation import (
|
||||
AuthorAnnotation,
|
||||
CreateAuthorAnnotation,
|
||||
UpdateAuthorAnnotation,
|
||||
)
|
||||
|
||||
|
||||
author_annotation_router = APIRouter(
|
||||
@@ -15,18 +19,16 @@ author_annotation_router = APIRouter(
|
||||
)
|
||||
|
||||
|
||||
@author_annotation_router.get("/", response_model=Page[AuthorAnnotation], dependencies=[Depends(Params)])
|
||||
@author_annotation_router.get(
|
||||
"/", response_model=Page[AuthorAnnotation], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def get_author_annotations():
|
||||
return await paginate(
|
||||
AuthorAnnotationDB.objects
|
||||
)
|
||||
return await paginate(AuthorAnnotationDB.objects)
|
||||
|
||||
|
||||
@author_annotation_router.post("/", response_model=AuthorAnnotation)
|
||||
async def create_author_annotation(data: CreateAuthorAnnotation):
|
||||
return await AuthorAnnotationDB.objects.create(
|
||||
**data.dict()
|
||||
)
|
||||
return await AuthorAnnotationDB.objects.create(**data.dict())
|
||||
|
||||
|
||||
@author_annotation_router.get("/{id}", response_model=AuthorAnnotation)
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
from typing import Union
|
||||
from random import choice as random_choice
|
||||
|
||||
from fastapi import APIRouter, Depends, Request, HTTPException, status
|
||||
|
||||
from fastapi_pagination import Params
|
||||
from fastapi_pagination.ext.ormar import paginate
|
||||
from app.utils.pagination import CustomPage
|
||||
|
||||
from app.models import Book as BookDB, Author as AuthorDB, BookAnnotation as BookAnnotationDB
|
||||
from app.serializers.book import Book, RemoteBook, BookDetail, CreateBook, UpdateBook, CreateRemoteBook
|
||||
from app.depends import check_token
|
||||
from app.filters.book import get_book_filter
|
||||
from app.models import Author as AuthorDB
|
||||
from app.models import Book as BookDB
|
||||
from app.models import BookAnnotation as BookAnnotationDB
|
||||
from app.serializers.book import (
|
||||
Book,
|
||||
RemoteBook,
|
||||
BookDetail,
|
||||
CreateBook,
|
||||
UpdateBook,
|
||||
CreateRemoteBook,
|
||||
)
|
||||
from app.serializers.book_annotation import BookAnnotation
|
||||
from app.services.book import BookTGRMSearchService, GetRandomBookService, BookCreator
|
||||
from app.filters.book import get_book_filter
|
||||
from app.depends import check_token
|
||||
from app.utils.pagination import CustomPage
|
||||
|
||||
|
||||
book_router = APIRouter(
|
||||
@@ -22,10 +30,12 @@ book_router = APIRouter(
|
||||
)
|
||||
|
||||
|
||||
SELECT_RELATED_FIELDS = ["source", "authors", "translators", "annotations"]
|
||||
SELECT_RELATED_FIELDS = ["source", "authors", "translators", "annotations"]
|
||||
|
||||
|
||||
@book_router.get("/", response_model=CustomPage[RemoteBook], dependencies=[Depends(Params)])
|
||||
@book_router.get(
|
||||
"/", response_model=CustomPage[RemoteBook], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def get_books(book_filter: dict = Depends(get_book_filter)):
|
||||
return await paginate(
|
||||
BookDB.objects.select_related(SELECT_RELATED_FIELDS).filter(**book_filter)
|
||||
@@ -49,7 +59,7 @@ async def get_random_book():
|
||||
@book_router.get("/{id}", response_model=BookDetail)
|
||||
async def get_book(id: int):
|
||||
book = await BookDB.objects.select_related(SELECT_RELATED_FIELDS).get_or_none(id=id)
|
||||
|
||||
|
||||
if book is None:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
|
||||
@@ -59,8 +69,7 @@ async def get_book(id: int):
|
||||
@book_router.get("/remote/{source_id}/{remote_id}", response_model=Book)
|
||||
async def get_remote_book(source_id: int, remote_id: int):
|
||||
book = await BookDB.objects.select_related(SELECT_RELATED_FIELDS).get_or_none(
|
||||
source=source_id,
|
||||
remote_id=remote_id
|
||||
source=source_id, remote_id=remote_id
|
||||
)
|
||||
|
||||
if book is None:
|
||||
@@ -84,9 +93,7 @@ async def update_book(id: int, data: UpdateBook):
|
||||
author_ids = data_dict.pop("authors", [])
|
||||
authors = await AuthorDB.objects.filter(id__in=author_ids).all()
|
||||
|
||||
book = await BookDB.objects.create(
|
||||
**data_dict
|
||||
)
|
||||
book = await BookDB.objects.create(**data_dict)
|
||||
|
||||
for author in authors:
|
||||
await book.authors.add(author)
|
||||
@@ -104,6 +111,8 @@ async def get_book_annotation(id: int):
|
||||
return annotation
|
||||
|
||||
|
||||
@book_router.get("/search/{query}", response_model=CustomPage[Book], dependencies=[Depends(Params)])
|
||||
@book_router.get(
|
||||
"/search/{query}", response_model=CustomPage[Book], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def search_books(query: str, request: Request):
|
||||
return await BookTGRMSearchService.get(query, request.app.state.redis)
|
||||
|
||||
@@ -3,30 +3,32 @@ from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi_pagination import Params, Page
|
||||
from fastapi_pagination.ext.ormar import paginate
|
||||
|
||||
from app.models import BookAnnotation as BookAnnotationDB
|
||||
from app.serializers.book_annotation import BookAnnotation, CreateBookAnnotation, UpdateBookAnnotation
|
||||
from app.depends import check_token
|
||||
from app.models import BookAnnotation as BookAnnotationDB
|
||||
from app.serializers.book_annotation import (
|
||||
BookAnnotation,
|
||||
CreateBookAnnotation,
|
||||
UpdateBookAnnotation,
|
||||
)
|
||||
|
||||
|
||||
book_annotation_router = APIRouter(
|
||||
prefix="/api/v1/book_annotations",
|
||||
tags=["book_annotation"],
|
||||
dependencies=[Depends(check_token)]
|
||||
dependencies=[Depends(check_token)],
|
||||
)
|
||||
|
||||
|
||||
@book_annotation_router.get("/", response_model=Page[BookAnnotation], dependencies=[Depends(Params)])
|
||||
@book_annotation_router.get(
|
||||
"/", response_model=Page[BookAnnotation], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def get_book_annotations():
|
||||
return await paginate(
|
||||
BookAnnotationDB.objects
|
||||
)
|
||||
return await paginate(BookAnnotationDB.objects)
|
||||
|
||||
|
||||
@book_annotation_router.post("/", response_model=BookAnnotation)
|
||||
async def create_book_annotation(data: CreateBookAnnotation):
|
||||
return await BookAnnotationDB.objects.create(
|
||||
**data.dict()
|
||||
)
|
||||
return await BookAnnotationDB.objects.create(**data.dict())
|
||||
|
||||
|
||||
@book_annotation_router.get("/{id}", response_model=BookAnnotation)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
from random import choice as random_choice
|
||||
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
|
||||
from fastapi_pagination import Params
|
||||
from fastapi_pagination.ext.ormar import paginate
|
||||
from app.utils.pagination import CustomPage
|
||||
|
||||
from app.models import Sequence as SequenceDB, Book as BookDB, BookSequences as BookSequencesDB
|
||||
from app.serializers.sequence import Sequence, CreateSequence, Book as SequenceBook
|
||||
from app.services.sequence import SequenceTGRMSearchService, GetRandomSequenceService
|
||||
from app.depends import check_token
|
||||
from app.models import Book as BookDB
|
||||
from app.models import Sequence as SequenceDB
|
||||
from app.serializers.sequence import Book as SequenceBook
|
||||
from app.serializers.sequence import Sequence, CreateSequence
|
||||
from app.services.sequence import SequenceTGRMSearchService, GetRandomSequenceService
|
||||
from app.utils.pagination import CustomPage
|
||||
|
||||
|
||||
sequence_router = APIRouter(
|
||||
@@ -19,11 +19,11 @@ sequence_router = APIRouter(
|
||||
)
|
||||
|
||||
|
||||
@sequence_router.get("/", response_model=CustomPage[Sequence], dependencies=[Depends(Params)])
|
||||
@sequence_router.get(
|
||||
"/", response_model=CustomPage[Sequence], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def get_sequences():
|
||||
return await paginate(
|
||||
SequenceDB.objects
|
||||
)
|
||||
return await paginate(SequenceDB.objects)
|
||||
|
||||
|
||||
@sequence_router.get("/random", response_model=Sequence)
|
||||
@@ -38,21 +38,30 @@ async def get_sequence(id: int):
|
||||
return await SequenceDB.objects.get(id=id)
|
||||
|
||||
|
||||
@sequence_router.get("/{id}/books", response_model=CustomPage[SequenceBook], dependencies=[Depends(Params)])
|
||||
@sequence_router.get(
|
||||
"/{id}/books",
|
||||
response_model=CustomPage[SequenceBook],
|
||||
dependencies=[Depends(Params)],
|
||||
)
|
||||
async def get_sequence_books(id: int):
|
||||
return await paginate(
|
||||
BookDB.objects.select_related(["source", "annotations", "authors", "translators"])
|
||||
.filter(sequences__id=id).order_by("sequences__booksequences__position")
|
||||
BookDB.objects.select_related(
|
||||
["source", "annotations", "authors", "translators"]
|
||||
)
|
||||
.filter(sequences__id=id)
|
||||
.order_by("sequences__booksequences__position")
|
||||
)
|
||||
|
||||
|
||||
@sequence_router.post("/", response_model=Sequence)
|
||||
async def create_sequence(data: CreateSequence):
|
||||
return await SequenceDB.objects.create(
|
||||
**data.dict()
|
||||
)
|
||||
return await SequenceDB.objects.create(**data.dict())
|
||||
|
||||
|
||||
@sequence_router.get("/search/{query}", response_model=CustomPage[Sequence], dependencies=[Depends(Params)])
|
||||
@sequence_router.get(
|
||||
"/search/{query}",
|
||||
response_model=CustomPage[Sequence],
|
||||
dependencies=[Depends(Params)],
|
||||
)
|
||||
async def search_sequences(query: str, request: Request):
|
||||
return await SequenceTGRMSearchService.get(query, request.app.state.redis)
|
||||
|
||||
@@ -3,9 +3,9 @@ from fastapi import APIRouter, Depends
|
||||
from fastapi_pagination import Params, Page
|
||||
from fastapi_pagination.ext.ormar import paginate
|
||||
|
||||
from app.depends import check_token
|
||||
from app.models import Source as SourceDB
|
||||
from app.serializers.source import Source, CreateSource
|
||||
from app.depends import check_token
|
||||
|
||||
|
||||
source_router = APIRouter(
|
||||
@@ -22,6 +22,4 @@ async def get_sources():
|
||||
|
||||
@source_router.post("", response_model=Source)
|
||||
async def create_source(data: CreateSource):
|
||||
return await SourceDB.objects.create(
|
||||
**data.dict()
|
||||
)
|
||||
return await SourceDB.objects.create(**data.dict())
|
||||
|
||||
@@ -4,12 +4,16 @@ from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
from fastapi_pagination import Params
|
||||
from fastapi_pagination.ext.ormar import paginate
|
||||
from app.utils.pagination import CustomPage
|
||||
|
||||
from app.models import Translation as TranslationDB
|
||||
from app.serializers.translation import Translation, CreateTranslation, CreateRemoteTranslation
|
||||
from app.services.translation import TranslationCreator
|
||||
from app.depends import check_token
|
||||
from app.models import Translation as TranslationDB
|
||||
from app.serializers.translation import (
|
||||
Translation,
|
||||
CreateTranslation,
|
||||
CreateRemoteTranslation,
|
||||
)
|
||||
from app.services.translation import TranslationCreator
|
||||
from app.utils.pagination import CustomPage
|
||||
|
||||
|
||||
translation_router = APIRouter(
|
||||
@@ -19,23 +23,27 @@ translation_router = APIRouter(
|
||||
)
|
||||
|
||||
|
||||
@translation_router.get("/", response_model=CustomPage[Translation], dependencies=[Depends(Params)])
|
||||
@translation_router.get(
|
||||
"/", response_model=CustomPage[Translation], dependencies=[Depends(Params)]
|
||||
)
|
||||
async def get_translations():
|
||||
return await paginate(
|
||||
TranslationDB.objects.prefetch_related(["book", "author"])
|
||||
)
|
||||
return await paginate(TranslationDB.objects.prefetch_related(["book", "author"]))
|
||||
|
||||
|
||||
@translation_router.post("/", response_model=Translation)
|
||||
async def create_translation(data: Union[CreateTranslation, CreateRemoteTranslation]):
|
||||
translation = await TranslationCreator.create(data)
|
||||
|
||||
return await TranslationDB.objects.prefetch_related(["book", "author"]).get(id=translation.id)
|
||||
return await TranslationDB.objects.prefetch_related(["book", "author"]).get(
|
||||
id=translation.id
|
||||
)
|
||||
|
||||
|
||||
@translation_router.delete("/{id}", response_model=Translation)
|
||||
async def delete_translation(id: int):
|
||||
translation = await TranslationDB.objects.prefetch_related(["book", "author"]).get_or_none(id=id)
|
||||
translation = await TranslationDB.objects.prefetch_related(
|
||||
["book", "author"]
|
||||
).get_or_none(id=id)
|
||||
|
||||
if translation is None:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi_pagination import add_pagination
|
||||
import aioredis
|
||||
|
||||
from core.db import database
|
||||
from core.config import env_config
|
||||
import aioredis
|
||||
from fastapi_pagination import add_pagination
|
||||
|
||||
from app.views import routers
|
||||
from core.config import env_config
|
||||
from core.db import database
|
||||
|
||||
|
||||
def start_app() -> FastAPI:
|
||||
@@ -25,13 +25,13 @@ def start_app() -> FastAPI:
|
||||
|
||||
add_pagination(app)
|
||||
|
||||
@app.on_event('startup')
|
||||
@app.on_event("startup")
|
||||
async def startup() -> None:
|
||||
database_ = app.state.database
|
||||
if not database_.is_connected:
|
||||
await database_.connect()
|
||||
|
||||
@app.on_event('shutdown')
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown() -> None:
|
||||
database_ = app.state.database
|
||||
if database_.is_connected:
|
||||
|
||||
@@ -18,8 +18,8 @@ class EnvConfig(BaseSettings):
|
||||
REDIS_PASSWORD: Optional[str]
|
||||
|
||||
class Config:
|
||||
env_file = '.env'
|
||||
env_file_encoding = 'utf-8'
|
||||
env_file = ".env"
|
||||
env_file_encoding = "utf-8"
|
||||
|
||||
|
||||
env_config = EnvConfig()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from urllib.parse import quote
|
||||
from databases import Database
|
||||
|
||||
from databases import Database
|
||||
from sqlalchemy import MetaData
|
||||
|
||||
from core.config import env_config
|
||||
|
||||
Reference in New Issue
Block a user