Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
 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
Ejemplo n.º 6
0
 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
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
0
 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'])
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
 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)
Ejemplo n.º 11
0
    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)
Ejemplo n.º 13
0
 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
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
 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)
Ejemplo n.º 17
0
 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)
Ejemplo n.º 18
0
    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)
Ejemplo n.º 19
0
    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)
Ejemplo n.º 20
0
    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)
Ejemplo n.º 21
0
 def next_page_number(self):
     if not self.has_next():
         raise EmptyPage()
     return self.number + 1
Ejemplo n.º 22
0
 def previous_page_number(self):
     if self.number <= 1:
         raise EmptyPage()
     return self.number - 1
Ejemplo n.º 23
0
    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)