Mercurial > piecrust2
view piecrust/data/paginator.py @ 111:208c652551a3
Quick fix for making the server correctly update referenced pages.
Disable the file-system cache for rendered segments when in server mode. We
can bring this optimization back when we're actually using the baking record
in the server too in order to know dependencies.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 16 Oct 2014 17:03:42 -0700 |
parents | dc8a6ff88f37 |
children | f130365568ff |
line wrap: on
line source
import math import logging from werkzeug.utils import cached_property from piecrust.data.base import IPaginationSource from piecrust.data.filters import PaginationFilter from piecrust.data.iterators import PageIterator logger = logging.getLogger(__name__) class Paginator(object): debug_render = ['has_more', 'items', 'has_items', 'items_per_page', 'items_this_page', 'prev_page_number', 'this_page_number', 'next_page_number', 'prev_page', 'next_page', 'total_item_count', 'total_page_count', 'next_item', 'prev_item'] debug_render_invoke = ['has_more', 'items', 'has_items', 'items_per_page', 'items_this_page', 'prev_page_number', 'this_page_number', 'next_page_number', 'prev_page', 'next_page', 'total_item_count', 'total_page_count', 'next_item', 'prev_item'] def __init__(self, page, source, uri, page_num=1, pgn_filter=None, items_per_page=-1): self._parent_page = page self._source = source self._uri = uri self._page_num = page_num self._iterator = None self._pgn_filter = pgn_filter self._items_per_page = items_per_page self._pgn_set_on_ctx = False @property def is_loaded(self): return self._iterator is not None @property def has_more(self): return self.next_page_number is not None @property def unload(self): self._iterator = None # Backward compatibility with PieCrust 1.0 {{{ @property def posts(self): return self.items @property def has_posts(self): return self.has_items @property def posts_per_page(self): return self.items_per_page @property def posts_this_page(self): return self.items_this_page @property def total_post_count(self): return self.total_item_count @property def next_post(self): return self.next_item @property def prev_post(self): return self.prev_item # }}} @property def items(self): self._load() return self._iterator @property def has_items(self): return self.posts_this_page > 0 @cached_property def items_per_page(self): if self._items_per_page > 0: return self._items_per_page if self._parent_page: ipp = self._parent_page.config.get('items_per_page') if ipp is not None: return ipp if isinstance(self._source, IPaginationSource): return self._source.getItemsPerPage() raise Exception("No way to figure out how many items to display " "per page.") @property def items_this_page(self): self._load() return len(self._iterator) @property def prev_page_number(self): if self._page_num > 1: return self._page_num - 1 return None @property def this_page_number(self): return self._page_num @property def next_page_number(self): self._load() if self._iterator._has_more: return self._page_num + 1 return None @property def prev_page(self): num = self.prev_page_number if num is not None: return self._getPageUri(num) return None @property def this_page(self): return self._getPageUri(self._page_num) @property def next_page(self): num = self.next_page_number if num is not None: return self._getPageUri(num) return None @property def total_item_count(self): self._load() return self._iterator.total_count @property def total_page_count(self): total_count = self.total_item_count per_page = self.items_per_page return int(math.ceil(total_count / per_page)) @property def next_item(self): self._load() return self._iterator.prev_page @property def prev_item(self): self._load() return self._iterator.next_page def all_page_numbers(self, radius=-1): total_page_count = self.total_page_count if total_page_count == 0: return [] if radius <= 0 or total_page_count < (2 * radius + 1): return list(range(1, total_page_count + 1)) first_num = self._page_num - radius last_num = self._page_num + radius if first_num <= 0: last_num += 1 - first_num first_num = 1 elif last_num > total_page_count: first_num -= (last_num - total_page_count) last_num = total_page_count first_num = max(1, first_num) last_num = min(total_page_count, last_num) return list(range(first_num, last_num + 1)) def page(self, index): return self._getPageUri(index) def _load(self): if self._iterator is not None: return if self._source is None: raise Exception("Can't load pagination data: no source has been defined.") pag_filter = self._getPaginationFilter() offset = (self._page_num - 1) * self.items_per_page self._iterator = PageIterator(self._source, current_page=self._parent_page, pagination_filter=pag_filter, offset=offset, limit=self.items_per_page, locked=True) self._iterator._iter_event += self._onIteration def _getPaginationFilter(self): f = PaginationFilter() if self._pgn_filter is not None: f.addClause(self._pgn_filter.root_clause) if isinstance(self._source, IPaginationSource): sf = self._source.getPaginationFilter(self._parent_page) if sf is not None: f.addClause(sf) return f def _getPageUri(self, index): uri = self._uri if index > 1: if uri != '': uri += '/' uri += str(index) return uri def _onIteration(self): if self._parent_page is not None and not self._pgn_set_on_ctx: eis = self._parent_page.app.env.exec_info_stack eis.current_page_info.render_ctx.setPagination(self) self._pgn_set_on_ctx = True