3

I'd like to implement pagination such that I can allow the user to choose the number of records per page such as 10, 25, 50 etc. How should I go about this? Is there an app I can add onto my project to do this?

Thanks

4 Answers4

5

Django has a Paginator object built into core. It's a rather straightforward API to use. Instantiate a Paginator class with two arguments: the list and the number of entries per "page". I'll paste some sample code at the bottom.

In your case you want to allow the user to choose the per-page count. You could either make the per-page count part of the URL (ie. your/page/10/) or you could make it a query string (ie. your/page/?p=10).

Something like...

# Assuming you're reading the Query String value ?p=
try:
    per_page = int(request.REQUEST['p'])
except:
    per_page = 25     # default value

paginator = Paginator(objects, per_page)

Here's some sample code from the Django doc page for the Paginator to better see how it works.

>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2)

>>> p.count
4
>>> p.num_pages
2
>>> p.page_range
[1, 2]

>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']
T. Stone
  • 19,209
  • 15
  • 69
  • 97
  • There's one bit I've realized I don't know how to do...the setting of the records per page works fine, just that the number of pages reverts back to the default once I go to the second page –  Nov 16 '09 at 19:00
  • 2
    Instead of a try/except you get use the accessor method and provide a default: `per_page = int(request.REQUEST.get('p', 25))` – Marshall May 11 '15 at 17:39
1

google on "django pagination" and make sure to use "covering index" in your SQL for efficient query.

Dor
  • 7,344
  • 4
  • 32
  • 45
0

T. Stone's answer covers most of what I was going to say. I just want to add that you can use pagination in Generic Views. In particular, you may find django.views.generic.list_detail.object_list useful.

You can write a small wrapper function that gets the number of objects to display per page from the request object, then calls object_list.

def paginated_object_list(request, page):

    my_queryset=MyModel.objects.all()
    #Here's T. Stone's code to get the number of items per page
    try:
        per_page = int(request.REQUEST['p'])
    except:
        per_page = 25     # default value

    return object_list(request, queryset=my_queryset, 
                                     paginate_by=per_page, page=page)

Then, the context for your template will contain the variables,

  • paginator: An instance of django.core.paginator.Paginator.
  • page_obj: An instance of django.core.paginator.Page.

and you can loop through page_obj to display the objects for that page.

Wladimir Palant
  • 56,865
  • 12
  • 98
  • 126
Alasdair
  • 298,606
  • 55
  • 578
  • 516
0

What does need? Well.

You can add custom control for change_list.html, for pagination block for example.

This will be reload list page with get parameter per_page for example with certain value onchange event.

For your adminModel you must override changelist_view method where you must handle get parameter and set this value as list_per_page field value.

def changelist_view(self, request):
    if request.GET.get('per_page') and int(
            request.GET.get('per_page')) in CHANGELIST_PERPAGE_LIMITS:
        self.list_per_page = int(request.GET.get('per_page'))
    else:
        self.list_per_page = 100
    extra_context = {'changelist_perpage_limits': CHANGELIST_PERPAGE_LIMITS,
                     'list_per_page': self.list_per_page}
    return super(mymodelAdmin, self).changelist_view(request, extra_context)

I use extra_context for access to this values into template. Maybe there is more neat approach to access i don't know :-)