mirror of
https://github.com/grillazz/fastapi-sqlalchemy-asyncpg.git
synced 2025-11-30 13:20:40 +03:00
refactor
This commit is contained in:
4
app/models/__init__.py
Normal file
4
app/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# for Alembic and unit tests
|
||||
from app.models.stuff import * # noqa
|
||||
from app.models.nonsense import * # noqa
|
||||
from app.models.shakespeare import * # noqa
|
||||
64
app/models/base.py
Normal file
64
app/models/base.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from typing import Any
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.ext.declarative import as_declarative, declared_attr
|
||||
|
||||
|
||||
@as_declarative()
|
||||
class BaseReadOnly:
|
||||
id: Any
|
||||
__name__: str
|
||||
# Generate __tablename__ automatically
|
||||
|
||||
@declared_attr
|
||||
def __tablename__(cls) -> str:
|
||||
return cls.__name__.lower()
|
||||
|
||||
|
||||
@as_declarative()
|
||||
class Base:
|
||||
id: Any
|
||||
__name__: str
|
||||
# Generate __tablename__ automatically
|
||||
|
||||
@declared_attr
|
||||
def __tablename__(cls) -> str:
|
||||
return cls.__name__.lower()
|
||||
|
||||
async def save(self, db_session: AsyncSession):
|
||||
"""
|
||||
|
||||
:param db_session:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
db_session.add(self)
|
||||
return await db_session.commit()
|
||||
except SQLAlchemyError as ex:
|
||||
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex))
|
||||
|
||||
async def delete(self, db_session: AsyncSession):
|
||||
"""
|
||||
|
||||
:param db_session:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
await db_session.delete(self)
|
||||
await db_session.commit()
|
||||
return True
|
||||
except SQLAlchemyError as ex:
|
||||
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex))
|
||||
|
||||
async def update(self, db_session: AsyncSession, **kwargs):
|
||||
"""
|
||||
|
||||
:param db_session:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
for k, v in kwargs.items():
|
||||
setattr(self, k, v)
|
||||
await self.save(db_session)
|
||||
42
app/models/nonsense.py
Normal file
42
app/models/nonsense.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import uuid
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import Column, String, select
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.base import Base
|
||||
|
||||
|
||||
class Nonsense(Base):
|
||||
__tablename__ = "nonsense"
|
||||
__table_args__ = (
|
||||
{"schema": "happy_hog"},
|
||||
)
|
||||
id = Column(UUID(as_uuid=True), unique=True, default=uuid.uuid4, autoincrement=True)
|
||||
name = Column(String, nullable=False, primary_key=True, unique=True)
|
||||
description = Column(String, nullable=False)
|
||||
|
||||
def __init__(self, name: str, description: str):
|
||||
self.name = name
|
||||
self.description = description
|
||||
|
||||
|
||||
@classmethod
|
||||
async def find(cls, db_session: AsyncSession, name: str):
|
||||
"""
|
||||
|
||||
:param db_session:
|
||||
:param name:
|
||||
:return:
|
||||
"""
|
||||
stmt = select(cls).where(cls.name == name)
|
||||
result = await db_session.execute(stmt)
|
||||
instance = result.scalars().first()
|
||||
if instance is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail={"Record not found": f"There is no record for requested name value : {name}"},
|
||||
)
|
||||
else:
|
||||
return instance
|
||||
134
app/models/shakespeare.py
Normal file
134
app/models/shakespeare.py
Normal file
@@ -0,0 +1,134 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
ForeignKey,
|
||||
ForeignKeyConstraint,
|
||||
Integer,
|
||||
PrimaryKeyConstraint,
|
||||
String,
|
||||
Table,
|
||||
Text,
|
||||
UniqueConstraint,
|
||||
select,
|
||||
)
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from app.models.base import Base
|
||||
|
||||
metadata = Base.metadata
|
||||
|
||||
|
||||
class Character(Base):
|
||||
__tablename__ = "character"
|
||||
__table_args__ = (PrimaryKeyConstraint("id", name="character_pkey"), {"schema": "shakespeare"})
|
||||
|
||||
id = Column(String(32))
|
||||
name = Column(String(64), nullable=False)
|
||||
speech_count = Column(Integer, nullable=False)
|
||||
abbrev = Column(String(32))
|
||||
description = Column(String(2056))
|
||||
|
||||
work = relationship("Work", secondary="shakespeare.character_work", back_populates="character")
|
||||
paragraph = relationship("Paragraph", back_populates="character")
|
||||
|
||||
|
||||
class Wordform(Base):
|
||||
__tablename__ = "wordform"
|
||||
__table_args__ = (PrimaryKeyConstraint("id", name="wordform_pkey"), {"schema": "shakespeare"})
|
||||
|
||||
id = Column(Integer)
|
||||
plain_text = Column(String(64), nullable=False)
|
||||
phonetic_text = Column(String(64), nullable=False)
|
||||
stem_text = Column(String(64), nullable=False)
|
||||
occurences = Column(Integer, nullable=False)
|
||||
|
||||
|
||||
class Work(Base):
|
||||
__tablename__ = "work"
|
||||
__table_args__ = (PrimaryKeyConstraint("id", name="work_pkey"), {"schema": "shakespeare"})
|
||||
|
||||
id = Column(String(32))
|
||||
title = Column(String(32), nullable=False)
|
||||
long_title = Column(String(64), nullable=False)
|
||||
year = Column(Integer, nullable=False)
|
||||
genre_type = Column(String(1), nullable=False)
|
||||
source = Column(String(16), nullable=False)
|
||||
total_words = Column(Integer, nullable=False)
|
||||
total_paragraphs = Column(Integer, nullable=False)
|
||||
notes = Column(Text)
|
||||
|
||||
character = relationship("Character", secondary="shakespeare.character_work", back_populates="work")
|
||||
chapter = relationship("Chapter", back_populates="work")
|
||||
paragraph = relationship("Paragraph", back_populates="work")
|
||||
|
||||
|
||||
class Chapter(Base):
|
||||
__tablename__ = "chapter"
|
||||
__table_args__ = (
|
||||
ForeignKeyConstraint(["work_id"], ["shakespeare.work.id"], name="chapter_work_id_fkey"),
|
||||
PrimaryKeyConstraint("id", name="chapter_pkey"),
|
||||
UniqueConstraint(
|
||||
"work_id", "section_number", "chapter_number", name="chapter_work_id_section_number_chapter_number_key"
|
||||
),
|
||||
{"schema": "shakespeare"},
|
||||
)
|
||||
|
||||
id = Column(Integer)
|
||||
work_id = Column(ForeignKey("shakespeare.work.id"), nullable=False)
|
||||
section_number = Column(Integer, nullable=False)
|
||||
chapter_number = Column(Integer, nullable=False)
|
||||
description = Column(String(256), nullable=False)
|
||||
|
||||
work = relationship("Work", back_populates="chapter")
|
||||
paragraph = relationship("Paragraph", back_populates="chapter")
|
||||
|
||||
|
||||
t_character_work = Table(
|
||||
"character_work",
|
||||
metadata,
|
||||
Column("character_id", ForeignKey("shakespeare.character.id"), nullable=False),
|
||||
Column("work_id", ForeignKey("shakespeare.work.id"), nullable=False),
|
||||
ForeignKeyConstraint(["character_id"], ["shakespeare.character.id"], name="character_work_character_id_fkey"),
|
||||
ForeignKeyConstraint(["work_id"], ["shakespeare.work.id"], name="character_work_work_id_fkey"),
|
||||
PrimaryKeyConstraint("character_id", "work_id", name="character_work_pkey"),
|
||||
schema="shakespeare",
|
||||
)
|
||||
|
||||
|
||||
class Paragraph(Base):
|
||||
__tablename__ = "paragraph"
|
||||
__table_args__ = (
|
||||
ForeignKeyConstraint(["character_id"], ["shakespeare.character.id"], name="paragraph_character_id_fkey"),
|
||||
ForeignKeyConstraint(
|
||||
["work_id", "section_number", "chapter_number"],
|
||||
["shakespeare.chapter.work_id", "shakespeare.chapter.section_number", "shakespeare.chapter.chapter_number"],
|
||||
name="paragraph_chapter_fkey",
|
||||
),
|
||||
ForeignKeyConstraint(["work_id"], ["shakespeare.work.id"], name="paragraph_work_id_fkey"),
|
||||
PrimaryKeyConstraint("id", name="paragraph_pkey"),
|
||||
{"schema": "shakespeare"},
|
||||
)
|
||||
|
||||
id = Column(Integer)
|
||||
work_id = Column(ForeignKey("shakespeare.work.id"), nullable=False)
|
||||
paragraph_num = Column(Integer, nullable=False)
|
||||
character_id = Column(ForeignKey("shakespeare.character.id"), nullable=False)
|
||||
plain_text = Column(Text, nullable=False)
|
||||
phonetic_text = Column(Text, nullable=False)
|
||||
stem_text = Column(Text, nullable=False)
|
||||
paragraph_type = Column(String(1), nullable=False)
|
||||
section_number = Column(Integer, nullable=False)
|
||||
chapter_number = Column(Integer, nullable=False)
|
||||
char_count = Column(Integer, nullable=False)
|
||||
word_count = Column(Integer, nullable=False)
|
||||
|
||||
character = relationship("Character", back_populates="paragraph", lazy="selectin")
|
||||
chapter = relationship("Chapter", back_populates="paragraph", lazy="selectin")
|
||||
work = relationship("Work", back_populates="paragraph", lazy="selectin")
|
||||
|
||||
@classmethod
|
||||
async def find(cls, db_session: AsyncSession, character: str):
|
||||
stmt = select(cls).join(Character).join(Chapter).join(Work).where(Character.name == character)
|
||||
result = await db_session.execute(stmt)
|
||||
instance = result.scalars().all()
|
||||
return instance
|
||||
41
app/models/stuff.py
Normal file
41
app/models/stuff.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import uuid
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import Column, String, select
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.base import Base
|
||||
|
||||
|
||||
class Stuff(Base):
|
||||
__tablename__ = "stuff"
|
||||
__table_args__ = (
|
||||
{"schema": "happy_hog"},
|
||||
)
|
||||
id = Column(UUID(as_uuid=True), unique=True, default=uuid.uuid4, autoincrement=True)
|
||||
name = Column(String, nullable=False, primary_key=True, unique=True)
|
||||
description = Column(String, nullable=False)
|
||||
|
||||
def __init__(self, name: str, description: str):
|
||||
self.name = name
|
||||
self.description = description
|
||||
|
||||
@classmethod
|
||||
async def find(cls, db_session: AsyncSession, name: str):
|
||||
"""
|
||||
|
||||
:param db_session:
|
||||
:param name:
|
||||
:return:
|
||||
"""
|
||||
stmt = select(cls).where(cls.name == name)
|
||||
result = await db_session.execute(stmt)
|
||||
instance = result.scalars().first()
|
||||
if instance is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail={"Not found": f"There is no record for name: {name}"},
|
||||
)
|
||||
else:
|
||||
return instance
|
||||
Reference in New Issue
Block a user