Коммит для синхронизации. Частично сделаны роуты для меню. Модели и схемы пайдантика
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
from fastapi import FastAPI
|
||||
|
||||
from fastfood.routes import router
|
||||
|
||||
|
||||
async def generate_test_data():
|
||||
"""
|
||||
@@ -13,5 +15,6 @@ def create_app():
|
||||
Создание экземпляра приложения FastAPI и врзврат его
|
||||
"""
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
|
||||
return app
|
||||
|
24
fastfood/config.py
Normal file
24
fastfood/config.py
Normal file
@@ -0,0 +1,24 @@
|
||||
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 = "demo_db"
|
||||
|
||||
@property
|
||||
def DATABASE_URL_asyncpg(self):
|
||||
"""
|
||||
Возвращает строку подключения к БД необходимую для SQLAlchemy
|
||||
"""
|
||||
return (
|
||||
f"postgresql+asyncpg://{self.DB_USER}:{self.DB_PASS}"
|
||||
f"@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}"
|
||||
)
|
||||
|
||||
model_config = SettingsConfigDict(env_file=".env")
|
||||
|
||||
|
||||
settings = Settings()
|
31
fastfood/crud.py
Normal file
31
fastfood/crud.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from sqlalchemy import select
|
||||
|
||||
from fastfood.dbase import async_session_maker, async_engine
|
||||
from fastfood import models, schemas
|
||||
|
||||
|
||||
async def create_db_and_tables():
|
||||
async with async_engine.begin() as conn:
|
||||
await conn.run_sync(models.Base.metadata.drop_all)
|
||||
await conn.run_sync(models.Base.metadata.create_all)
|
||||
|
||||
|
||||
class Crud:
|
||||
@staticmethod
|
||||
async def get_menus():
|
||||
async with async_session_maker() as session:
|
||||
query = select(models.Menu)
|
||||
result = await session.execute(query)
|
||||
return result.scalars().all()
|
||||
|
||||
|
||||
@staticmethod
|
||||
async def add_menu(menu: schemas.Menu):
|
||||
async with async_session_maker() as session:
|
||||
new_menu_item = models.Menu(
|
||||
title=menu.title,
|
||||
description=menu.description,
|
||||
)
|
||||
session.add(new_menu_item)
|
||||
await session.commit()
|
||||
return new_menu_item
|
22
fastfood/dbase.py
Normal file
22
fastfood/dbase.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from typing import AsyncGenerator
|
||||
|
||||
from sqlalchemy.ext.asyncio import (
|
||||
AsyncSession,
|
||||
async_sessionmaker,
|
||||
create_async_engine,
|
||||
)
|
||||
|
||||
from fastfood.config import settings
|
||||
|
||||
|
||||
async_engine = create_async_engine(settings.DATABASE_URL_asyncpg)
|
||||
async_session_maker = async_sessionmaker(
|
||||
async_engine,
|
||||
class_=AsyncSession,
|
||||
expire_on_commit=False,
|
||||
)
|
||||
|
||||
|
||||
async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
|
||||
async with async_session_maker() as session:
|
||||
yield session
|
42
fastfood/models.py
Normal file
42
fastfood/models.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from decimal import Decimal
|
||||
from typing import List, Annotated, Optional
|
||||
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship, DeclarativeBase
|
||||
|
||||
|
||||
intpk = Annotated[int, mapped_column(primary_key=True)]
|
||||
str_25 = Annotated[str, 25]
|
||||
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
pass
|
||||
|
||||
|
||||
class Menu(Base):
|
||||
__tablename__ = "menu"
|
||||
|
||||
id: Mapped[intpk]
|
||||
title: Mapped[str_25]
|
||||
description: Mapped[Optional[str]]
|
||||
submenus: Mapped[List["SubMenu"]] = relationship()
|
||||
|
||||
|
||||
class SubMenu(Base):
|
||||
__tablename__ = "submenu"
|
||||
|
||||
id: Mapped[intpk]
|
||||
title: Mapped[str_25]
|
||||
description: Mapped[Optional[str]]
|
||||
parent_menu: Mapped[int] = mapped_column(ForeignKey("menu.id"))
|
||||
dishes: Mapped[List["Dish"]] = relationship()
|
||||
|
||||
|
||||
class Dish(Base):
|
||||
__tablename__ = "dish"
|
||||
|
||||
id: Mapped[intpk]
|
||||
title: Mapped[str_25]
|
||||
description: Mapped[Optional[str]]
|
||||
price: Mapped[Decimal]
|
||||
parent_submenu: Mapped[int] = mapped_column(ForeignKey("submenu.id"))
|
30
fastfood/routes.py
Normal file
30
fastfood/routes.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy import insert, select
|
||||
|
||||
from fastfood import models, schemas
|
||||
from fastfood.dbase import get_async_session
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/api/v1/menus")
|
||||
async def read_menu(session: AsyncSession = Depends(get_async_session)):
|
||||
stmt = select(models.Menu)
|
||||
result = await session.execute(stmt)
|
||||
data = result.mappings().all()
|
||||
return data
|
||||
|
||||
|
||||
@router.post("/api/v1/menus", status_code=201)
|
||||
async def add_menu(menu: schemas.MenuBase, session: AsyncSession = Depends(get_async_session)):
|
||||
"""
|
||||
docstring
|
||||
"""
|
||||
stmt = insert(models.Menu).values(**menu.dict())
|
||||
await session.execute(stmt)
|
||||
await session.commit()
|
||||
return {"status": "success"}
|
||||
|
39
fastfood/schemas.py
Normal file
39
fastfood/schemas.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class MenuBase(BaseModel):
|
||||
title: str
|
||||
description: str | None = None
|
||||
|
||||
|
||||
class SubMenuBase(MenuBase):
|
||||
pass
|
||||
|
||||
|
||||
class DishBase(MenuBase):
|
||||
price: Decimal
|
||||
|
||||
|
||||
class Dish():
|
||||
id: int
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class SubMenu(SubMenuBase):
|
||||
id: int
|
||||
# dishes: list[Dish]
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class Menu(MenuBase):
|
||||
id: int
|
||||
# submenus: list[SubMenu]
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
Reference in New Issue
Block a user