Add requirements, cli commands. New project structure

This commit is contained in:
2024-05-10 12:15:18 +04:00
parent e426c281b9
commit 698cca0aeb
12 changed files with 94 additions and 33 deletions

14
cli_commands.py Normal file
View File

@@ -0,0 +1,14 @@
from asyncio import run as aiorun
import typer
import database
cli = typer.Typer()
@cli.command(name="create")
def create_database(): aiorun(database.create_all())
@cli.command(name="drop")
def drop_database(): aiorun(database.drop_all())
@cli.command(name="recreate")
def recreate_database(): aiorun(database.recreate_all())

View File

@@ -1,3 +1,4 @@
from .crud import *
from .schemas import *
from .database import get_session, init_models
from .database import get_session, drop_all, create_all, recreate_all
from .crud import *

View File

@@ -1,8 +0,0 @@
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from .models import *
async def get_user(db: AsyncSession, user_id: int):
return await db.get(User, user_id)

View File

@@ -0,0 +1 @@
from .games import *

16
database/crud/games.py Normal file
View File

@@ -0,0 +1,16 @@
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from .. import models as mdl
from .. import schemas as sch
from ..database import add_transaction
async def add_game(db: AsyncSession, game_info: sch.GameCreate, user_id: int):
game = mdl.Game(**game_info.model_dump(), owner_id=user_id)
return await add_transaction(db, game)
async def get_games(db: AsyncSession):
return (await db.execute(select(mdl.Game))).scalars().all()
async def get_game(db: AsyncSession, game_id: int):
return await db.get(mdl.Game, game_id)

View File

@@ -19,8 +19,23 @@ async def get_session() -> AsyncSession: # type: ignore
async with async_session() as session: # type: ignore
yield session
async def init_models():
async def drop_all():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
async def create_all():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async def recreate_all():
await drop_all()
await create_all()
async def add_transaction[T](db: AsyncSession, entity: T) -> T:
try:
db.add(entity)
await db.commit()
await db.refresh(entity)
return entity
except Exception as ex:
await db.rollback()
raise ex

View File

@@ -1,5 +1,5 @@
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from .database import Base
@@ -9,8 +9,10 @@ class Game(Base):
__tablename__ = "games"
id = Column(Integer, primary_key=True)
title = Column(String)
cover = Column(String)
title = Column(String, nullable=False)
description = Column(String)
torrent_file = Column(String, nullable=False)
language = Column(String)
version = Column(String)
download_size = Column(String)
@@ -30,8 +32,8 @@ class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
email = Column(String, unique=True)
name = Column(String)
hash_of_password = Column(String)
email = Column(String, nullable=False, unique=True)
name = Column(String, nullable=False)
hash_of_password = Column(String, nullable=False)
games = relationship("Game", back_populates="owner")

View File

@@ -2,8 +2,10 @@ from pydantic import BaseModel
class GameBase(BaseModel):
cover: str | None = None
title: str
description: str | None = None
torrent_file: str
language: str | None = None
version: str | None = None
download_size: str | None = None
@@ -25,7 +27,7 @@ class Game(GameBase):
owner_id: int
class Config:
orm_mode = True
from_attributes = True
class UserBase(BaseModel):
@@ -42,4 +44,4 @@ class User(UserBase):
games: list[Game] = []
class Config:
orm_mode = True
from_attributes = True

22
main.py
View File

@@ -1,22 +1,14 @@
from typing import Union
from fastapi import Depends, FastAPI, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
import typer
from database import *
import cli_commands
from routes import *
app = FastAPI()
app.include_router(games_router)
cli = typer.Typer()
cli.add_typer(cli_commands.cli, name="database")
@app.on_event("startup")
async def startup_event():
await init_models()
@app.get("/users/{user_id}", response_model=User)
async def read_user(user_id: int, db: AsyncSession = Depends(get_session)):
db_user = await get_user(db, user_id=user_id)
print(db_user)
if db_user is None:
raise HTTPException(status_code=404, detail="User not found")
return db_user
if(__name__ == "__main__"): cli()

5
requirements.txt Normal file
View File

@@ -0,0 +1,5 @@
fastapi==0.111.0
pydantic==2.7.1
SQLAlchemy==2.0.30
aiosqlite==0.20.0
typer==0.12.3

1
routes/__init__.py Normal file
View File

@@ -0,0 +1 @@
from .games import router as games_router

20
routes/games.py Normal file
View File

@@ -0,0 +1,20 @@
from fastapi import APIRouter, Depends, HTTPException
from database import *
router = APIRouter(prefix="/games", tags=["Games"])
@router.get("/", response_model=list[Game])
async def get_games(db: AsyncSession = Depends(get_session)):
try: return await crud.get_games(db)
except Exception as ex: raise HTTPException(500)
@router.get("/{game_id}", response_model=Game)
async def get_game(game_id: int, db: AsyncSession = Depends(get_session)):
return await crud.get_game(db, game_id)
@router.post("/", response_model=Game)
async def add_game(game: GameCreate, user_id: int, db:AsyncSession = Depends(get_session)):
try: return await crud.add_game(db, game, user_id)
except Exception as ex: raise HTTPException(500)