Добавлены базы и роуты для Серверов и Баз Данных

This commit is contained in:
2024-10-23 16:53:57 +09:00
parent 505e1b1377
commit 6fece6d096
22 changed files with 783 additions and 29 deletions

9
core/__init__.py Normal file
View File

@ -0,0 +1,9 @@
__all__ = (
"settings",
"db_helper",
"Base"
)
from .settings import settings
from .db_helper import db_helper
from .base import Base
from .models import *

6
core/base.py Normal file
View File

@ -0,0 +1,6 @@
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import MetaData
from core.settings import settings
class Base(DeclarativeBase):
__abstract__ = True
metadata = MetaData(naming_convention=settings.database.convention)

0
core/crud/__init__.py Normal file
View File

53
core/crud/databases.py Normal file
View File

@ -0,0 +1,53 @@
from ..models import Database
from ..schemas import DatabaseBase, DatabaseSchema
from sqlalchemy import select, delete
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Sequence, Optional, List
async def get_all(
session: AsyncSession
) -> Sequence[DatabaseSchema]:
stmt = select(Database).order_by(Database.id)
result = await session.scalars(stmt)
return result.all()
async def get(
session: AsyncSession,
id: int
) -> DatabaseSchema:
db_login = await session.get(Database,id)
if db_login is None:
return None
return db_login
async def create(
session:AsyncSession,
model: DatabaseBase
) -> DatabaseSchema:
login = Database(**model.model_dump())
session.add(login)
await session.commit()
return login
async def delete(
session: AsyncSession,
id: int
):
db_login = await session.get(Database,id)
if db_login is None:
return None
stmt = delete(Database).filter(Database.id == id)
await session.execute(stmt)
await session.commit()
async def update(
session:AsyncSession,
id: int,
model: DatabaseBase
) -> DatabaseSchema:
db_login = await session.get(Database,id)
if db_login is None:
return None
for var, value in vars(model).items():
setattr(db_login, var, value) if value else None
await session.commit()
return db_login

53
core/crud/servers.py Normal file
View File

@ -0,0 +1,53 @@
from ..models import Server
from ..schemas import ServerBase, ServerSchema
from sqlalchemy import select, delete
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Sequence, Optional, List
async def get_all(
session: AsyncSession
) -> Sequence[ServerSchema]:
stmt = select(Server).order_by(Server.id)
result = await session.scalars(stmt)
return result.all()
async def get(
session: AsyncSession,
id: int
) -> ServerSchema:
db_login = await session.get(Server,id)
if db_login is None:
return None
return db_login
async def create(
session:AsyncSession,
model: ServerBase
) -> ServerSchema:
login = Server(**model.model_dump())
session.add(login)
await session.commit()
return login
async def delete(
session: AsyncSession,
id: int
):
db_login = await session.get(Server,id)
if db_login is None:
return None
stmt = delete(Server).filter(Server.id == id)
await session.execute(stmt)
await session.commit()
async def update(
session:AsyncSession,
id: int,
model: ServerBase
) -> ServerSchema:
db_login = await session.get(Server,id)
if db_login is None:
return None
for var, value in vars(model).items():
setattr(db_login, var, value) if value else None
await session.commit()
return db_login

46
core/db_helper.py Normal file
View File

@ -0,0 +1,46 @@
from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine, async_sessionmaker, AsyncSession
from typing import AsyncGenerator
from core.settings import settings
class DatabaseHelper:
def __init__(
self,
url: str,
echo:bool=False,
echo_pool:bool=False,
pool_size: int = 5,
max_overflow: int =10,
) -> None:
try:
self.engine: AsyncEngine = create_async_engine(
url=url,
echo=echo,
echo_pool=echo_pool,
pool_size=pool_size,
max_overflow = max_overflow
)
except TypeError:
# The pool_size argument won't work for the default SQLite setup in SQLAlchemy 0.7, try without
self.engine: AsyncEngine = create_async_engine(url=url)
self.session_factory: async_sessionmaker[AsyncSession] = async_sessionmaker(
bind= self.engine,
autoflush=False,
autocommit=False,
expire_on_commit=False
)
async def dispose(self) -> None:
await self.engine.dispose()
async def session_getter(self) -> AsyncGenerator[AsyncSession,None]:
async with self.session_factory() as session:
yield session
db_helper = DatabaseHelper(
url = settings.database.url,
echo = settings.database.echo,
echo_pool = settings.database.echo_pool,
pool_size = settings.database.pool_size,
max_overflow = settings.database.max_overflow,
)

20
core/models.py Normal file
View File

@ -0,0 +1,20 @@
from .base import Base
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy import func
from sqlalchemy import String, Integer, Boolean, ForeignKey, DateTime
from datetime import date, datetime
class Server(Base):
__tablename__ = "easy_servers"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
name:Mapped[str] = mapped_column(String(255), nullable=False, unique=True)
description: Mapped[str | None] = mapped_column(String(1000), nullable=True)
url: Mapped[str] = mapped_column(String(1000), nullable=False, unique=False)
class Database(Base):
__tablename__ = "easy_databases"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
name:Mapped[str] = mapped_column(String(255), nullable=False, unique=True)
description: Mapped[str | None] = mapped_column(String(1000), nullable=True)
date_created: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, default= func.now())
server_id: Mapped[int] = mapped_column(Integer, ForeignKey("easy_servers.id"))

10
core/router.py Normal file
View File

@ -0,0 +1,10 @@
from fastapi import APIRouter
from .routers.servers import router as server_router
router = APIRouter(
tags=["Core"],
prefix="/core",
)
router.include_router(
router=server_router,
)

0
core/routers/__init__.py Normal file
View File

40
core/routers/servers.py Normal file
View File

@ -0,0 +1,40 @@
from fastapi import APIRouter, Depends
from ..crud.servers import get, get_all,delete,update, create
from typing import Annotated, Sequence
from sqlalchemy.ext.asyncio import AsyncSession
from ..db_helper import db_helper
from ..schemas import ServerBase, ServerSchema
router = APIRouter( tags=["Server"], prefix="/server")
@router.get("/", response_model=Sequence[ServerSchema])
async def get_all_server(session: Annotated[AsyncSession, Depends(db_helper.session_getter)]):
return await get_all(session)
@router.get("/{id}", response_model=ServerSchema)
async def get_server(session: Annotated[AsyncSession, Depends(db_helper.session_getter)],id:int):
return await get(session,id)
@router.post("/", response_model=ServerSchema)
async def create_server(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)],
model: ServerBase
):
login = await create(
session=session,
model=model
)
return login
@router.patch("/{id}", response_model=ServerSchema)
async def update_server(
session: Annotated[AsyncSession, Depends(db_helper.session_getter)],
id: int,
model: ServerBase
):
login = await update(
session=session,
id=id,
model=model
)
return login

19
core/schemas.py Normal file
View File

@ -0,0 +1,19 @@
from pydantic import BaseModel
from datetime import datetime
class ServerBase(BaseModel):
name:str
description: str | None
url: str
class ServerSchema(ServerBase):
id: int
class DatabaseBase(BaseModel):
name:str
description: str | None
date_created: datetime | None
server_id: int
class DatabaseSchema(DatabaseBase):
id: int

36
core/settings.py Normal file
View File

@ -0,0 +1,36 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import BaseModel
class UvicornSettings(BaseModel):
host: str = "0.0.0.0"
port: int = 8000
reload: bool = True
class DatabaseSettings(BaseModel):
url: str
echo:bool=False
echo_pool:bool=False
pool_size: int = 50
max_overflow: int =10
convention:dict = {
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
case_sensitive=False,
env_nested_delimiter="__",
env_prefix="APP_CONFIG__"
)
database: DatabaseSettings
uvicorn: UvicornSettings = UvicornSettings()
settings = Settings()
print(settings.database.url)