From f6c39cea05df3573c15a2317de13e4eda0c246ce Mon Sep 17 00:00:00 2001 From: pi3c Date: Sun, 21 Jan 2024 08:12:51 +0300 Subject: [PATCH] =?UTF-8?q?Api=20=D0=B4=D0=BB=D1=8F=20=D0=B1=D0=BB=D1=8E?= =?UTF-8?q?=D0=B4.=20Test=20OK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastfood/crud.py | 51 +++++++++++++++++++++++++- fastfood/models.py | 25 ++++++------- fastfood/routes.py | 87 ++++++++++++++++++++++++++++++++++++++++----- fastfood/schemas.py | 16 ++++----- 4 files changed, 145 insertions(+), 34 deletions(-) diff --git a/fastfood/crud.py b/fastfood/crud.py index 90dc132..f886bb3 100644 --- a/fastfood/crud.py +++ b/fastfood/crud.py @@ -65,7 +65,7 @@ class Crud: @staticmethod async def create_submenu_item( - menu_id: UUID, submenu: schemas.SubmenuBase, session: AsyncSession, + menu_id: UUID, submenu: schemas.MenuBase, session: AsyncSession, ): async with session: new_submenu = models.SubMenu(**submenu.model_dump()) @@ -105,4 +105,53 @@ class Crud: await session.execute(query) await session.commit() + @staticmethod + async def get_dishes(submenu_id: UUID, session: AsyncSession): + async with session: + query = select(models.Dish).where(models.Dish.parent_submenu == submenu_id) + dishes = await session.execute(query) + return dishes.scalars().all() + + @staticmethod + async def create_dish_item( + submenu_id: UUID, dish: schemas.DishBase, session: AsyncSession, + ): + async with session: + new_dish = models.Dish(**dish.model_dump()) + new_dish.parent_submenu = submenu_id + session.add(new_dish) + await session.flush() + await session.commit() + return new_dish + + @staticmethod + async def get_dish_item( + dish_id: UUID, session: AsyncSession, + ): + async with session: + query = select(models.Dish).where(models.Dish.id == dish_id) + submenu = await session.execute(query) + return submenu.scalars().one_or_none() + + @staticmethod + async def update_dish_item( + dish_id: UUID, + dish: schemas.DishBase, + session: AsyncSession, + ): + async with session: + query = update(models.Dish).where(models.Dish.id == dish_id).values(**dish.model_dump()) + await session.execute(query) + await session.commit() + qr = select(models.Dish).where(models.Dish.id == dish_id) + updated_submenu = await session.execute(qr) + return updated_submenu.scalars().one() + + @staticmethod + async def delete_dish_item(dish_id: UUID, session: AsyncSession): + async with session: + query = delete(models.Dish).where(models.Dish.id == dish_id) + await session.execute(query) + await session.commit() + diff --git a/fastfood/models.py b/fastfood/models.py index ba84495..14b3bff 100644 --- a/fastfood/models.py +++ b/fastfood/models.py @@ -18,33 +18,30 @@ str_25 = Annotated[str, 25] class Base(DeclarativeBase): - pass + id: Mapped[uuidpk] + title: Mapped[str_25] + description: Mapped[Optional[str]] class Menu(Base): __tablename__ = "menu" - id: Mapped[uuidpk] - title: Mapped[str_25] - description: Mapped[Optional[str]] - submenus: Mapped[List["SubMenu"]] = relationship("SubMenu", backref="menu", lazy='dynamic') + submenus: Mapped[List["SubMenu"]] = relationship( + "SubMenu", backref="menu", lazy='dynamic', cascade="all,delete", + ) class SubMenu(Base): __tablename__ = "submenu" - id: Mapped[uuidpk] - title: Mapped[str_25] - description: Mapped[Optional[str]] parent_menu: Mapped[uuid.UUID] = mapped_column(ForeignKey("menu.id")) - dishes: Mapped[List["Dish"]] = relationship() + dishes: Mapped[List["Dish"]] = relationship( + "Dish", backref="submenu", lazy="dynamic", cascade="all,delete", + ) class Dish(Base): __tablename__ = "dish" - id: Mapped[uuidpk] - title: Mapped[str_25] - description: Mapped[Optional[str]] - price: Mapped[Decimal] - parent_submenu: Mapped[UUID] = mapped_column(ForeignKey("submenu.id")) + price: Mapped[float] + parent_submenu: Mapped[uuid.UUID] = mapped_column(ForeignKey("submenu.id")) diff --git a/fastfood/routes.py b/fastfood/routes.py index bf6450a..95b2c6e 100644 --- a/fastfood/routes.py +++ b/fastfood/routes.py @@ -1,13 +1,13 @@ from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException -from sqlalchemy import insert, select from uuid import UUID from sqlalchemy.ext.asyncio import AsyncSession -from fastfood import models, schemas +from fastfood import schemas from fastfood.crud import Crud as crud from fastfood.dbase import get_async_session + router = APIRouter() @@ -36,7 +36,7 @@ async def get_menu( ): result = await crud.get_menu_item(menu_id=menu_id, session=session) if not result: - raise HTTPException(status_code=404, detail="menu not found") + raise HTTPException(status_code=404, detail="menu not found") return result @@ -46,12 +46,16 @@ async def update_menu( menu: schemas.MenuBase, session: AsyncSession = Depends(get_async_session), ): - result = await crud.update_menu_item(menu_id=menu_id, menu=menu, session=session) + result = await crud.update_menu_item( + menu_id=menu_id, menu=menu, session=session, + ) return result @router.delete("/api/v1/menus/{menu_id}") -async def delete_menu(menu_id: UUID, session: AsyncSession = Depends(get_async_session)): +async def delete_menu( + menu_id: UUID, session: AsyncSession = Depends(get_async_session), +): await crud.delete_menu_item(menu_id=menu_id, session=session) @@ -67,7 +71,7 @@ async def get_submenus( @router.post("/api/v1/menus/{menu_id}/submenus", status_code=201) async def create_submenu_item( menu_id: UUID, - submenu: schemas.SubmenuBase, + submenu: schemas.MenuBase, session: AsyncSession = Depends(get_async_session), ): result = await crud.create_submenu_item( @@ -88,11 +92,14 @@ async def get_submenu( menu_id=menu_id, submenu_id=submenu_id, session=session, ) if not result: - raise HTTPException(status_code=404, detail="submenu not found") + raise HTTPException(status_code=404, detail="submenu not found") return result -@router.patch("/api/v1/menus/{menu_id}/submenus/{submenu_id}", response_model=schemas.MenuBase) +@router.patch( + "/api/v1/menus/{menu_id}/submenus/{submenu_id}", + response_model=schemas.MenuBase, +) async def update_submenu( menu_id: UUID, submenu_id: UUID, @@ -106,5 +113,67 @@ async def update_submenu( @router.delete("/api/v1/menus/{menu_id}/submenus/{submenu_id}") -async def delete_menu(menu_id: UUID, submenu_id: UUID, session: AsyncSession = Depends(get_async_session)): +async def delete_submenu(menu_id: UUID, submenu_id: UUID, session: AsyncSession = Depends(get_async_session)): await crud.delete_submenu_item(submenu_id=submenu_id, session=session) + + +@router.get("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes") +async def get_dishes( + menu_id: UUID, + submenu_id: UUID, + session: AsyncSession = Depends(get_async_session) +): + result = await crud.get_dishes(submenu_id=submenu_id, session=session) + return result + + +@router.post("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes", status_code=201) +async def create_dish( + menu_id: UUID, + submenu_id: UUID, + dish: schemas.DishBase, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.create_dish_item( + submenu_id=submenu_id, + dish=dish, + session=session, + ) + return result + + +@router.get("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}") +async def get_dish( + menu_id: UUID, + submenu_id: UUID, + dish_id: UUID, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.get_dish_item( + dish_id=dish_id, session=session, + ) + if not result: + raise HTTPException(status_code=404, detail="dish not found") + return result + + +@router.patch( + "/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}", + response_model=schemas.DishBase, +) +async def update_submenu( + menu_id: UUID, + submenu_id: UUID, + dish_id: UUID, + dish: schemas.DishBase, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.update_dish_item( + dish_id=dish_id, dish=dish, session=session, + ) + return result + + +@router.delete("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}") +async def delete_dish(menu_id: UUID, submenu_id: UUID, dish_id: UUID, session: AsyncSession = Depends(get_async_session)): + await crud.delete_dish_item(dish_id=dish_id, session=session) diff --git a/fastfood/schemas.py b/fastfood/schemas.py index 00c6653..b30c5bc 100644 --- a/fastfood/schemas.py +++ b/fastfood/schemas.py @@ -8,22 +8,18 @@ from pydantic import BaseModel class MenuBase(BaseModel): title: str description: Optional[str] - + class Config: from_attributes = True class Menu(MenuBase): id: UUID - title: str - description: Optional[str] - # submenus: Optional[List[SubMenu]] - class Config: - from_attributes = True - -class SubmenuBase(MenuBase): +class DishBase(MenuBase): + price: str + + +class Dish(DishBase, Menu): pass - -