I just started using this class in my blog software. It requires two queries, one to get the main page of results plus the index of the next page and one to get the index of the previous page. Since it requires two queries per request, you definitely want to use memcache to save the results. It works well with non-consecutive index numbers, but it does only provide Next and Previous pages; it doesn't provide for directly indexing page N.
I'd love to hear any thoughts on this approach and feedback, and please feel free to use to code in your own app. #Copyright 2008 Adam A. Crossland # #Licensed under the Apache License, Version 2.0 (the "License"); #you may not use this file except in compliance with the License. #You may obtain a copy of the License at # #http://www.apache.org/licenses/LICENSE-2.0 # #Unless required by applicable law or agreed to in writing, software #distributed under the License is distributed on an "AS IS" BASIS, #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #See the License for the specific language governing permissions and #limitations under the License. from google.appengine.ext import db import copy class PaginatedList(list): def __init__(self, *args, **kw): list.__init__(self, *args, **kw) self.prev_index = None self.next_index = None self.curr_index = None class Paginator: "A class that supports pagination of AppEngine Models" def __init__(self, page_size, index_field): self.page_size = page_size self.index_field = index_field def get_page(self, query=None, start_index=None, ascending=True): "Takes a normal AppEngine Query and returns paginated results." fetched = None # I need to make a copy of the query, as once I use it to get the main # collection of desired records, I will not be able to re-use it to get # the next or prev collection. query_copy = copy.deepcopy(query) if ascending: # First, I will grab the requested page of entities and determine # the index for the next page filter_on = self.index_field + " >=" fetched = PaginatedList(query.filter(filter_on, start_index).order(self.index_field).fetch(self.page_size + 1)) if len(fetched) > 0: # The first row that we get back is the real index. fetched.curr_index = fetched[0].index if len(fetched) > self.page_size: fetched.next_index = fetched[-1].index del(fetched[-1]) # Now, I will try to determine the index of the previous page filter_on = self.index_field + " <" previous_page = query_copy.filter(filter_on, start_index).order("-" + self.index_field).fetch(self.page_size) if len(previous_page) > 0: fetched.prev_index = previous_page[-1].index else: # Follow the same logical pattern as for ascending, but reverse # the polarity of the neutron flow filter_on = self.index_field + " <=" fetched = PaginatedList(query.filter(filter_on, start_index).order("-" + self.index_field).fetch(self.page_size + 1)) if len(fetched) > 0: # The first row that we get back is the real index. fetched.curr_index = fetched[0].index if len(fetched) > self.page_size: fetched.next_index = fetched[-1].index del(fetched[-1]) # Determine index of previous page filter_on = self.index_field + " >" previous_page = query_copy.filter(filter_on, start_index).order(self.index_field).fetch(self.page_size) if len(previous_page) > 0: fetched.prev_index = previous_page[-1].index return fetched --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Google App Engine" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en -~----------~----~----~----~------~----~------~--~---
