from django.core.paginator import Paginator from boards.abstracts.constants import PARAM_PAGE __author__ = 'neko259' PATTERN_PAGE_URL = '{}' PAGINATOR_LOOKAROUND_SIZE = 2 def get_paginator(*args, **kwargs): return DividedPaginator(*args, **kwargs) class DividedPaginator(Paginator): lookaround_size = PAGINATOR_LOOKAROUND_SIZE def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True, current_page=1, link=None, params=None): super().__init__(object_list, per_page, orphans, allow_empty_first_page) self.link = link self.params = params self.current_page = current_page def _left_range(self): return self.page_range[:self.lookaround_size] def _right_range(self): pages = self.num_pages-self.lookaround_size if pages <= 0: return [] else: return self.page_range[pages:] def _center_range(self): index = self.page_range.index(self.current_page) start = max(self.lookaround_size, index - self.lookaround_size) end = min(self.num_pages - self.lookaround_size, index + self.lookaround_size + 1) return self.page_range[start:end] def _get_divided_range(self): dr = list() dr += self._left_range() dr += self._center_range() dr += self._right_range() # Remove duplicates dr = list(set(dr)) dr.sort() return dr def get_dividers(self, divided_range): dividers = [] prev_page = 1 for page in divided_range: if page - prev_page > 1: dividers.append(page) # There can be no more than 2 dividers, so don't bother going # further if len(dividers) > 2: break prev_page = page return dividers def get_page_url(self, page): self.params[PARAM_PAGE] = page url_params = '&'.join(['{}={}'.format(key, self.params[key]) for key in self.params.keys()]) return '{}?{}'.format(self.link, url_params) def supports_urls(self): return self.link is not None and self.params is not None def get_next_page_url(self): current = self.page(self.current_page) if current.has_next(): return self.get_page_url(current.next_page_number()) def get_prev_page_url(self): current = self.page(self.current_page) if current.has_previous(): return self.get_page_url(current.previous_page_number()) def get_page_url_list(self): output = [] divided_range = self._get_divided_range() dividers = self.get_dividers(divided_range) for page in divided_range: if page in dividers: output.append('...') if page == self.current_page: cls = 'class="current_page"' else: cls = '' output.append(PATTERN_PAGE_URL.format(cls, self.get_page_url(page), page)) return ', '.join(output)