[docs]classPaginator[ItemT]:"""Helper class for paginating a sequence of items """request:web.Request"""The request object"""items:Sequence[ItemT]"""The items to paginate"""total_items:int"""The total number of items"""current_index:int"""The current page index"""per_page:int"""The number of items per page"""page_query_param:str"""The query parameter for the page number"""per_page_query_param:str"""The query parameter for the number of items per page"""pages:list[Page[ItemT]]"""A list of :class:`Page` objects"""def__init__(self,request:web.Request,items:Sequence[ItemT],total_items:int|None=None,current_index:int|None=None,per_page:int=10,page_query_param:str='page',per_page_query_param:str='per_page',disable_pagination:bool=False,)->None:self.request=requestself.items=itemsself.disable_pagination=disable_paginationifdisable_pagination:per_page=len(items)current_index=0total_items=len(items)else:iftotal_itemsisNone:total_items=len(items)ifcurrent_indexisNone:current_index=int(request.query.get(page_query_param,0))ifrequest.query.get(per_page_query_param):per_page=int(request.query[per_page_query_param])self.current_index=current_indexself.total_items=total_itemsself.per_page=per_pageself.page_query_param=page_query_paramself.per_page_query_param=per_page_query_paramself.pages:list[Page[ItemT]]=[]foriinrange(self.num_pages):self.pages.append(Page(self,i))@propertydefnum_pages(self)->int:"""Number of pages """ifself.total_items<=self.per_page:return1returnmath.ceil(self.total_items/self.per_page)@propertydefcurrent_page(self)->Page[ItemT]:"""The current :class:`Page` object """returnself.pages[self.current_index]@propertydefpaginating(self)->bool:"""Flag to indicate whether pagination is active """returnlen(self.pages)>1
[docs]defiter_pages(self,max_pages:int=10)->Iterable[Page[ItemT]]:"""Iterate over :attr:`pages` Iteration will be centered around the current page index within the given *max_pages*. Arguments: max_pages: The maximum number of pages to iterate over """start=max(0,self.current_index-max_pages//2)end=min(self.num_pages,start+max_pages)returnself.pages[start:end]
[docs]classPage[ItemT]:"""A page of items within a :class:`Paginator` """paginator:Paginator[ItemT]page_num:int"""The page number"""def__init__(self,paginator:Paginator[ItemT],page_num:int)->None:self.paginator=paginatorself.page_num=page_num@propertydefactive(self)->bool:"""Whether this page is the :attr:`~Paginator.current_page`"""returnself.page_num==self.paginator.current_index@propertydefstart_index(self)->int:"""The index of the first item within :attr:`~Paginator.items` for this page """returnself.page_num*self.paginator.per_page@propertydefend_index(self)->int:"""The index of the last item within :attr:`~Paginator.items` for this page """returnself.start_index+self.paginator.per_page@propertydefhas_next(self)->bool:"""Whether there is a next page """returnself.page_num<self.paginator.num_pages-1@propertydefhas_prev(self)->bool:"""Whether there is a previous page """returnself.page_num>0@propertydefprev_page_num(self)->int:"""The index of the previous page """returnself.page_num-1@propertydefnext_page_num(self)->int:"""The index of the next page """returnself.page_num+1@propertydefnext_page(self)->Page[ItemT]:"""The next :class:`Page` """returnself.paginator.pages[self.next_page_num]@propertydefprev_page(self)->Page[ItemT]:"""The previous :class:`Page` """ifself.page_num==0:raiseIndexError('No previous page')returnself.paginator.pages[self.prev_page_num]@propertydefurl(self)->URL:"""The URL for this page """returnself.paginator._build_url(self.page_num)@propertydefslice(self)->slice:"""A :class:`slice` object for the :attr:`~Paginator.items` of this page """returnslice(self.start_index,self.end_index)@propertydeflength(self)->int:"""The number of items on this page """returnlen(self)def__iter__(self)->Iterator[ItemT]:yield fromself.paginator.items[self.slice]def__len__(self)->int:returnlen(self.paginator.items[self.slice])