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

        # 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.
        result = self.object_list[bottom:top].execute()
        page = Page(result.hits, number, self)
        # Update the `_count`.
        self._count = page.object_list.total
        # Also store the aggregations, if any.
        if hasattr(result, 'aggregations'):
            page.aggregations = result.aggregations

        # 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
Esempio n. 2
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

        # 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.
        result = self.object_list[bottom:top].execute()
        page = Page(result.hits, number, self)
        # Update the `_count`.
        self._count = page.object_list.total
        # Also store the aggregations, if any.
        if hasattr(result, 'aggregations'):
            page.aggregations = result.aggregations

        # 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
Esempio n. 3
0
    def build_page(self):
        """For some reason occasionally the default pagination contains Nones
        (probably a bug in django-haystack. We don't want that."""
        # Copied from super()
        try:
            page_no = int(self.request.GET.get('page', 1))
        except (TypeError, ValueError):
            raise Http404("Not a valid number for page.")

        if page_no < 1:
            raise Http404("Pages should be 1 or greater.")

        start_offset = (page_no - 1) * self.results_per_page
        self.results = self.results.load_all() # Force haystack to pull all 'Product' objects at the same time
        self.results[start_offset:start_offset + self.results_per_page]

        paginator = Paginator(self.results, self.results_per_page)

        # My stuff
        try:
            page = paginator.page(page_no)
        except EmptyPage:
            page = Page([], page_no, paginator)
        page.object_list = [o for o in page.object_list if o is not None]
        return paginator, page
Esempio n. 4
0
 def _get_page(self, *args, **kwargs):
     page = Page(*args, **kwargs)
     if page.has_next():
         page.next_page_first_item = page[-1]
         page.object_list = page.object_list[:-1]
     else:
         page.next_page_first_item = None
     return page
Esempio n. 5
0
def test_paginator_tags(snapshot):
    objects = ['object %d' % i for i in range(100)]
    paginator = Paginator(objects, 5)
    template = loader.get_template('cruds_mixins/partials/pagination.html')
    page = Page(objects, 1, paginator)
    c = {'page_obj': page, 'is_paginated': True}
    result = template.render(c)
    snapshot.assert_match(result)

    page = Page(objects, 15, paginator)
    c = {'page_obj': page, 'is_paginated': True}
    result = template.render(c)
    snapshot.assert_match(result)
Esempio n. 6
0
def by_storyteller(obj):
    if isinstance(obj, User):
        user = obj
    else:
        user = obj.owner
    template_name = "maps/_widget_by_storyteller.html"
    maps_page = Page([], 0, _by_storyteller_pager(None, user, 'maps'))
    layers_page = Page([], 0, _by_storyteller_pager(None, user, 'layers'))
    return loader.render_to_string(template_name, {
        'user': user,
        'maps_pager': maps_page,
        'layers_pager': layers_page
    })
Esempio n. 7
0
 def page(self, number):
     "Returns a Page object for the given 1-based page number."
     number = self.validate_number(number)
     if self.count == 0:
         return Page(self.object_list, number, self)
     bottom = (number - 1) * self.per_page
     bottomdate = self.parentcomments[bottom].sortdate
     top = bottom + self.per_page
     if top + self.orphans >= self.count:
         object_list = self.object_list.filter(sortdate__lte=bottomdate)
     else:
         topdate = self.parentcomments[bottom+self.per_page-1].sortdate
         object_list = self.object_list.filter(
             sortdate__range=(topdate, bottomdate))
     return Page(object_list, number, self)
Esempio n. 8
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.
        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 = int(page.object_list.total)

        # 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
Esempio n. 9
0
 def page(self, number):
     """
     Override the page method in Paginator since Solr has already
     paginated stuff for us.
     """
     number = self.validate_number(number)
     return Page(self.object_list, number, self)
Esempio n. 10
0
 def page(self, number):
     number = self.validate_number(number)
     offset = (number - 1) * self.per_page
     if offset + self.per_page + self.orphans >= self.count:
         top = self.count
     return Page(self.object_list.fetch(self.per_page, offset=offset),
                 number, self)
