A simple view-based paginator library for discord.py 2.0. Works with Python 3.8+.
discord-ext-pager is available on PyPI, and as such can be installed using pip.
Users of Danny's discord-ext-menus will find some familiarity in this library. Provided are the following classes:
- PaginatorView: The view class that manages pagination and navigation.
- PageSource: The base class for sources the paginator view can accept.
- ListPageSource: The base class for formatting a list of items.
- AsyncIteratorPageSource: The base class for formatting an asynchronous iterator of items.
- PageOption:
A subclass of
discord.SelectOptionused for presenting navigation options. - StopAction: An enum for customizing PaginatorView's stop button behaviour.
- TimeoutAction: An enum for customizing PaginatorView's timeout behaviour.
While the PaginatorView can be instantiated and used by itself, page formatting
is handled by subclassing one of the PageSource base classes:
from typing import List
from discord.ext.pager import ListPageSource, PageSource, PaginatorView
class EmbedListPageSource(ListPageSource):
"""Takes a list of items and formats it in an embed."""
def format_page(self, view: PaginatorView, page: List[object]):
index = self.current_index * self.page_size
description = "\n".join(
f"{i}. {x}"
for i, x in enumerate(page, start=index + 1)
)
return discord.Embed(description=description)
# Anywhere a channel or interaction is available:
fruits = ["🍎 Apple", "🍊 Orange", "🍋 Lemon"]
source = EmbedListPageSource(fruits, page_size=2)
view = PaginatorView(sources=source, timeout=180)
await view.start(interaction)A navigation select menu for sub-pages can be added by overriding the
get_page_options() method to return a list of PageOption objects:
from typing import List
from discord.ext.pager import ListPageSource, PageOption, PageSource, PaginatorView
class MessageSource(PageSource):
"""A page source that simply displays a string in the message content."""
def __init__(self, message: str):
super().__init__(current_index=0)
self.message = message
def get_page(self, index: int):
return self.message
def format_page(self, view: PaginatorView, page: str):
return {"content": page, "embed": None}
class MessageNavigator(ListPageSource):
"""A list of messages that the user can select to view."""
def get_page_options(self, view: PaginatorView, page: List[MessageSource]):
# PageOption() takes the same arguments as discord.SelectOption
# plus a source= argument
return [PageOption(source=source, label=source.message) for source in page]
def format_page(self, view: PaginatorView, page: List[MessageSource]):
description = "\n".join(source.message for source in page)
embed = discord.Embed(description=description)
return {"content": None, "embed": embed}
hands = "👈👉👆👇🫵🤞🫰🤘🤙🤛🤜✊👊👋👏🙌"
source = MessageNavigator([MessageSource(s) for s in hands], page_size=5)
view = PaginatorView(sources=source)
await view.start(ctx)Once an option is selected, the PageSource contained within that option
is appended to PaginatorView.sources, causing that source to be displayed.
Another button is automatically provided for users to back out to the last
page source. This can be manually triggered by passing a list of page sources
to the PaginatorView(sources=) argument.
Click on an example below to see its source code:

