February 3, 2011

Django AJAX Tutorial Part 2 - ajax pagination #1

Hello again. For some time now I will continue my tutorials concerning using AJAX with Django. I have received few requests to write about pagination next, so this is the topic for today's post. In the last months I went through few different methods of ajax pagination. I will try to show you at least three but each in different post.
The one I'm going to write about today was the first I've tried. It uses built-in django generic views.

Let's begin with views, as they're most important here :

#!/usr/bin/env python
# encoding: utf-8
import math

from django.conf import settings
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.generic.list_detail import object_list

from models import Friend

#we're importing LazyEncoder written in first part of Django - Ajax tutorial
from tutorial_utils import LazyEncoder

# 'global' variable storing amount of objects per page
per_page = 4

def index(request):
    #we take all object's that we want to be paginated
    friends = Friend.objects.all()
    #count them
    count = friends.count()
    #count amount of pages
    pages = math.ceil(count / float(per_page))
    pages = int(pages)
    #create list of pages
    pages = range(1, pages+1)

    #if amount of objects is smaller than per_page variable, we create only one page
    if count <= per_page:
        pages = 1

    return render_to_response('pagination/index1.html', {
            'pages': pages, 'count': count
            }, context_instance=RequestContext(request))

#this view will create us list of friends
def friends_list(request):

    #first take all objects       
    friends = Friend.objects.all()   
    template = 'pagination/friends1.html'
    #using generic view display list of objects paginated by 'pagenate_by' elements. Good part about using object_ilst generic view is that it automatically paginates elements and then allows showing the desired page by accessing 'page_with_objects_url' + ?page=number_of_page. we will take advantage of this in our example.

    return object_list(request, 
        queryset = friends,
        paginate_by = per_page,
        template_name = template,
        extra_context = {}
Ok so idea is that we use generic view 'object_list' that paginates objects for us and creates links for each page. So now let's take a look at urls :
from django.conf.urls.defaults import *
from views import *

urlpatterns = patterns('',
    url(r'^start$', index, name="index"),
    url(r'^friends_list/$', friends_list),
Nothing complicated here. I'm not using named urls here to make it easier to understand in the javascript part. Next thing are the templates. First I'll present the one responsible for creating list of friends (props go to michalbe for lending me his twitter avatar :)) :
    {% for f in object_list %}

  • {{ f.name }}

  • {% endfor %}
And main template with the pagination part :


{% ifequal count 0 %}

You have no friends.

{% else %}
    {% if pages %} {% ifequal pages 1 %}
  • {{pages}}
  • {% else %} {% for i in pages %}
  • {{i}}
  • {% endfor %}{% endifequal %}{% endif %}
{% endifequal %}
As you can see here I've included pagination in this template (so that it won't be refreshed each time user changes page). If number of pages is none, we're showing appropriate alert. Else if there is only one page, we're not using loop because we would get two pages in fact (page 0 and 1). If there are more pages, we're just going through a for loop adding each of them and setting their id's to page number. we will need that in the js part which comes next. Once again I'm using jQuery here to keep it simple and take advantage of it's built in function 'load' that reads content under specified address and then includes it html of our page :

Ok, so that's the whole code for today. As previously I've created working example for you under this link : http://samples.fromzerotocodehero.x14.eu/pagination1/start And here's a downloadable package (soon I'll move all of this to my git account I promise :) ): http://ofcjs.x14.eu/pagination1.zip