Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paging with reverse cursors in appengine

I am trying to get forward and backwards pagination working for a query I have on my app.

I have started with the example at: https://developers.google.com/appengine/docs/python/ndb/queries#cursors

I would expect that example to do a typical forward/back pagination to create cursors that you can pass to your template in order to be used in a subsequent request for the page after/before the current one. But what it is doing is getting cursors for the same page, one from the beginning and the other from the end (if I have understood correctly).

What I want is a cursor to the beginning of the following page, and a cursor to the beginning of the previous page, to use in my UI.

I have managed to almost get that with the following code, based on the mentioned example:

    curs = Cursor(urlsafe=self.request.get('cur'))

    q = MyModel.query(MyModel.usett == usett_key)
    q_forward = q.order(-MyModel.sugerida)
    q_reverse = q.order(MyModel.sugerida)

    ofus, next_curs, more = q_forward.fetch_page(num_items_page,
                                                 start_cursor=curs)

    rev_cursor = curs.reversed()
    ofus1, prev_curs, more1 = q_reverse.fetch_page(num_items_page,
                                                 start_cursor=rev_cursor)

    context = {}

    if more and next_curs:
        context['next_curs'] = next_curs.urlsafe()

    if more1 and prev_curs:
        context['prev_curs'] = prev_curs.reversed().urlsafe()

The problem, and the point of this question, is that I use more and more1 to see if there is a next page. And that is not working in the backwards sense. For the first page, more1 is True, in the second page more1 is False, and subsequent pages give True.

I would need something that gives False for the first page and True for every other page. It seems like this more return value is the thing to use, but maybe I have a bad Query setup, or any other thing wrong.

Thanks everyone!

Edit: Since I didn't find a simple solution for this, I switched to using ndbpager.

like image 390
payala Avatar asked Nov 12 '22 15:11

payala


1 Answers

There's no such thing. You know thats theres (at least) one page before the current page if you started the query with a cursor (the first page usualy dosnt have a cursor). A common trick to access the previous page is inverting the sort-order.

If you have a list, sorted by creationdate desc, you could take the creationdate of the first element of your current page, query for elements with creationdate < this creationdate using inverted sort order. This will return the oldest elements which are newer then the given creationdate. Flip the list of retrived elements (to bring them into the correct order again) and there you have the elements of the page before, without using a cursor.

Note: this requires the values of your sortorder beeing distinct.

In some cases, its also possible to use a prebuild index allowing random-access to different pages, see https://bitbucket.org/viur/server/src/98de79b91778bb9b16e520acb28e257b21091790/indexes.py for more.

like image 158
T. Steinrücken Avatar answered Nov 15 '22 11:11

T. Steinrücken