NinjaCipher:-*-:ro60

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.

Del.icio.us Digg BlinkList Furl Ma.gnolia Reddit Spurl

3 Responses to “Django Pagination Wrapper”

  1. timmah Says:

    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

  2. mattd Says:

    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.

  3. Ninjacipher » Blog Archive » New Django Paginator Example Says:

    [...] 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 [...]

Leave a Reply

You must be logged in to post a comment.