Esempio n. 11
0
    def page(self, number):
        """
        Returns a page object.
        """
        # Don't fetch hits, only care about aggregations.
        self.object_list._params['search_type'] = 'count'
        result = self.object_list.execute()

        # Pull the results from the aggregations.
        hits = []
        aggs = result.aggregations
        buckets = aggs['top_hits']['buckets']
        for bucket in buckets:
            # Have to check the bucket key since other tags could get
            # aggregated (e.g., `featured-game`) when we only care about game
            # categories.
            if bucket['key'] in GAME_CATEGORIES:
                hits.append(bucket['first_game']['hits']['hits'][0])

        page = Page(hits, number, self)

        # Update the `_count`.
        self._count = len(page.object_list)

        return page
Esempio n. 12
0
def pagination(pager, url_name, *args):
    '''pager could be a page or pagination object.'''
    url = reverse(url_name, args=args)
    if not hasattr(pager, 'number'):
        # we're on 'page 0' - lazy load
        pager = Page([], 0, pager)
    return loader.render_to_string('_pagination.html', {'page' : pager, 'url': url})
Esempio n. 13
0
    def page(self, number):
        """
        Returns a Page object for the given 1-based page number.

        This will attempt to pull the results out of the cache first, based on
        the requested page number. If not found in the cache,
        it will pull a fresh list and then cache that result + the total result count.
        """
        if self.cache_key is None:
            return super(CachedPaginator, self).page(number)

        # In order to prevent counting the queryset
        # we only validate that the provided number is integer
        # The rest of the validation will happen when we fetch fresh data.
        # so if the number is invalid, no cache will be setted
        # number = self.validate_number(number)
        try:
            number = int(number)
        except (TypeError, ValueError):
            raise PageNotAnInteger('That page number is not an integer')

        page_cache_key = "%s:%s:%s" % (self.cache_key, self.per_page, number)
        page_data = cache.get(page_cache_key)

        if page_data is None:
            page = super(CachedPaginator, self).page(number)
            #cache not only the objects, but the total count too.
            page_data = (page.object_list, self.count)
            cache.set(page_cache_key, page_data, self.cache_timeout)
        else:
            cached_object_list, cached_total_count = page_data
            self.set_count(cached_total_count)
            page = Page(cached_object_list, number, self)

        return page
Esempio n. 14
0
 def page(self, number):
     number = self.validate_number(number)
     bottom = (number - 1) * self.per_page
     top = bottom + self.per_page
     if top + self.orphans >= self.count:
         top = self.count
     return Page(self.object_list.get_slice(bottom,self.per_page), number, self)
Esempio n. 15
0
   def page(self, number):
       "Returns a Page object for the given 1-based page number."
       number = self.validate_number(number)
       if self.count == 0:
           return Page(self.object_list, number, self)
       bottom = (number - 1) * self.per_page
 # This results in a query to the database ...
       bottomdate = self.parentcomments[bottom].sort_date
       try:
 # This too results in a query to the database ...
           top = self.parentcomments[bottom+self.per_page-1].sort_date
           object_list = self.object_list.filter(sort_date__range=(top, bottomdate))
       except IndexError:
           object_list = self.object_list.filter(sort_date__lte=bottomdate)
 # And another (final) call to the database
       return Page(object_list, number, self)
Esempio n. 16
0
    def _get_page(self, *args, **kwargs):
        """
		Return an instance of a single page.
		This hook can be used by subclasses to use an alternative to the
		standard :cls:`Page` object.
		"""
        return Page(*args, **kwargs)
Esempio n. 17
0
 def page(self, number):
     "Returns a Page object for the given 1-based page number."
     number = self.validate_number(number)
     offset = (number - 1) * self.per_page
     if offset + self.per_page + self.orphans >= self.count:
         top = self.count
     return Page(self.object_list.fetch(self.per_page, offset), number,
                 self)
Esempio n. 18
0
def user_list(request):
    current_page = request.GET.get('p', 1)
    current_page = int(current_page)

    per_page_count = request.COOKIES.get('per_page_count', 10)  # 获取cookie值
    per_page_count = int(per_page_count)

    page_obj = Page(current_page, len(LIST), per_page_count)

    data = LIST[page_obj.start:page_obj.end]

    page_str = page_obj.page_str("/user_list/")

    return render(request, 'user_list.html', {
        'li': data,
        'page_str': page_str
    })
