Django is a civilized way to build web applications. Pagination is a civilized way to display lots of data. There are still people developing websites with tens of thousands of items crammed in a single page. Even if you use JavaScript to paginate client-side, never ending download results in poor user experience.
Django has pagination support built-in. All you need to do is to wrap your QuerySet with django.core.paginator.Paginator and add paginator.page(some_page_number) to your template context. Then you can use attributes/methods such as has_next and num_pages or iterate over page_range to display your pagination navigation. To access items in current page you can use object_list, which is in fact a QuerySet sliced with correct limits. That also means; only those items that you want to display are queried. It’s all documented well as usual.
Django-pagination Takes It One Step Further
In my opinion pagination belongs to presentation. If you have many queries/views to paginate, you might find yourself repetitively writing pagination code. You can move all your pagination code into the template with django-pagination. This is accomplished with a middleware and a set of template tags.
With django-pagination you can paginate your results like this:
{% autopaginate object_list %}
{% for object in object_list %}
{{ object }}
{% endfor %}
{% paginate %}
autopaginate tag replaces your QuerySet with a paginator and paginate tag renders pagination/pagination.html template with correct values.
You can download django-pagination from Google Code, but appereantly development is moved to GitHub. I wish there was a message left on the Google Code page.
A Little SEO Shouldn’t Hurt
When you have a paginated view, you usually display the results of the first page if the pagination variable is missing. As a result /some_view/ and /some_view/?page=1 return identical responses. This might be interpreted by search engines as a duplicate. My solution for this is to redirect the first page to the page without a page variable:
1 from django.http import HttpResponsePermanentRedirect 2 from pagination.middleware import PaginationMiddleware 3 4 class SEOPaginationMiddleware(PaginationMiddleware): 5 def process_request(self, request): 6 if request.method == 'GET': 7 try: 8 page = int(request.GET['page']) 9 except (KeyError, ValueError, TypeError): 10 page = None 11 if page == 1: 12 params = request.GET.copy() 13 del(params['page']) 14 path = request.path 15 if params: 16 path += '?' + params.urlencode() 17 return HttpResponsePermanentRedirect(path) 18 return super(SEOPaginationMiddleware, self).process_request(request)
This works only if your page variable is an URL parameter (i.e. you are using GET).
Related posts:
- My PyCon APAC 2011 Presentation: Optimizing Media Performance with django_compressor
- Working with files in Django – Part 1
- Working with files in Django – Part 2
- Working with files in Django – Part 3
- Drawing Gradients with PyGame
Tags: django, pagination, python, template
Dear Muhuk,
Can you direct me to a good example of “Paginated” page?
Then I may have a little chance of understanding how it handles lots of data.
Thanks.
@Efe: There’s little known site named Google, if you run a query on that you’ll see a nice example of pagination.