validate the css validate the xhtml

HackerMoJo.com


Ceci n'est pas une blog
by Glenn Franxman, Django Developer / Stunt Programmer.

Holy Paginator, Batman!

posted: 2007-03-28 03:08:08 perma-link, RSS comments feed

I got this pic from allthingsukranian.com - a site that sells handmade ukranian crafts in the US.

Django has a really great pagination framework built in, but it does encourage you to write code like:

entries = MtEntry.objects.filter( entry_status__exact = 2).order_by( '-entry_created_on' )
paginator = ObjectPaginator(entries, 5)
page = int( request.GET.get('page', 1) )
object_list = paginator.get_page(page - 1)
c = RequestContext(request, {
'%s_list' % template_object_name: object_list,
'is_paginated': paginator.pages > 1,
'results_per_page': paginate_by,
'has_next': paginator.has_next_page(page - 1),
'has_previous': paginator.has_previous_page(page - 1),
'page': page,
'next': page + 1,
'previous': page - 1,
'last_on_page': paginator.last_on_page(page - 1),
'first_on_page': paginator.first_on_page(page - 1),
'pages': paginator.pages,
'hits' : paginator.hits,
})

That's actually a little simplified -- it doesn't handle any cases where bad data was passed in, etc. I took that from the generic view code in django's trunk and cut it down. I just want to demonstrate how much the view writer needs to account for the work to be done in the template and the tip-toeing around off-by-one errors that have to be carefully avoided.

Here's what I've done to simplify that on my way to creating the holy grail of pagination productivity:


class pager( ObjectPaginator ):
def set_page( self, p ):
if p >= 0 and p < self.pages:
self.current_page = p
else:
self.current_page = 0
def this_page( self ):
return [ itm for itm in self.get_page( self.current_page ) ] # trn this from a set to a list
def has_next( self ):
return self.has_next_page( self.current_page )
def has_prev( self ):
return self.has_previous_page( self.current_page )
def next_page( self ):
return self.has_next() and self.current_page + 1 or 0
def prev_page( self ):
return self.has_prev() and self.current_page - 1 or 0

So now, my view code looks like:

entries = MtEntry.objects.filter( entry_status__exact = 2).order_by( '-entry_created_on' )
paginator = pager( entries, 5 )
paginator.set_page( int( request.GET.get( 'page', '0' ) ) )
c = Context( { 'entries': paginator.this_page(), 'paginator': paginator} )


and my templates look like:

<ul>
{% for item in paginator.this_page %}
<li>{{ item }}</li>
{% endfor %}
</ul>
<p>
There are {{ paginator.hits }} entries.
{% if paginator.has_prev %}<a href="?page={{paginator.prev_page}}">Previous</a> {% endif %}
{% if paginator.has_next %}<a href="?page={{paginator.next_page}}">More</a> {% endif %}
</p>

As you can see: very coder friendly and very template designer friendly. In fact, I can use that template as my jumping off point for any paginated list.

In general, my strategy is to make the view code responsible for fetching the core object(s) for a page and not worry about the details of the actual page. How pagination is handled is left up to the page designers who have now been given a tool for managing pagination. I believe my departure on this from the general django communities design patterns stems from most django work being handled by python developers, whereas I have an actual separation of python and template development.


Comments

1#1

Wolf49 commented, on October 22, 2009 at 5:07 a.m.:

A home can still have attractive vegetation, including trees and shrubs and still meet defensible space standards. ,

3#3

Aicha commented, on September 21, 2012 at 6:35 a.m.:

01/02/2007 Patrick Reagan After reading a post from local blggeor Matthew Van Boogart, I took a look at Bob Aman's FeedTools to pull in RSS feeds from Google News to support a client project that I'm working on. The process required to consume the feed was really trivial after a couple hours I had a barebones feed reader complete with unit and functional tests.

4#4

hkxoxjuvtf commented, on September 22, 2012 at 1:13 a.m.:

mv8PvP <a href="http://ltifrpmzkidu.com/">ltifrpmzkidu</a>

Post a comment


Based upon your reading habits, might I recommend:

Or, you might like:

Copyright © 2003,2004,2005,2006,2007,2008 GFranxman. All Rights Reserved


hosting: slicehost.com. powered by: django. written in: python. controlled by: bzr. monsters by: monsterID.

You've been exposed to: {'Science & Technology': 1}