Esempio n. 19
0
    def page(self, number):
        page = super(ObjectPaginator, self).page(number)

        if isinstance(page.object_list, QuerySet):
            ids = [product['pk'] for product in page.object_list.values('pk')]

            # keep same order by clause as used
            #   in paginator to fetch full product objects
            ordering = page.object_list.query.order_by
        elif isinstance(self.object_list, SearchQuerySet):
            # When this step happens just after the index was cleared, then product may be None
            # import pdb; pdb.set_trace()
            # ids = [product.pk for product in page.object_list if product is not None]
            ids = page.object_list

            # ordering = self.object_list._db_query_order  # our custom parameter to remember db order
            ordering = None
        else:
            raise

        if not ids:
            return Page([], number, self)

        product_set = self.model.objects.filter(id__in=ids)

        # ordering must by different than relevancy (relevancy occurs only in the elasticsearch part)
        if ordering and any(item not in ['relevancy', '-relevancy']
                            for item in ordering):
            product_set = product_set.order_by(*ordering)
        else:
            # it's a way to avoid automatically sorting by id. We want to have order which we get from the elasticsearch.
            # Especially useful when we search by id i.e. 400 (for this word we can find a lot of product by title and one by id).
            # We want to have the product which is found by id on the first position, so we should keep the list returned by solr.
            product_set = self.model.objects.filter(id__in=ids).extra(
                select={'manual': 'FIELD(id, %s)' % ','.join(map(str, ids))},
                order_by=['manual'],
            )

        # TODO: This is micro optimization for search to reduce number of queries
        if self.model == Booking:
            product_set = product_set.prefetch_related('trainer',
                                                       'trainer__user')
        elif self.model == Trainer:
            product_set = product_set.prefetch_related('user', 'diciplines')

        return Page(product_set, number, self)
Esempio n. 20
0
    def get_paginated_object_list(self, page_number, **kwargs):
        params = self.get_api_parameters(**kwargs)
        params['limit'] = self.per_page
        params['offset'] = (page_number - 1) * self.per_page

        result = requests.get(self.api_base_url, params=params).json()
        paginator = APIPaginator(result['meta']['total_count'], self.per_page)
        page = Page(result['items'], page_number, paginator)
        return (page, paginator)
Esempio n. 21
0
 def page(self, number):
     number = self.validate_number(number)
     bottom = (
         number -
         2) * self.per_page + self.first_page_count if number > 1 else 0
     top = bottom + (self.first_page_count
                     if number == 1 else self.per_page)
     if top + self.orphans >= self.count:
         top = self.count
     return Page(self.object_list[bottom:top], number, self)
Esempio n. 22
0
 def page(self, number):
     if number > self.num_pages:
         number = self.num_pages
     if number < 1:
         number = 1
     bottom = (number - 1) * self.per_page
     top = bottom + self.per_page
     if top + self.orphans >= self.count:
         top = self.count
     return Page(self.object_list[bottom:top], number, self)
Esempio n. 23
0
 def __init__(self, object_list, permage_id, paginator):
     number = -1
     self.permage_id = permage_id
     for page, pid in paginator.page_range:
         if pid == permage_id:
             number = page
     Page.__init__(self, object_list, number, paginator)
     self.asc = False
     if len(self.object_list) > 1:
         first = self.object_list[0].id
         second = self.object_list[1].id
         if first < second:
             self.asc = True
     #navigation: div id=paginator
     self.navigation = []
     prev_range = self.paginator.page_range[:number-1]
     next_range = self.paginator.page_range[number:]
     if len(self.paginator.page_range) <= self.paginator.navigation_steps:
         self.navigation = prev_range
         self.navigation.append([number, "current"])
         self.navigation.extend(next_range)
     else:
         steps = (self.paginator.navigation_steps-1) / 2
         prev_len = len(prev_range[:steps])
         next_len = len(next_range[steps*(-1):])
         extra_steps_prev = steps - prev_len
         extra_steps_next = steps - next_len
         steps = steps + extra_steps_next
         if len(prev_range) > steps:
             self.navigation.append(prev_range[0])
             self.navigation.append([-1, "..."])
             self.navigation.extend(prev_range[(steps-1)*(-1):])
         else:
             self.navigation.extend(prev_range[:steps])
         self.navigation.append([number, "current"])
         steps = ((self.paginator.navigation_steps-1) / 2) + extra_steps_prev
         if len(next_range) > steps:
             self.navigation.extend(next_range[:(steps-1)])
             self.navigation.append([-1, "..."])
             self.navigation.append(next_range[-1])
         else:
             self.navigation.extend(next_range[(steps+1)*(-1):])
