Compare commits

...

4 Commits

12 changed files with 143 additions and 95 deletions

View File

@ -6,43 +6,20 @@ from fastfood.routers.dish import router as dish_router
from fastfood.routers.menu import router as menu_router
from fastfood.routers.submenu import router as submenu_router
tags_metadata = [
{
'name': 'menu',
'description': 'Операции с меню.',
},
{
'name': 'submenu',
'description': 'Подменю и работа с ним',
},
{'name': 'dish', 'description': 'Блюда и работа с ними'},
]
def create_app(redis=None) -> FastAPI:
def create_app() -> FastAPI:
"""
Фабрика FastAPI.
"""
with open('openapi.json') as f:
js = json.load(f)
app = FastAPI(
title=js['info']['title'],
description=js['info']['description'],
version=js['info']['version'],
contact={
'name': 'Sergey Vanyushkin',
'url': 'http://pi3c.ru',
'email': 'pi3c@yandex.ru',
},
license_info={
'name': 'MIT license',
'url': 'https://mit-license.org/',
},
openapi_tags=tags_metadata,
)
app = FastAPI()
app.include_router(menu_router)
app.include_router(submenu_router)
app.include_router(dish_router)
def custom_openapi():
with open('openapi.json') as openapi:
return json.load(openapi)
app.openapi = custom_openapi
return app

View File

@ -10,7 +10,7 @@ from fastfood.schemas import Dish_db
class DishRepository:
def __init__(self, session: AsyncSession = Depends(get_async_session)):
def __init__(self, session: AsyncSession = Depends(get_async_session)) -> None:
self.db = session
async def get_dishes(self, menu_id: UUID, submenu_id: UUID) -> list[Dish]:
@ -49,21 +49,20 @@ class DishRepository:
submenu_id: UUID,
dish_id: UUID,
dish_data: Dish_db,
) -> Dish:
) -> Dish | None:
query = update(Dish).where(Dish.id == dish_id).values(**dish_data.model_dump())
await self.db.execute(query)
await self.db.commit()
qr = select(Dish).where(Dish.id == dish_id)
updated_submenu = await self.db.execute(qr)
return updated_submenu.scalars().one()
return updated_submenu.scalar_one_or_none()
async def delete_dish_item(
self,
menu_id: UUID,
submenu_id: UUID,
dish_id: UUID,
) -> int:
) -> None:
query = delete(Dish).where(Dish.id == dish_id)
await self.db.execute(query)
await self.db.commit()
return 200

View File

@ -11,7 +11,7 @@ from fastfood.models import Dish, Menu, SubMenu
class MenuRepository:
def __init__(self, session: AsyncSession = Depends(get_async_session)):
def __init__(self, session: AsyncSession = Depends(get_async_session)) -> None:
self.db = session
async def get_menus(self) -> list[Menu]:
@ -44,23 +44,21 @@ class MenuRepository:
)
menu = await self.db.execute(query)
menu = menu.scalars().one_or_none()
if menu is None:
return None
return menu
async def update_menu_item(
self,
menu_id: UUID,
menu: schemas.MenuBase,
) -> Menu:
) -> Menu | None:
query = update(Menu).where(Menu.id == menu_id).values(**menu.model_dump())
await self.db.execute(query)
await self.db.commit()
qr = select(Menu).where(Menu.id == menu_id)
updated_menu = await self.db.execute(qr)
return updated_menu.scalar_one()
return updated_menu.scalar_one_or_none()
async def delete_menu_item(self, menu_id: UUID):
async def delete_menu_item(self, menu_id: UUID) -> None:
query = delete(Menu).where(Menu.id == menu_id)
await self.db.execute(query)
await self.db.commit()

View File

@ -31,7 +31,7 @@ class RedisRepository:
pool: redis.Redis = Depends(get_redis_pool),
) -> None:
self.pool = pool
self.ttl = 2
self.ttl = 1800
async def get(self, key: str) -> Any | None:
data = await self.pool.get(key)

View File

