Django Pagination Wrapper
For my current project perva.de, I’ve been playing with Django’s core pagination class django.core.paginator.ObjectPaginator. I wrote this wrapper that adds some nice functions that are helpful for rendering. Drop me some comments if you have ideas on how it could be better or “hey ro60 your an idiot you should do this instead” is always welcome too.
Please to enjoy… yes?!
"""
This object inherits from the Django core ObjectPaginator class and
provides some aditional helpful calculations for rendering pagination links
"""
from django.core.paginator import ObjectPaginator, InvalidPage
class NFPaginator(ObjectPaginator):
def _set_current_page(self, current_page):
try:
self._current_page = int(current_page)
except:
self._current_page = 0
def _get_current_page(self):
return self._current_page
def _get_display_page(self):
if self._current_page == 0:
return 1
else:
return self._current_page
def _get_next_page(self):
try:
if ObjectPaginator.has_next_page(self,self._current_page):
return self._current_page + 1
else:
return -1
except:
NFLogger.message(sys.exc_info(),"exception")
def _get_previous_page(self):
try:
if ObjectPaginator.has_previous_page(self,self._current_page):
return self._current_page - 1
else:
return -1
except:
NFLogger.message(sys.exc_info(),"exception")
def get_page(self, page_number):
#if the page is invalid then we get the first page
try:
return ObjectPaginator.get_page(self,page_number)
except InvalidPage:
self._current_page = 0
return ObjectPaginator.get_page(self,self._current_pager)
def render_next(self):
return ObjectPaginator.has_next_page(self,self._current_page)
def render_previous(self):
return ObjectPaginator.has_previous_page(self,self._current_page)
display_page = property(_get_display_page)
current_page = property(_get_current_page,_set_current_page)
next_page = property(_get_next_page)
previous_page = property(_get_previous_page)
Then in your view
from pervade.netflippers import NFPaginator
def index(request):
if 'page' in request.GET:
page = request.GET['page']
else:
page = 0
paginator = NFPaginator(Bookmark.objects.all().order_by(’-created_at’), 2,0)
paginator.current_page = page
latest_bookmark_list = paginator.get_page(page)
return render_to_response(’bookmarks/index.html’, {’latest_bookmark_list’: latest_bookmark_list, ‘paginator’:paginator}, context_instance=RequestContext(request))
This all makes rendering a template allot simpler. Here is a link to a template partial that you can use.
P.S. There are calls to my logger class in here as well. Feel free to rip them out if you wish OR better yet include the logger as well.
Thx to Timmah for the comments. I’ve edited the get_page method to fix the blind page display issue.

January 7th, 2008 at 4:03 pm
I just needed pagination for the first time with Django and this
sounded like a pretty cool little wrapper. One little thing I noticed
and changed.
You blindly display whatever page the users requests. If you have
three pages and they put in page=14, then current_page is 14, but you
are displaying the first page. So, in the get_page method under the
except block I just set _current_page to page_number.
Well, ok two things, I didn’t like displaying “page 1 of x” when
page=1 since the pagination is 0 based. I just blindly increment
the page and then make sure it isn’t greater than self.pages.
This is a really good start on removing a lot of the extra code when
dealing with pagination in templates. If I get around to adding in
a configurable list display of page navigation more than next/previous,
I’ll be sure to let you know.
Thanks
January 7th, 2008 at 8:13 pm
You are correct on both counts. The displaying page 1 for 0
indexed page count was a design decision on my part as I
felt it was more aesthetically pleasing. I can see your point
though. I should most likely add in a config flag for that.
Also the blindly displaying the page num was an oversight.
I’ve updated the code to deal with that now. Thx for the
heads up.
Please do send along a link if you add the extra parts in you
mentioned as I think that would be very cool.
August 4th, 2008 at 12:07 pm
[...] release of 1.0. So I did a bit of digging into the new pagination code to see if I could rework my wrapper class to work with the new release. It turns out that with the updates there really is no good reason to [...]