22

I'm trying to figure out how to show something like "Showing 1-10 of 52" using django pagination in my templates.

I accomplished the pagination itself but nothing comes to my mind about this requirement.
Any ideas?

Mel
  • 5,837
  • 10
  • 37
  • 42
webgonewild
  • 245
  • 1
  • 2
  • 6

5 Answers5

81

As the documentation shows, Paginator objects have a count attribute which shows the total number of objects across all pages (in the queryset or list they're paginating) and Page objects have start_index() and end_index() methods.

So, assuming you pass the page to the template context:

Showing {{ page.start_index }}-{{ page.end_index }} of {{ page.paginator.count }}
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • 5
    This was very helpful - thanks. Only note I would have is that by default in a `ListView` the object is called `page_obj` rather than `page`. – BigglesZX May 02 '16 at 07:41
  • I got this error. jinja2.exceptions.UndefinedError: 'flask_sqlalchemy.Pagination object' has no attribute 'paginator' – Sathiyakugan Mar 30 '19 at 07:13
  • 1
    Yeah, it's easy to confuse the total number of records in the queryset with the total number of records in the model. If you want the total number of records in the model you need to pass that separately, `page.paginator.count` will supply the total from the queryset. – yekta Jul 24 '20 at 03:55
  • Total number of records in model is paginator.count not page.paginator.count. In reply to @yekta – d1spstack Jan 14 '22 at 14:31
3

The django Paginator object has a num_pages property. In your view, you can just pass the correct data to your template and show it there.

So as an (rough) example:

view

 current_page = ## input param 
 items_per_page = 10  
 paginator = Paginator(result, items_per_page)    

 ...
 return render_to_response('template.html', 
   {
     'num_pages': paginator.num_pages,
     'start_count': items_per_page * current_page + 1,
     'end_count': (items_per_page * current_page + 1) + len(paginator(current_page).object_list)
     'items_per_page':  items_per_page
   }

template

showing {{start_count} - {{end_count}} of {{num_pages}}

(I wrote this code without the benefit of a compiler, so test it)

marcc
  • 12,295
  • 7
  • 49
  • 59
  • 1
    just send paginator to template and then access pagintator properties like: {{ offers.previous_page_number }}, {{ offers.next_page_number }}, {{ offers.paginator.count }} – gerpaick Nov 11 '17 at 13:41
2

You'll need to do something moderately more complex behind the scenes. And please note that while I am a python dev, i've been using werkzeug and jinja2 for a long time now and so my django syntax is a little rusty. Also this was dry-coded (as in I just typed it here in the browser) and should be tested to make sure that it works as intended.

Generally I'll create a pagination object, and pass it in a query object that isn't filtered by pages, you can also tell it how many per page and what page you're on.

So something vaguely similar to:

Paginator(query, objects_per_page, current_page_number)

And then pass the resulting paginator object into the template.

Inside the paginator's init you'd want to do something similar to:

def __init__(self, query, objects_per_page, current_page_number):
    self.total = query.count()

    self.per_page = objects_per_page
    self.current_page_number = current_page_number
    self.lower_limit = objects_per_page * current_page_number
    self.upper_limit = objects_per_page * (current_page_number + 1)

    if self.upper_limit > self.total:
        self.upper_limit = self.total

    self.objects = query[self.lower_limit - 1:self.upper_limit - 1]

Then in the template you'd do something like

Showing {{paginator.lower_limit}}-{{paginator.upper_limit}} of {{paginator.total}}

And later when you are ready to iterate over the objects you could just iterate over paginator.objects.

I hope that gives you a general idea of how you can cleanly do this.

Bryan McLemore
  • 6,438
  • 1
  • 26
  • 30
  • Peharps its better to subclass the built in django.core.paginator.Paginator class to add the lower_limit and the upper_limit attributes. – webgonewild Nov 06 '09 at 18:38
  • Very possible, I've not used django's in quiet a while. Also the num_pages seems to be an invalid stat from where I sit. You seem to want the total number of objects, not the total number of pages, there may be another solution for that however in django's paginator. – Bryan McLemore Nov 06 '09 at 18:43
1
paginator = Paginator(query, settings.SEARCH_DATA_PER_PAGE)

For number of Pages :

num_of_pages = paginator.num_pages

For total number of items across all pages :

num_of_objects = paginator.count

You can calculate number of items per page from this data.

Sumit Badsara
  • 769
  • 9
  • 23
-1
totalPages = math.ceil(float(totalRecords)/recordsPerPage)

or

paginatorInstance.num_pages # this is there by default

Wasn't that hard, was it?

Prody
  • 5,182
  • 6
  • 44
  • 62