@ -11,7 +11,7 @@ from fastfood.schemas import MenuBase
class SubMenuRepository:
def __init__(self, session: AsyncSession = Depends(get_async_session)):
def __init__(self, session: AsyncSession = Depends(get_async_session)) -> None:
self.db = session
async def get_submenus(self, menu_id: UUID) -> list[SubMenu]:
@ -52,8 +52,6 @@ class SubMenuRepository:
)
submenu = await self.db.execute(query)
submenu = submenu.scalars().one_or_none()
if submenu is None:
return None
return submenu
async def update_submenu_item(
@ -61,7 +59,7 @@ class SubMenuRepository:
menu_id: UUID,
submenu_id: UUID,
submenu_data: MenuBase,
) -> SubMenu:
) -> SubMenu | None:
query = (
update(SubMenu)
.where(SubMenu.id == submenu_id)
@ -71,12 +69,11 @@ class SubMenuRepository:
await self.db.commit()
qr = select(SubMenu).where(SubMenu.id == submenu_id)
updated_submenu = await self.db.execute(qr)
return updated_submenu.scalar_one()
return updated_submenu.scalar_one_or_none()
async def delete_submenu_item(self, menu_id: UUID, submenu_id: UUID) -> int:
async def delete_submenu_item(self, menu_id: UUID, submenu_id: UUID) -> None:
query = delete(SubMenu).where(
SubMenu.id == submenu_id,
)
await self.db.execute(query)
await self.db.commit()
return 200

View File

@ -11,7 +11,10 @@ router = APIRouter(
)
@router.get('/', response_model=list[Dish])
@router.get(
'/',
response_model=list[Dish],
)
async def get_dishes(
menu_id: UUID,
submenu_id: UUID,
@ -22,14 +25,18 @@ async def get_dishes(
return result
@router.post('/', status_code=201, response_model=Dish)
@router.post(
'/',
status_code=201,
response_model=Dish,
)
async def create_dish(
menu_id: UUID,
submenu_id: UUID,
dish_data: DishBase,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> Dish:
return await dish.create_dish(
menu_id,
submenu_id,
@ -37,25 +44,34 @@ async def create_dish(
)
@router.get('/{dish_id}', response_model=Dish)
@router.get(
'/{dish_id}',
response_model=Dish,
)
async def get_dish(
menu_id: UUID,
submenu_id: UUID,
dish_id: UUID,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> Dish | None:
result = await dish.read_dish(
menu_id,
submenu_id,
dish_id,
)
if not result:
raise HTTPException(status_code=404, detail='dish not found')
raise HTTPException(
status_code=404,
detail=f'Блюдо c UUID={dish_id} не существует, доступ невозможен',
)
return result
@router.patch('/{dish_id}', response_model=Dish)
@router.patch(
'/{dish_id}',
response_model=Dish,
)
async def update_dish(
menu_id: UUID,
submenu_id: UUID,
@ -63,22 +79,29 @@ async def update_dish(
dish_data: DishBase,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> Dish:
result = await dish.update_dish(
menu_id,
submenu_id,
dish_id,
dish_data,
)
if not result:
raise HTTPException(
status_code=404,
detail=f'Блюдо c UUID={dish_id} не существует, обновление невозможно',
)
return result
@router.delete('/{dish_id}')
@router.delete(
'/{dish_id}',
)
async def delete_dish(
menu_id: UUID,
submenu_id: UUID,
dish_id: UUID,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> None:
await dish.del_dish(menu_id, submenu_id, dish_id)

View File

@ -11,54 +11,80 @@ router = APIRouter(
)
@router.get('/', response_model=list[MenuRead])
@router.get(
'/',
status_code=200,
response_model=list[MenuRead],
)
async def get_menus(
menu: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> list[MenuRead]:
return await menu.read_menus()
@router.post('/', status_code=201, response_model=MenuRead)
@router.post(
'/',
status_code=201,
response_model=MenuRead,
)
async def add_menu(
menu: MenuBase,
responce: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> MenuRead:
return await responce.create_menu(menu)
@router.get('/{menu_id}', response_model=MenuRead)
@router.get(
'/{menu_id}',
response_model=MenuRead,
)
async def get_menu(
menu_id: UUID,
responce: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> MenuRead:
result = await responce.read_menu(menu_id=menu_id)
if not result:
raise HTTPException(status_code=404, detail='menu not found')
raise HTTPException(
status_code=404,
detail=f'Меню c UUID={menu_id} не существует, доступ невозможен',
)
return result
@router.patch('/{menu_id}', response_model=MenuRead)
@router.patch(
'/{menu_id}',
response_model=MenuRead,
)
async def update_menu(
menu_id: UUID,
menu: MenuBase,
responce: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> MenuRead:
result = await responce.update_menu(
menu_id=menu_id,
menu_data=menu,
)
if not result:
raise HTTPException(
status_code=404,
detail=f'Меню c UUID={menu_id} не существует, Обновление невозможно',
)
return result
@router.delete('/{menu_id}')
@router.delete(
'/{menu_id}',
status_code=200,
)
async def delete_menu(
menu_id: UUID,
menu: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> None:
await menu.del_menu(menu_id)

View File

@ -11,23 +11,30 @@ router = APIRouter(
)
@router.get('/', response_model=list[SubMenuRead])
@router.get(
'/',
response_model=list[SubMenuRead],
)
async def get_submenus(
menu_id: UUID,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> list[SubMenuRead]:
result = await submenu.read_submenus(menu_id=menu_id)
return result
@router.post('/', status_code=201, response_model=SubMenuRead)
@router.post(
'/',
status_code=201,
response_model=SubMenuRead,
)
async def create_submenu_item(
menu_id: UUID,
submenu_data: MenuBase,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> SubMenuRead:
result = await submenu.create_submenu(
menu_id=menu_id,
submenu_data=submenu_data,
@ -35,19 +42,25 @@ async def create_submenu_item(
return result
@router.get('/{submenu_id}', response_model=SubMenuRead)
@router.get(
'/{submenu_id}',
response_model=SubMenuRead,
)
async def get_submenu(
menu_id: UUID,
submenu_id: UUID,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> SubMenuRead:
result = await submenu.read_menu(
menu_id=menu_id,
submenu_id=submenu_id,
)
if not result:
raise HTTPException(status_code=404, detail='submenu not found')
raise HTTPException(
status_code=404,
detail=f'Подменю c UUID={submenu_id} не существует, доступ невозможен',
)
return result
@ -61,20 +74,28 @@ async def update_submenu(
submenu_data: MenuBase,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> SubMenuRead:
result = await submenu.update_submenu(
menu_id=menu_id,
submenu_id=submenu_id,
submenu_data=submenu_data,
)
if not result:
raise HTTPException(
status_code=404,
detail=f'Gjlvеню c UUID={submenu_id} не существует, обновление невозможно',
)
return result
@router.delete('/{submenu_id}')
@router.delete(
'/{submenu_id}',
)
async def delete_submenu(
menu_id: UUID,
submenu_id: UUID,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
) -> None:
await submenu.del_menu(menu_id=menu_id, submenu_id=submenu_id)

View File

@ -103,14 +103,19 @@ class DishService:
async def update_dish(
self, menu_id: UUID, submenu_id: UUID, dish_id, dish_data: DishBase
) -> Dish:
) -> Dish | None:
dish_db = Dish_db(**dish_data.model_dump())
data = await self.dish_repo.update_dish_item(
menu_id, submenu_id, dish_id, dish_db
)
if data is None:
return None
dish = data.__dict__
dish['price'] = str(dish['price'])
dish = Dish(**dish)
await self.cache.set(
self.key(
'dish',
@ -125,13 +130,11 @@ class DishService:
return dish
async def del_dish(self, menu_id: UUID, submenu_id: UUID, dish_id: UUID) -> int:
response = await self.dish_repo.delete_dish_item(
async def del_dish(self, menu_id: UUID, submenu_id: UUID, dish_id: UUID) -> None:
await self.dish_repo.delete_dish_item(
menu_id,
submenu_id,
dish_id,
)
await self.cache.delete(key=str(menu_id), bg_task=self.bg_tasks)
await self.cache.invalidate(key=str(menu_id), bg_task=self.bg_tasks)
return response

View File

@ -87,8 +87,10 @@ class MenuService:
)
return menu
async def update_menu(self, menu_id: UUID, menu_data) -> MenuRead:
async def update_menu(self, menu_id: UUID, menu_data) -> MenuRead | None:
data = await self.menu_repo.update_menu_item(menu_id, menu_data)
if data is None:
return None
menu = data.__dict__
menu = {k: v for k, v in menu.items() if not k.startswith('_')}
dishes_conter = 0
@ -104,8 +106,7 @@ class MenuService:
await self.cache.invalidate(key=str(menu_id), bg_task=self.bg_tasks)
return menu
async def del_menu(self, menu_id: UUID):
data = await self.menu_repo.delete_menu_item(menu_id)
async def del_menu(self, menu_id: UUID) -> None:
await self.menu_repo.delete_menu_item(menu_id)
await self.cache.delete(key=str(menu_id), bg_task=self.bg_tasks)
await self.cache.invalidate(key=str(menu_id), bg_task=self.bg_tasks)
return data

View File

@ -89,14 +89,18 @@ class SubmenuService:
async def update_submenu(
self, menu_id: UUID, submenu_id: UUID, submenu_data: MenuBase
) -> SubMenuRead:
) -> SubMenuRead | None:
data = await self.submenu_repo.update_submenu_item(
menu_id, submenu_id, submenu_data
)
if data is None:
return None
submenu = data.__dict__
submenu = {k: v for k, v in submenu.items() if not k.startswith('_')}
submenu['dishes_count'] = len(submenu.pop('dishes'))
submenu = SubMenuRead(**submenu)
await self.cache.set(
self.key('submenu', menu_id=str(menu_id), submenu_id=str(submenu_id)),
submenu,
@ -106,8 +110,8 @@ class SubmenuService:
return submenu
async def del_menu(self, menu_id: UUID, submenu_id: UUID) -> int:
code = await self.submenu_repo.delete_submenu_item(menu_id, submenu_id)
async def del_menu(self, menu_id: UUID, submenu_id: UUID) -> None:
await self.submenu_repo.delete_submenu_item(menu_id, submenu_id)
await self.cache.delete(
key=self.key(
'submenu',
@ -117,4 +121,3 @@ class SubmenuService:
bg_task=self.bg_tasks,
)
await self.cache.invalidate(key=str(menu_id), bg_task=self.bg_tasks)
return code

File diff suppressed because one or more lines are too long