Проблема с пагинацией на aiogram==3.13.1
У меня есть класс который создаёт пагинацию из приходящей в него уже сформированной клавиатуры, клавиатура формируется на данных по запросу к FastApi(из бд Postgres), (все работает корректно), но есть проблема. Клавиатура некорректно реагирует на изменения в БД.
У меня в БД есть 3 записи, бот выводит 1 из 1 страницу на которой 3 записи, затем я добавляю еще 1 запись, бот выводит 1 из 1 страницу на которой 4 записи, но если я добавляю 6 записей в бд, бот выводит 1 из 2 страницу на которой 4 записи, но перейти на 2 страницу я не могу. Если в бд много записей, например на 5 страниц и я добвляю еще записи которые должны быть на 6 странице, то бот выводит 1 из 6 страниц, но если перейти на следующую страницу, последняя 6 страница пропадает и получается 2 из 5, если перейти назад 1 из 5, т.е. В класс для пагинации приходит клавиатура нужного размера, но он ее выводит только в том размере как до обновления бд, где размер клавиатуры мог поместиться на том количестве страниц как до обновления клавиатуры.
КОД ПАГИНАЦИИ
from aiogram import types, Router, Dispatcher
from aiogram.utils.keyboard import InlineKeyboardBuilder
from typing import Iterable, Union
import re
class PaginatedInlineKeyboard:
def __init__(
self,
data: Union[
types.InlineKeyboardMarkup,
Iterable[types.InlineKeyboardButton],
Iterable[Iterable[types.InlineKeyboardButton]],
InlineKeyboardBuilder
],
size: int = 2,
dp: Union[Dispatcher, Router, None] = None,
callback_startswith: str = "page_"
):
self.size = size
self.callback_startswith = callback_startswith
self.pages = self._prepare_pages(data)
self.max_page = len(self.pages) - 1
self.current_page = 0
if dp:
self._register_handlers(dp)
def _prepare_pages(self, data) -> list:
"""Преобразует входные данные в список страниц с кнопками."""
buttons = []
if isinstance(data, types.InlineKeyboardMarkup):
buttons = data.inline_keyboard
elif isinstance(data, InlineKeyboardBuilder):
buttons = data.export().inline_keyboard
elif isinstance(data, Iterable):
for item in data:
if isinstance(item, Iterable) and not isinstance(item, types.InlineKeyboardButton):
buttons.append(list(item))
elif isinstance(item, types.InlineKeyboardButton):
buttons.append([item])
return [buttons[i:i + self.size] for i in range(0, len(buttons), self.size)]
def get_markup(self) -> types.InlineKeyboardMarkup:
"""Создает InlineKeyboardMarkup с кнопками текущей страницы и навигацией."""
kb = InlineKeyboardBuilder()
for row in self.pages[self.current_page]:
kb.row(*row)
# Кнопки пагинации
pagination_buttons = []
if self.current_page > 0:
pagination_buttons.append(types.InlineKeyboardButton(text="◀️", callback_data=f"{self.callback_startswith}{self.current_page - 1}"))
pagination_buttons.append(types.InlineKeyboardButton(text=f"{self.current_page + 1}/{self.max_page + 1}", callback_data="ignore"))
if self.current_page < self.max_page:
pagination_buttons.append(types.InlineKeyboardButton(text="▶️", callback_data=f"{self.callback_startswith}{self.current_page + 1}"))
if pagination_buttons:
kb.row(*pagination_buttons)
return kb.as_markup()
async def update_pagination(self, call: types.CallbackQuery):
"""Обработчик нажатий на кнопки пагинации."""
match = re.match(rf"{re.escape(self.callback_startswith)}(\d+)", call.data)
if match:
new_page = int(match.group(1))
if 0 <= new_page <= self.max_page:
self.current_page = new_page
await call.message.edit_reply_markup(reply_markup=self.get_markup())
await call.answer()
def _register_handlers(self, dp: Union[Dispatcher, Router]):
"""Регистрирует обработчик пагинации."""
dp.callback_query.register(self.update_pagination, lambda c: c.data.startswith(self.callback_startswith))
КОД ФОРМИРОВАНИЯ КЛАВИАТУРЫ
async def inline_keyboard(iterable_object = None, callback_data: str = None, line_width: int = None, router: Router = None):
builder = InlineKeyboardBuilder()
for object in iterable_object:
builder.adjust(line_width)
builder.add(types.InlineKeyboardButton(text=str(object['name']), callback_data=callback_data + str(object['id'])))
pagination = PaginatedInlineKeyboard(builder.as_markup(), size=line_width, dp=router, callback_startswith=f'{callback_data[:-1]}page_')
return pagination.get_markup()
Дебажил, но происходит магия), и я уже не в состоянии ее понять. Помогите люди добрые!