├── .gitignore ├── app ├── database │ ├── models.py │ └── requests.py ├── handlers.py └── keyboards.py ├── db.sqlite3 └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | /.venv -------------------------------------------------------------------------------- /app/database/models.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import BigInteger, String, ForeignKey 2 | from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column 3 | from sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engine 4 | 5 | engine = create_async_engine(url='sqlite+aiosqlite:///db.sqlite3') 6 | 7 | async_session = async_sessionmaker(engine) 8 | 9 | 10 | class Base(AsyncAttrs, DeclarativeBase): 11 | pass 12 | 13 | 14 | class User(Base): 15 | __tablename__ = 'users' 16 | 17 | id: Mapped[int] = mapped_column(primary_key=True) 18 | tg_id = mapped_column(BigInteger) 19 | 20 | 21 | class Category(Base): 22 | __tablename__ = 'categories' 23 | 24 | id: Mapped[int] = mapped_column(primary_key=True) 25 | name: Mapped[str] = mapped_column(String(25)) 26 | 27 | 28 | class Item(Base): 29 | __tablename__ = 'items' 30 | 31 | id: Mapped[int] = mapped_column(primary_key=True) 32 | name: Mapped[str] = mapped_column(String(25)) 33 | description: Mapped[str] = mapped_column(String(120)) 34 | price: Mapped[int] = mapped_column() 35 | category: Mapped[int] = mapped_column(ForeignKey('categories.id')) 36 | 37 | 38 | async def async_main(): 39 | async with engine.begin() as conn: 40 | await conn.run_sync(Base.metadata.create_all) 41 | -------------------------------------------------------------------------------- /app/database/requests.py: -------------------------------------------------------------------------------- 1 | from app.database.models import async_session 2 | from app.database.models import User, Category, Item 3 | from sqlalchemy import select 4 | 5 | 6 | async def set_user(tg_id: int) -> None: 7 | async with async_session() as session: 8 | user = await session.scalar(select(User).where(User.tg_id == tg_id)) 9 | 10 | if not user: 11 | session.add(User(tg_id=tg_id)) 12 | await session.commit() 13 | 14 | 15 | async def get_categories(): 16 | async with async_session() as session: 17 | return await session.scalars(select(Category)) 18 | 19 | 20 | async def get_category_item(category_id): 21 | async with async_session() as session: 22 | return await session.scalars(select(Item).where(Item.category == category_id)) 23 | 24 | 25 | async def get_item(item_id): 26 | async with async_session() as session: 27 | return await session.scalar(select(Item).where(Item.id == item_id)) 28 | -------------------------------------------------------------------------------- /app/handlers.py: -------------------------------------------------------------------------------- 1 | from aiogram import F, Router 2 | from aiogram.types import Message, CallbackQuery 3 | from aiogram.filters import CommandStart 4 | 5 | import app.keyboards as kb 6 | import app.database.requests as rq 7 | 8 | router = Router() 9 | 10 | 11 | @router.message(CommandStart()) 12 | async def cmd_start(message: Message): 13 | await rq.set_user(message.from_user.id) 14 | await message.answer('Добро пожаловать в магазин кроссовок!', reply_markup=kb.main) 15 | 16 | 17 | @router.message(F.text == 'Каталог') 18 | async def catalog(message: Message): 19 | await message.answer('Выберите категорию товара', reply_markup=await kb.categories()) 20 | 21 | 22 | @router.callback_query(F.data.startswith('category_')) 23 | async def category(callback: CallbackQuery): 24 | await callback.answer('Вы выбрали категорию') 25 | await callback.message.answer('Выберите товар по категории', 26 | reply_markup=await kb.items(callback.data.split('_')[1])) 27 | 28 | 29 | @router.callback_query(F.data.startswith('item_')) 30 | async def category(callback: CallbackQuery): 31 | item_data = await rq.get_item(callback.data.split('_')[1]) 32 | await callback.answer('Вы выбрали товар') 33 | await callback.message.answer(f'Название: {item_data.name}\nОписание: {item_data.description}\nЦена: {item_data.price}$') 34 | -------------------------------------------------------------------------------- /app/keyboards.py: -------------------------------------------------------------------------------- 1 | from aiogram.types import (ReplyKeyboardMarkup, KeyboardButton, 2 | InlineKeyboardMarkup, InlineKeyboardButton) 3 | 4 | from aiogram.utils.keyboard import InlineKeyboardBuilder 5 | 6 | from app.database.requests import get_categories, get_category_item 7 | 8 | main = ReplyKeyboardMarkup(keyboard=[[KeyboardButton(text='Каталог')], 9 | [KeyboardButton(text='Корзина')], 10 | [KeyboardButton(text='Контакты'), 11 | KeyboardButton(text='О нас')]], 12 | resize_keyboard=True, 13 | input_field_placeholder='Выберите пункт меню...') 14 | 15 | 16 | async def categories(): 17 | all_categories = await get_categories() 18 | keyboard = InlineKeyboardBuilder() 19 | for category in all_categories: 20 | keyboard.add(InlineKeyboardButton(text=category.name, callback_data=f"category_{category.id}")) 21 | keyboard.add(InlineKeyboardButton(text='На главную', callback_data='to_main')) 22 | return keyboard.adjust(2).as_markup() 23 | 24 | 25 | async def items(category_id): 26 | all_items = await get_category_item(category_id) 27 | keyboard = InlineKeyboardBuilder() 28 | for item in all_items: 29 | keyboard.add(InlineKeyboardButton(text=item.name, callback_data=f"item_{item.id}")) 30 | keyboard.add(InlineKeyboardButton(text='На главную', callback_data='to_main')) 31 | return keyboard.adjust(2).as_markup() 32 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlxrd/aiogram_fast_pt2/b2eeabf1288c5ab7ff7b1de25409759a940b5b9d/db.sqlite3 -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from aiogram import Bot, Dispatcher 3 | 4 | from app.handlers import router 5 | from app.database.models import async_main 6 | 7 | 8 | async def main(): 9 | await async_main() 10 | bot = Bot(token='token') 11 | dp = Dispatcher() 12 | dp.include_router(router) 13 | await dp.start_polling(bot) 14 | 15 | 16 | if __name__ == '__main__': 17 | try: 18 | asyncio.run(main()) 19 | except KeyboardInterrupt: 20 | print('Бот выключен') 21 | --------------------------------------------------------------------------------