diff --git a/.gitignore b/.gitignore index 9bf9036..d65606d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ content/* -dev_database.db +dev_database*.db run.bat # Byte-compiled / optimized / DLL files diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..dc3f727 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.analysis.typeCheckingMode": "basic" +} diff --git a/database/crud/games.py b/database/crud/games.py index d353c88..ca9be8b 100644 --- a/database/crud/games.py +++ b/database/crud/games.py @@ -17,9 +17,22 @@ async def add_game(db: AsyncSession, return await add_transaction(db, game) +async def edit_game(db: AsyncSession, + game_id: int, + game_info: sch.GameCreate): + game = await db.get(mdl.Game, game_id) + game_fields = [c.name for c in mdl.Game.__table__.columns] + new_game_info = { + **{k: v for k, v in vars(game).items() if k in game_fields}, + **game_info.model_dump()} + print(game_fields, new_game_info) + game = mdl.Game(**new_game_info) + await db.commit() + return 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) + async def get_game(db: AsyncSession, game_id: int): + return await db.get(mdl.Game, game_id) diff --git a/database/database.py b/database/database.py index 8e37b57..4b17b45 100644 --- a/database/database.py +++ b/database/database.py @@ -15,7 +15,7 @@ Base = declarative_base() async def get_session() -> AsyncSession: # type: ignore async with async_session() as session: # type: ignore - yield session + yield session # type: ignore async def drop_all(): diff --git a/database/schemas/games.py b/database/schemas/games.py index a3d0039..d262cc3 100644 --- a/database/schemas/games.py +++ b/database/schemas/games.py @@ -1,33 +1,43 @@ from typing import Optional -from pydantic import BaseModel +from fastapi import Body +from pydantic import BaseModel, ConfigDict, Field class GameCardBase(BaseModel): - title: str - cover: Optional[str] = None - description: Optional[str] = None - version: Optional[str] = None + title: str = Field(examples=["DwarfFortress", "RimWorld"]) + cover: Optional[str] = \ + Field(default=None, examples=["cover_filename.jpg"]) + description: Optional[str] = \ + Field(default=None, + examples=["Dwarf Fortress - это игра, которая" + " находится в стадии разработки уже" + " довольно долгое время, но уже собрала" + " большую базу поклонников и довольно хорошие отзывы"]) + version: Optional[str] = \ + Field(default=None, examples=["50.08 (Steam edition)"]) class GameCard(GameCardBase): - id: int + id: int = Field(examples=[1]) class GameBase(GameCardBase): - torrent_file: str - trailer: Optional[str] = None + torrent_file: str = Field(examples=["torrent_filename.torrent"]) + trailer: Optional[str] = \ + Field(default=None, examples=[ + "https://www.youtube.com/watch?v=xawsp16oxb0"]) - system: Optional[str] = None - processor: Optional[str] = None - memory: Optional[str] = None - graphics: Optional[str] = None - storage: Optional[str] = None - - developer: Optional[str] = None - language: Optional[str] = None - release_date: Optional[str] = None - download_size: Optional[str] = None + system: Optional[str] = Field(default=None, examples=["Windows"]) + processor: Optional[str] = \ + Field(default=None, examples=["Любой (от 2Ghz)"]) + memory: Optional[str] = Field(default=None, examples=["512Mb"]) + graphics: Optional[str] = Field(default=None, examples=["Любая"]) + storage: Optional[str] = Field(default=None, examples=["100Mb"]) + developer: Optional[str] = Field(default=None, examples=["Bay12Games"]) + language: Optional[str] = Field(default=None, examples=["eng/рус"]) + release_date: Optional[str] = Field(default=None, examples=["2014"]) + download_size: Optional[str] = Field(default=None, examples=["80Mb"]) class GameCreate(GameBase): @@ -35,10 +45,9 @@ class GameCreate(GameBase): class Game(GameBase): - id: int - update_date: str - upload_date: str - owner_id: int + id: int = Field(examples=[1]) + update_date: str = Field(examples=["2024-05-13 12:00:00"]) + upload_date: str = Field(examples=["2024-05-13 12:00:00"]) + owner_id: int = Field(examples=[1]) - class Config: - from_attributes = True + model_config = ConfigDict(from_attributes=True) diff --git a/main.py b/main.py index 4d233cf..2ab1b42 100644 --- a/main.py +++ b/main.py @@ -5,7 +5,14 @@ import typer import cli_commands from routes import * -app = FastAPI() +app = FastAPI( + title=".Torrent", + description=".Torrent - сервис обмена .torrent файлами видеоигр, фильмов и аудиокниг", + contact={ + "name": "Платон (разработчик)", + "url": "https://github.com/StepanovPlaton" + }, +) app.include_router(startup_router) app.include_router(games_router) app.include_router(files_router) diff --git a/routes/games.py b/routes/games.py index 5afa148..1b976e8 100644 --- a/routes/games.py +++ b/routes/games.py @@ -1,37 +1,36 @@ -from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.ext.asyncio import AsyncSession +from fastapi import APIRouter, Depends -from database import * +import database as db from file_handler import * games_router = APIRouter(prefix="/games", tags=["Games"]) -@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: - raise HTTPException(500) +@games_router.get("/", response_model=list[db.Game]) +async def get_games(db_session: AsyncSession = Depends(db.get_session)): + return await db.get_games(db_session) -@games_router.get("/cards", response_model=list[GameCard]) -async def get_games_cards(db: AsyncSession = Depends(get_session)): - try: - return await crud.get_games(db) - except Exception: - raise HTTPException(500) +@games_router.get("/cards", response_model=list[db.GameCard]) +async def get_games_cards(db_session: AsyncSession = Depends(db.get_session)): + return await db.get_games(db_session) -@games_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) +@games_router.get("/{game_id}", response_model=db.Game) +async def get_game(game_id: int, db_session: AsyncSession = Depends(db.get_session)): + return await db.get_game(db_session, game_id) -@games_router.post("/", response_model=Game) -async def add_game(game: GameCreate, +@games_router.put("/{game_id}", response_model=db.Game) +async def edit_game(game_id: int, + game: db.GameCreate, + db_session: AsyncSession = Depends(db.get_session)): + return await db.edit_game(db_session, game_id, game) + + +@games_router.post("/", response_model=db.Game) +async def add_game(game: db.GameCreate, user_id: int, - db: AsyncSession = Depends(get_session)): - try: - return await crud.add_game(db, game, user_id) - except Exception: - raise HTTPException(500) + db_session: AsyncSession = Depends(db.get_session)): + return await db.add_game(db_session, game, user_id)