This commit is contained in:
2024-01-29 02:19:02 +03:00
parent cae407a5f4
commit bab8008ec8
9 changed files with 344 additions and 73 deletions

View File

@@ -4,10 +4,6 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
DB_HOST: str = "localhost"
DB_PORT: int = 5432
DB_USER: str = "postrges"
DB_PASS: str = "postgres"
DB_NAME: str = "postgres"
POSTGRES_DB: str = "fastfod_db"
POSTGRES_PASSWORD: str = "postgres"
POSTGRES_USER: str = "postgres"
@@ -18,8 +14,9 @@ class Settings(BaseSettings):
Возвращает строку подключения к БД необходимую для SQLAlchemy
"""
return (
f"postgresql+asyncpg://{self.DB_USER}:{self.DB_PASS}"
f"@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}"
"postgresql+asyncpg://"
f"{self.POSTGRES_USER}:{self.POSTGRES_PASSWORD}"
f"@{self.DB_HOST}:{self.DB_PORT}/{self.POSTGRES_DB}"
)
@property
@@ -28,11 +25,11 @@ class Settings(BaseSettings):
Возвращает строку подключения к БД необходимую для SQLAlchemy
"""
return (
f"postgresql+asyncpg://{self.DB_USER}:{self.DB_PASS}"
f"@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}_test"
"postgresql+asyncpg://"
f"{self.POSTGRES_USER}:{self.POSTGRES_PASSWORD}"
f"@{self.DB_HOST}:{self.DB_PORT}/{self.POSTGRES_DB}_test"
)
model_config = SettingsConfigDict(env_file=".env")

View File

@@ -1,8 +1,8 @@
from uuid import UUID
from sqlalchemy import delete, func, select, update
from sqlalchemy import delete, distinct, func, select, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Query, aliased
from sqlalchemy.orm import aliased
from fastfood import models, schemas
@@ -12,8 +12,8 @@ class MenuCrud:
async def get_menus(session: AsyncSession):
async with session:
query = select(models.Menu)
result = await session.execute(query)
return result.scalars().all()
menus = await session.execute(query)
return menus
@staticmethod
async def create_menu_item(menu: schemas.MenuBase, session: AsyncSession):
@@ -27,55 +27,25 @@ class MenuCrud:
@staticmethod
async def get_menu_item(menu_id: UUID, session: AsyncSession):
async with session:
""" Комментарий для проверяющего
То что было, оставил закоментированным, удалю в следующей части
в pgadmin набросал следующий запрос
WITH subq as (
SELECT
s.id,
s.title,
s.description,
s.parent_menu,
count(d.id) as dishes_count
FROM submenu s
JOIN dish d ON s.id = d.parent_submenu
GROUP BY s.id
)
SELECT
m.id,
m.title,
m.description,
count(q.id) AS submenus_count,
SUM(q.dishes_count) AS dishes_count
FROM menu m
JOIN subq q ON m.id = q.parent_menu
GROUP BY m.id
"""
m = aliased(models.Menu)
s = aliased(models.SubMenu)
d = aliased(models.Dish)
query = select(m).where(m.id == menu_id)
query = (
select(
m,
func.count(distinct(s.id)).label("submenus_count"),
func.count(distinct(d.id)).label("dishes_count")
)
.join(s, s.parent_menu == m.id, isouter=True)
.join(d, d.parent_submenu == s.id, isouter=True)
.group_by(m.id)
.where(m.id == menu_id)
)
menu = await session.execute(query)
menu = menu.scalars().one_or_none()
if menu is None:
return None
submenu_query = select(
func.count(s.id).label("counter")
).filter(s.parent_menu == menu_id)
counter = await session.execute(submenu_query)
dish_query = (
select(func.count(d.id))
.join(s)
.filter(d.parent_submenu == s.id)
.filter(s.parent_menu == menu_id)
)
dishes = await session.execute(dish_query)
menu.submenus_count = counter.scalars().one_or_none()
menu.dishes_count = dishes.scalars().one_or_none()
return menu
@staticmethod
@@ -94,7 +64,7 @@ class MenuCrud:
await session.commit()
qr = select(models.Menu).where(models.Menu.id == menu_id)
updated_menu = await session.execute(qr)
return updated_menu.scalars().one()
return updated_menu
@staticmethod
async def delete_menu_item(menu_id: UUID, session: AsyncSession):

View File

@@ -1,9 +1,11 @@
import uuid
from copy import deepcopy
from typing import Annotated, List, Optional
from sqlalchemy import ForeignKey
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from sqlalchemy.util import hybridproperty
uuidpk = Annotated[
uuid.UUID,
@@ -21,6 +23,17 @@ class Base(DeclarativeBase):
title: Mapped[str_25]
description: Mapped[Optional[str]]
def __eq__(self, other):
classes_match = isinstance(other, self.__class__)
a, b = deepcopy(self.__dict__), deepcopy(other.__dict__)
a.pop('_sa_instance_state', None)
b.pop('_sa_instance_state', None)
attrs_match = (a == b)
return classes_match and attrs_match
def __ne__(self, other):
return not self.__eq__(other)
class Menu(Base):
__tablename__ = "menu"
@@ -28,10 +41,21 @@ class Menu(Base):
submenus: Mapped[List["SubMenu"]] = relationship(
"SubMenu",
backref="menu",
lazy="dynamic",
lazy="selectin",
cascade="all, delete",
)
@hybridproperty
def submenus_count(self):
return len(self.submenus)
@hybridproperty
def dishes_count(self):
counter = 0
for sub in self.submenus:
counter += len(sub.dishes)
return counter
class SubMenu(Base):
__tablename__ = "submenu"
@@ -42,10 +66,14 @@ class SubMenu(Base):
dishes: Mapped[List["Dish"]] = relationship(
"Dish",
backref="submenu",
lazy="dynamic",
lazy="selectin",
cascade="all, delete",
)
@hybridproperty
def dishes_count(self):
return len(self.dishes)
class Dish(Base):
__tablename__ = "dish"

View File

@@ -17,7 +17,7 @@ router = APIRouter(
@router.get("/", response_model=Optional[List[schemas.Menu]])
async def get_menus(session: AsyncSession = Depends(get_async_session)):
result = await crud.get_menus(session=session)
return result
return result.scalars().all()
@router.post("/", status_code=201, response_model=schemas.Menu)
@@ -54,7 +54,7 @@ async def update_menu(
menu=menu,
session=session,
)
return result
return result.scalars().one()
@router.delete("/{menu_id}")