def page(self, number): """ Returns a Page object for the given 1-based page number. """ number = self.validate_number(number) bottom = (number - 1) * self.per_page top = bottom + self.per_page page_items = self.object_list[bottom:top] # check moved from validate_number if not page_items: if number == 1 and self.allow_empty_first_page: pass else: raise EmptyPage('That page contains no results') return InfinitePage(page_items, number, self)
def page(self, number): number = self.validate_number(number) self.has_previous_page = False if number == 1 else True bottom = (number - 1) * self.per_page top = bottom + self.per_page top_with_extra = top + 1 object_with_extra = list(self.object_list[bottom:top_with_extra]) if not object_with_extra: raise EmptyPage(_('That page contains no results')) if len(object_with_extra) >= self.per_page: object_with_extra = object_with_extra[:-1] self.has_next_page = True else: self.has_next_page = False return self._get_page(object_with_extra, number, self)
def get_page(queryset, order_by, per_page, start=0): if start < 0: raise InvalidPage() object_list = list(_slice_queryset(queryset, order_by, per_page, start)) if start and not object_list: raise EmptyPage() next_cursor = None if len(object_list) > per_page: next_slice_first_item = object_list.pop(-1) attr_name = order_by.lstrip("-") next_cursor = getattr(next_slice_first_item, attr_name) return CursorPage(start, object_list, next_cursor)
def validate_number(self, number): """ Validates the given 1-based page number. """ try: number = int(number) except (TypeError, ValueError): raise PageNotAnInteger('That page number is not an integer') if number < 1: raise EmptyPage('That page number is less than 1') if number > self.num_pages: if number == 1 and self.allow_empty_first_page: pass else: number = self.num_pages return number
def validate_number(self, number): "Validates the given 1-based page number." try: number = int(number) except (TypeError, ValueError): raise PageNotAnInteger('That page number is not an integer') if number < 1: return 1 if number > self.num_pages: if number == 1 and self.allow_empty_first_page: return 1 elif self.num_pages > 0: return self.num_pages else: raise EmptyPage('That page contains no results') return number
def validate_number(self, number): """Validate the given 1-based page number.""" try: if isinstance(number, float) and not number.is_integer(): raise ValueError number = int(number) except (TypeError, ValueError): raise PageNotAnInteger(_('That page number is not an integer')) if number < 1: raise EmptyPage(_('That page number is less than 1')) if number > self.num_pages: if number == 1 and self.allow_empty_first_page: pass else: return self.num_pages return number
def validate_number(self, number): "Validates the given 1-based page number." try: number = int(number) except ValueError: raise PageNotAnInteger('That page number is not an integer') if number < 1: if SHOW_FIRST_PAGE_WHEN_INVALID: number = 1 else: raise EmptyPage('That page number is less than 1') if number > self.num_pages: if number == 1 and self.allow_empty_first_page: pass else: number = 1 return number
def test_invalid_page_pagination_number(self): data = [ "asik", "hehe", "seru", "asik", "hehe", "seru", "asik", "hehe", "seru", "asik", "hehe", "seru", "asik", "hehe", "seru", "asik", "hehe", "seru", "asik", "hehe", "seru", "asik", "hehe", "seru", "asik", "hehe", "seru", "asik", "hehe", "seru" ] test1 = paginate_page("...", data) test2 = paginate_page(-1, data) with patch.object(Manager, 'get_or_create') as a: a.side_effect = PageNotAnInteger("page number is not an integer") res = paginate_page("...", data) self.assertEqual(res['page_range'], test1['page_range']) with patch.object(Manager, 'get_or_create') as a: a.side_effect = EmptyPage("page number is less than 1") res = paginate_page(-1, data) self.assertEqual(res['page_range'], test2['page_range'])
def page(self, page_num=1): """Return the requested Page object""" try: int(page_num) except: raise PageNotAnInteger if page_num not in self.page_range: raise EmptyPage('That page does not exist.') # Page 1 starts at 0; take one off before calculating start = (page_num - 1) * self.page_size new_result = self._fetch_page(start=start) grouped_results = [ x['doclist'][0] for x in new_result.grouped[self.group_field]['groups'] ] return SolrPage(grouped_results, page_num, self)
def page(self, number): number = self.validate_number(number) bottom = (number - 1) * self.per_page top = bottom + self.per_page # Retrieve more objects to check if there is a next page. objects = list(self.object_list[bottom:top + self.orphans + 1]) objects_count = len(objects) if objects_count > (self.per_page + self.orphans): # If another page is found, increase the total number of pages. self._num_pages = number + 1 # In any case, return only objects for this page. objects = objects[:self.per_page] elif (number != 1) and (objects_count <= self.orphans): raise EmptyPage(_("That page contains no results")) else: # This is the last page. self._num_pages = number return Page(objects, number, self)
def __init__(self, request, *args, **kwargs): # При сжатии страниц: кол-во страниц, соседних текущей с каждой стороны, # чьи номера будут показаны self.page_neighbors = kwargs.pop('page_neighbors', 2) # При сжатии страниц: кол-во страниц, соседних с граничными, # чьи номера будут показаны self.side_neighbors = kwargs.pop('side_neighbors', 0) # При сжатии страниц: минимальное кол-во страниц, заменямых многоточием self.min_zip_pages = kwargs.pop('min_zip_pages', 2) # Якорь, добавляемяй к ссылкам self.anchor = kwargs.pop('anchor', '') super().__init__(*args, **kwargs) self.request = request if not self.allow_empty_first_page and self.count == 0: raise EmptyPage('That page contains no results')
def page(self, value, pk=_NO_PK, move_to=NEXT_PAGE): """ The param ``value`` may be ``None`` to get the first page. Pass both ``value`` and ``pk`` when the ``lookup_field``'s model field is not unique. Otherwise, just pass the ``value`` :raises: ``EmptyPage`` """ assert move_to in (NEXT_PAGE, PREV_PAGE) query_set = self.seek( value=value, pk=pk, move_to=move_to) if value and not query_set.exists(): raise EmptyPage() return SeekPage( query_set=query_set, key={'value': value, 'pk': pk}, move_to=move_to, paginator=self)
def page(self, number): number = self.validate_number(number) current_per_page = self.get_current_per_page(number) bottom = 0 if number == 1 else ((number - 2) * self.per_page + self.first_page) top = bottom + current_per_page # get more objects to see if there is a next page objects = list(self.object_list[bottom:top + self.orphans + 1]) objects_count = len(objects) if objects_count > (current_per_page + self.orphans): # if there is a next page increase the total number of pages self._num_pages = number + 1 # but return only objects for this page objects = objects[:current_per_page] elif (number != 1) and (objects_count <= self.orphans): raise EmptyPage('That page contains no results') else: # this is the last page self._num_pages = number return CustomPage(objects, number, self)
def page(self, number): "Returns a Page object for the given 1-based page number." try: number = int(number) except ValueError: raise PageNotAnInteger('That page number is not an integer') bottom = (number - 1) * self.per_page top = bottom + self.per_page + 5 try: _page = EndlessPage(list(self.object_list[bottom:top]), number, self) except AssertionError: top = top - 5 _page = EndlessPage(list(self.object_list[bottom:top]), number, self) if not _page.object_list: if number == 1 and self.allow_empty_first_page: pass else: raise EmptyPage('That page contains no results') return _page
def page(self, number): """ Returns a page object. This class overrides the default behavior and ignores "orphans" and assigns the count from the ES result to the Paginator. """ number = self.validate_number(number) bottom = (number - 1) * self.per_page top = bottom + self.per_page if top > self.max_result_window: raise InvalidPage( 'That page number is too high for the current page size') # Force the search to evaluate and then attach the count. We want to # avoid an extra useless query even if there are no results, so we # directly fetch the count from hits. if self.use_elasticsearch_dsl: result = self.object_list[bottom:top].execute() # Overwrite `object_list` with the list of ES results. page = Page(result.hits, number, self) # Overwrite the `count` with the total received from ES results. self.count = page.object_list.total else: page = Page(self.object_list[bottom:top], number, self) # Force the search to evaluate and then attach the count. list(page.object_list) self.count = page.object_list.count() # Now that we have the count validate that the page number isn't higher # than the possible number of pages and adjust accordingly. if number > self.num_pages: if number == 1 and self.allow_empty_first_page: pass else: raise EmptyPage('That page contains no results') return page
def page(self, number): number = self.validate_number(number) current_per_page = self.get_current_per_page(number) if number == 1: bottom = 0 else: bottom = ((number - 2) * self.per_page + self.first_page) top = bottom + current_per_page # Retrieve more objects to check if there is a next page. objects = list(self.object_list[bottom:top + self.orphans + 1]) objects_count = len(objects) if objects_count > (current_per_page + self.orphans): # If another page is found, increase the total number of pages. self._num_pages = number + 1 # In any case, return only objects for this page. objects = objects[:current_per_page] elif (number != 1) and (objects_count <= self.orphans): raise EmptyPage('That page contains no results') else: # This is the last page. self._num_pages = number return CustomPage(objects, number, self)
def page(self, number): number = self.validate_number(number) bottom = (number - 1) * self.per_page top = bottom + self.per_page # Retrieve more objects to check if there is a next page. look_ahead_items = (self.look_ahead - 1) * self.per_page + 1 objects = list(self.object_list[bottom:top + self.orphans + look_ahead_items]) objects_count = len(objects) if objects_count > (self.per_page + self.orphans): # If another page is found, increase the total number of pages. self._num_pages = number + (objects_count // self.per_page) # In any case, return only objects for this page. objects = objects[:self.per_page] elif (number != 1) and (objects_count <= self.orphans): raise EmptyPage(_("That page contains no results")) else: # This is the last page. self._num_pages = number # For rendering purposes in `table_page_range`, we have to remember the final count self._final_num_pages = number return Page(objects, number, self)
def page(self, number): _number = number # number=None occurs when a non-existant page is requested through RequestConfig.configure(). # Its algorithm is to select max(pages) when a non-existant page number is requested. # By the nature of LazyPaginator, it is impossible to know the highest page number, so we use the # number of pages we see when looking at the first page. if number is None: number = 1 number = self.validate_number(number) bottom = (number - 1) * self.per_page top = bottom + self.per_page # Retrieve more objects to check if there is a next page. look_ahead_items = (self.look_ahead - 1) * self.per_page + 1 object_list = list(self.object_list[bottom:top + self.orphans + look_ahead_items]) objects_count = len(object_list) if objects_count > (self.per_page + self.orphans): # If another page is found, increase the total number of pages. self._num_pages = number + (objects_count // self.per_page) # In any case, return only objects for this page. objects = object_list[:self.per_page] elif (number != 1) and (objects_count <= self.orphans): raise EmptyPage(_("That page contains no results")) else: # This is the last page. self._num_pages = number # For rendering purposes in `table_page_range`, we have to remember the final count self._final_num_pages = number objects = object_list if _number is None: # For number=None, always show the last per_page records number = self._num_pages bottom = objects_count - self.per_page objects = object_list[bottom:] return Page(objects, number, self)
def page(self, number): """ Returns a Page object for the given 1-based page number. Retrieves objects for the given page number plus 1 additional to check if there are more objects after this page. """ number = self.validate_number(number) offset = (number - 1) * self.per_page # this page objects + 1 extra window_items = list(self.object_list[offset:offset + self.per_page + 1]) page_items = window_items[:self.per_page] if not page_items: if number == 1 and self.allow_empty_first_page: pass else: raise EmptyPage("That page contains no results") has_next = len(window_items) > len(page_items) return InfinitePage(page_items, number, self, has_next)
def page(self, value=None, pk=None): if (value is None and pk is not None) or (value is not None and pk is None): raise ValueError("Both 'value' and 'pk' arguments must be provided") query_set = self.query_set if value is not None and pk is not None: lookup_filter, lookup_exclude = self.prepare_lookup(value, pk) query_set = query_set.filter(**lookup_filter) if lookup_exclude: query_set = query_set.exclude(**lookup_exclude) order = self.prepare_order() query_set = query_set.order_by(*order)[:self.per_page + 1] object_list = list(query_set) has_next = len(object_list) > self.per_page object_list = object_list[:self.per_page] if not object_list and value: raise EmptyPage("That page contains no results") return SeekPage(object_list=object_list, number=value, paginator=self, has_next=has_next)
def next_page_number(self): if not self.has_next(): raise EmptyPage() return self.number + 1
def previous_page_number(self): if self.number <= 1: raise EmptyPage() return self.number - 1
def page(self, number): number = self.validate_number(number) cursor, offset = self._get_cursor_and_offset(number - 1) if cursor: self.object_list.starting_cursor(cursor) results = self.object_list[:(self.per_page * self._batch_size)] else: bottom = (self.per_page * self._find_nearest_page_with_cursor(number - 1)) top = bottom + (self.per_page * self._batch_size) #No cursor, so grab the full batch results = self.object_list[bottom:top] self._process_batch_hook(results, number - 1, cursor, offset) nearest_page_with_cursor = self._find_nearest_page_with_cursor(number - 1) next_cursor = None if self.object_list.supports_cursors: #Store the cursor at the start of the NEXT batch next_cursor = self.object_list.next_cursor self._put_cursor(nearest_page_with_cursor + self._batch_size, next_cursor) batch_result_count = len(results) actual_results = results[offset:offset + self.per_page] if not actual_results: if number == 1 and self.allow_empty_first_page: pass else: raise EmptyPage('That page contains no results') # Calculate known_page_count and cache it if necessary. known_page_count = int(nearest_page_with_cursor + ceil(batch_result_count / float(self.per_page))) if known_page_count >= self._get_known_page_count(): if next_cursor and self._readahead: if self.object_list.contains_more_objects(next_cursor): known_page_count += 1 else: self._put_final_page(known_page_count) elif batch_result_count == self._batch_size * self.per_page: # If we got back exactly the right amount, we assume there is at least # one more page. known_page_count += 1 self._put_known_page_count(known_page_count) # Calculate known_item_count and if it's the last item known_item_count = int(nearest_page_with_cursor * self.per_page + batch_result_count) if known_item_count > self._get_known_items_count(): self._put_known_items_count(known_item_count) if batch_result_count < (self.per_page * self._batch_size): # No need to read ahead for one item, it won't be 100% accurate anyway. self._put_final_item(known_item_count) return UnifiedPage(actual_results, number, self)