A Civilized Way Display Lots Of Data

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).

Bookmark and Share

Related posts:

  1. My PyCon APAC 2011 Presentation: Optimizing Media Performance with django_compressor
  2. Working with files in Django – Part 1
  3. Working with files in Django – Part 2
  4. Working with files in Django – Part 3
  5. Drawing Gradients with PyGame

Tags: , , ,

2 Responses to “A Civilized Way Display Lots Of Data”

  1. Efe says:

    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.

  2. @Efe: There’s little known site named Google, if you run a query on that you’ll see a nice example of pagination.