Pagination snippets

280 views
Skip to first unread message

jchris

unread,
Apr 8, 2008, 10:39:27 PM4/8/08
to Google App Engine
I've gotten to the point in my application that I need to paginate the
user data. I'm a python noob so while I can write something, I might
be better off cargo-culting. Is there a good place to go to look for
code that will work with webapp? I don't really want or need a whole
framework.

Maybe someone should setup a github project for useful snippets.

ma...@google.com

unread,
Apr 9, 2008, 2:24:04 PM4/9/08
to Google App Engine
Hi,
Pagination is definitely possible with Google App Engine, and you can
use our query.fetch() method documented here to implement it:
http://code.google.com/appengine/docs/datastore/queryclass.html#Query_fetch

An incomplete quick coding example to retrieve story items from your
datastore might look something like this, of course it would need to
be modified based on your specific application:

def generate_stories(self, query, template_values={}):
"""Generates a page from a given Stories query.

We handle different output types (Atom, HTML, etc) and paging so
that
the pages that handle lists of stories do not need to replicate that
logic.

Args:
query: a configured datastore query that will generate a list of
stories
template_values: additional values to expand into the
template
"""
# Move to the spot in the iterator specified by the start and num
# arguments in the URL
start = self.get_arg_range('start', min_value=0, max_value=1000,
default=0)
num = self.get_arg_range('num', min_value=1, max_value=100,
default=10)

# include one more story to see if we have another page, it is
faster
# to include one more story if it is there, and then throw it away
for
# the page, than issue a second query to test if there are more
stories
stories = query.fetch(num+1, start)
# was the extra story retrieved? If so, there are more stories to go
more_stories = len(stories) > num
# throw away the extra story for now
stories = stories[:num-1]
# if this is not a 0 start, there are previous stories too
prev_stories = start > 0
# and pass in the actual number of stories that will be displayed
disp_end = max(len(stories), 0) + start + 1
disp_start = start + 1

-Marzia

Mike Axiak

unread,
Apr 9, 2008, 2:28:37 PM4/9/08
to Google App Engine
Django comes with a pagination utility built in [1]. I believe it's
fairly separate from the rest of the project, so you can just::

from django.core.paginator import ObjectPaginator, InvalidPage

And follow the documents. Just note: Even though they show QuerySets,
I believe it will work with any iterator. Also, the SVN version of
Django has a newer and better paginator.

Cheers,
Mike

1: http://www.djangoproject.com/documentation/0.96/models/pagination/

Jared

unread,
Apr 21, 2008, 2:57:27 AM4/21/08
to Google App Engine
Would it be possible to get a more complete example of how this
works? Like maybe in conjunction with the guestbook app or something?

On Apr 9, 2:24 pm, ma...@google.com wrote:
> Hi,
>  Paginationis definitely possible with Google App Engine, and you can
> use our query.fetch() method documented here to implement it:http://code.google.com/appengine/docs/datastore/queryclass.html#Query...

Venkatesh Rangarajan

unread,
Apr 22, 2008, 11:19:38 AM4/22/08
to google-a...@googlegroups.com
Jared,

here is a working example. Let me know if it works for you.

My Handler (from django.core.paginator import ObjectPaginator, InvalidPage)

----------------------------------------
class ListAll(webapp.RequestHandler):
def get(self):
#visitors=db.GqlQuery("SELECT * FROM Visit")
visitors=Visit.all()
visitors.order('-date')
visitors=visitors.fetch(limit=100)
paginate_by =10
paginator = ObjectPaginator(visitors, paginate_by)
#self.response.out.write(paginator.pages)
try:
page = int(self.request.get('page', 0))
visits = paginator.get_page(page)
except InvalidPage:
raise http.Http404
template_values = {
'visits': visits,
'is_paginated' : True,
'results_per_page' : paginate_by,
'has_next': paginator.has_next_page(page),
'has_previous': paginator.has_previous_page(page),
'page': page + 1,
'next': page + 1,
'previous': page - 1,
'pages': paginator.pages,
'action':action,
}
path = os.path.join(os.path.dirname(__file__), 'show.html')
self.response.out.write(template.render(path, template_values))
----------------------------------------

Here is my Template HTML
----------------------------------------------------
{% if has_previous %}
<a href="?q=ip&page={{ previous }}">
< < previous {{ page }}
{% endif %}
{% if has_next %}
<a href="?q=ip&page={{ next }}"> next >>
{% endif %}
</tr></td>
{% endifequal %}
------------------------------------------------------

Jared

unread,
May 23, 2008, 4:21:48 PM5/23/08
to Google App Engine
Finally got to playing around with this. Just something to point
out...

Rather than displaying a 404 page when the page= number is set out of
bounds, you could do something like this...

try:
page = int(self.request.get('page',0))
visits = paginator.get_page(page)
except:
visits = paginator.get_page(int(paginator.pages-1))

Then, no matter how far off the deep end page is set to (20000 or
something), the user will just get the last page. I kind of like that
better than a 404 page, but that's personal preference.

On Apr 22, 11:19 am, "Venkatesh Rangarajan"
Reply all
Reply to author
Forward
0 new messages