Esempio n. 24
0
 def page(self, number):
     number = self.validate_number(number)
     offset = (number - 1) * self.per_page
     limit = self.per_page
     if offset + limit + self.orphans >= self.count:
         limit = self.count - offset
     query_with_limit = self._get_limit_offset_query(limit, offset)
     data = list(
         self.raw_query_set.model.objects.raw(query_with_limit,
                                              self.raw_query_set.params))
     return Page(data, number, self)
Esempio n. 25
0
    def extend_paginator(cls, page_items: Page):
        """Дополняет объект постраничной навигации.

        :param page_items:

        """
        max_pages_before_after = 10
        page = page_items.number

        min_page_before = page - max_pages_before_after
        if min_page_before < 1:
            min_page_before = 0

        max_page_after = page + max_pages_before_after
        if max_page_after > page_items.paginator.num_pages:
            max_page_after = page_items.paginator.num_pages

        page_items.before_current = reversed(
            range(page - 1, min_page_before, -1))
        page_items.after_current = range(page + 1, max_page_after + 1)
 def page(self,number):
     number = self.validate_number(number)
     offset = (number -1 ) * self.per_page
     limit = self.per_page
     if offset + limit + self.orphans >= self.count:
         limit = self.count - offset
     database_vendor = self.connection.vendor
     try:
         query_with_limit = getattr(self,'%s_getquery' % database_vendor)(limit,offset)
     except AttributeError:
         raise DatabaseNotSupportedException('%s is not supported by RawQuerySetPaginator' % database_vendor)
     return Page(list(self.raw_query_set.model.objects.raw(query_with_limit,self.raw_query_set.params)), number, self)
Esempio n. 27
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
        page = Page(self.object_list[bottom:top], number, self)

        # 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.
        # Overwrite `object_list` with the list of ES results.
        page.object_list = page.object_list.execute().hits
        # Update the `_count`.
        self._count = page.object_list.total

        return page
Esempio n. 28
0
    def _get_page(self, object_list, number, paginator):
        self.result = object_list.execute(params=self._params)
        if isinstance(self.result.hits.total, int):
            self.count = self.result.hits.total
        else:
            self.count = int(self.result.hits.total.value)

        if self.count == 0 and not self.allow_empty_first_page:
            return 0
        hits = max(1, self.count - self.orphans)
        self.num_pages = ceil(hits / self.per_page)
        return Page(self.result, number, self)
Esempio n. 29
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
        page = Page(self.object_list[bottom:top], number, self)

        # 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.
        # Overwrite `object_list` with the list of ES results.
        page.object_list = page.object_list.execute().hits
        # Update the `_count`.
        self._count = page.object_list.total

        return page
Esempio n. 30
0
    def current_page(self):
        try:
            page = int(self.request.GET['page'])

            if page <= 0:
                raise ValueError()
        except (ValueError, KeyError):
            page = self.default

        try:
            return self.page(page)
        except EmptyPage:
            return Page([], page, self)
Esempio n. 31
0
    def page(self, number):
        "Returns a Page object for the given 1-based page number."
        bottom = (number - 1) * self.per_page
        top = bottom + self.per_page
        queryset = self.object_list.fetch((number * self.per_page)+1)
        results = queryset[bottom:top]
        try:
            queryset[top]
            self._num_pages = number + 1
        except IndexError:
            self._num_pages = number

        return Page(results, number, self)
Esempio n. 32
0
 def _get_page(self, *args, **kwargs):
     page = Page(*args, **kwargs)
     if page.has_next():
        page.next_page_first_item = page[-1]
        page.object_list = page.object_list[:-1]
     else:
        page.next_page_first_item = None
     return page
