AIOGRAM, SQLALCHEMY Как вывести рандомную позицию из базы данных?
Подскажите, пожалуйста, как вывести из БД одну рандомную позицию. У меня есть несколько категорий, в них по несколько позиций. Пока что бот выводит все позиции по конкретной категории, но нужна одна - случайная (по конкретной категории). Знаю про random.choice и order_by(func.random()), но непонятно, где именно это лучше делать (в сессиях к бд или хендлерах) и как делать.
P.S. Делаю бота по фильмам (выводит постер фильма, описание, рейтинг, жанр). Не судите строго, я любитель
Таблицы:
class Category(Base):
__tablename__ = 'categories'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100))
item_rel: Mapped[List['Item']] = relationship(back_populates='category_rel')
class Item(Base):
__tablename__ = 'items'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100))
description: Mapped[str] = mapped_column(String(200))
photo: Mapped[str] = mapped_column(String(200))
rating: Mapped[int] = mapped_column()
genre: Mapped[str] = mapped_column(String(200))
category: Mapped[int] = mapped_column(ForeignKey('categories.id'))
category_rel: Mapped['Category'] = relationship(back_populates='item_rel')
сессии БД:
async def get_categories():
async with async_session() as session:
categories = await session.scalars(select(Category))
return categories
async def get_items_by_category(category_id: int):
async with async_session() as session:
items = await session.scalars(select(Item).where(Item.category == category_id))
return items
async def get_category():
async with async_session() as session:
category = await session.scalars(select(Category).where(Category.id == 1))
return category
async def get_item_by_id(item_id: int):
async with async_session() as session:
item = await session.scalar(select(Item).where(Item.id == item_id).order_by(func.random()).limit(1))
return item
Кнопки:
async def categories():
all_categories = await get_categories()
keyboard = InlineKeyboardBuilder()
for category in all_categories:
keyboard.add(InlineKeyboardButton(text=category.name,
callback_data=f'category_{category.id}'))
return keyboard.adjust(2).as_markup()
async def category():
all_categories = await get_category()
keyboard = InlineKeyboardBuilder()
for category in all_categories:
keyboard.add(InlineKeyboardButton(text='Случайный фильм',
callback_data=f'randomz_{category.id}'))
return keyboard.adjust(2).as_markup()
Хендлеры:
@router.callback_query(F.data.startswith('category_'))
async def category(callback: CallbackQuery):
items = await get_items_by_category(callback.data.split('_')[1])
item = await get_item_by_id(callback.data.split('_')[1])
for item in items:
await callback.message.answer_photo(photo=item.photo, caption=f'<strong>{item.name}</strong>\n\n<b>Рейтинг:</b> {item.rating}\n\n<b>Рейтинг:</b> {item.genre}\n\n{item.description}')
await callback.answer('')
@router.callback_query(F.data.startswith('randomz_'))
async def randomz(callback: CallbackQuery):
items = await get_items_by_category(callback.data.split('_')[1])
item = await get_item_by_id(callback.data.split('_')[1])
for item in items:
await callback.message.answer_photo(photo=item.photo, caption=f'<strong>{item.name}</strong>\n\n<b>Рейтинг:</b> {item.rating}\n\n<b>Рейтинг:</b> {item.genre}\n\n{item.description}')
await callback.answer('')
Ответы (1 шт):
Автор решения: SVBazuev
→ Ссылка
Конечно в сессии БД:
import random
async def get_items_by_category(category_id: int):
async with async_session() as session:
items = await session.scalars(
select(Item).where(Item.category == category_id))
return random.choice(items)
или...
from sqlalchemy import func
async def get_items_by_category(category_id: int):
async with async_session() as session:
random_item = await session.scalars(
select(Item).where(Item.category == category_id
).order_by(func.random()).limit(1)
).first()
return random_item