Esempio n. 33
0
    def page(self, number):
        try:
            number = self.validate_number(number)
            self.page_num = number
            bottom = (number - 1) * self.per_page
            top = bottom + self.per_page
            if top + self.orphans >= self.count:
                top = self.count
        except (InvalidPage, EmptyPage, PageNotAnInteger):
            number = 1
            bottom = 0
            top = self.per_page

        return Page(self.object_list[bottom:top], number, self)
Esempio n. 34
0
 def page(self, number):
     """Returns a Page object for the given 1-based page number."""
     number = self.validate_number(number)
     if number == 1:
         bottom = 0
         if self.count > self.deltafirst:
             top = self.per_page - self.deltafirst
         else:
             top = self.per_page
     else:
         bottom = (number - 1) * self.per_page - self.deltafirst
         top = bottom + self.per_page
     if top + self.orphans >= self.count:
         top = self.count
     return Page(self.object_list[bottom:top], number, self)
Esempio n. 35
0
def paginate(object_list, page_size, page_num):
    """
    Takes an object_list, page_size, page_num and paginates the object list.
    """

    paginator = Paginator(object_list, page_size)

    try:
        page = paginator.page(page_num)
    except PageNotAnInteger:
        page = paginator.page(1)
    except EmptyPage:
        page = Page([], 1, paginator)
        page.page_range = []
        return page

    start = page.number - 3
    if start < 0: start = 0
    end = page.number + 2
    if end > paginator.num_pages: end = paginator.num_pages

    page.page_range = paginator.page_range[start:end]

    return page
Esempio n. 36
0
 def __init__(self, page, req):
   DjangoPage.__init__(self, page.object_list, page.number, page.paginator)
   self.req = req
Esempio n. 37
0
    def page(self, number):
        """
        Override the page method in Paginator since Solr has already
        paginated stuff for us.
        """

        number = self.validate_number(number)

        # figure out the solr query and execute it
        solr = SolrConnection(settings.SOLR) # TODO: maybe keep connection around?
        start = self.per_page * (number - 1)
        params = {"hl.snippets": 100, # TODO: make this unlimited
            "hl.requireFieldMatch": 'true', # limits highlighting slop
            "hl.maxAnalyzedChars": '102400', # increased from default 51200
            }
        params.update(self.facet_params)
        sort_field, sort_order = _get_sort(self.query.get('sort'), in_pages=True)
        solr_response = solr.query(self._q,
                                   fields=['id', 'title', 'date', 'month', 'day',
                                           'sequence', 'edition_label', 
                                           'section_label'],
                                   highlight=self._ocr_list,
                                   rows=self.per_page,
                                   sort=sort_field,
                                   sort_order=sort_order,
                                   start=start,
                                   **params)
        solr_facets = solr_response.facet_counts
        # sort states by number of hits per state (desc)
        facets = {'state': sorted(solr_facets.get('facet_fields')['state'].items(),
                                  lambda x, y: x - y, lambda k: k[1], True),
                  'year': solr_facets['facet_ranges']['year']['counts'],
                  'county': sorted(solr_facets.get('facet_fields')['county'].items(),
                                  lambda x, y: x - y, lambda k: k[1], True)}
        # sort by year (desc)
        facets['year'] = sorted(solr_facets['facet_ranges']['year']['counts'].items(),
                                lambda x, y: int(x) - int(y), lambda k: k[0], True)
        facet_gap = self.facet_params['f_year_facet_range_gap']
        if facet_gap > 1:
            facets['year'] = [('%s-%d' % (y[0], int(y[0])+facet_gap-1), y[1]) 
                              for y in facets['year']]
        pages = []
        for result in solr_response.results:
            page = models.Page.lookup(result['id'])
            if not page:
                continue
            words = set()
            coords = solr_response.highlighting[result['id']]
            for ocr in self._ocr_list:
                for s in coords.get(ocr) or []:
                    words.update(find_words(s))
            page.words = sorted(words, key=lambda v: v.lower())

            page.highlight_url = self.highlight_url(page.url,
                                                    page.words,
                                                    number, len(pages))
            pages.append(page)

        solr_page = Page(pages, number, self)
        solr_page.facets = facets
        return solr_page