Paging with reverse cursors in appengine
Asked Answered
R

2

6

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.

Result answered 18/12, 2012 at 11:13 Comment(0)
T
3

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.

Terrorstricken answered 20/12, 2012 at 9:52 Comment(4)
There are cases when the first page is queried with a cursor, for example, when you go to page 2 and return back to page 1, you get page 1 with a cursor. And if you depend on that, you would then be on page 1 showing that there is a previous page just because you have a cursor.Result
How did you mannage to create a cursor that points before the first Element of a List? Ive tried it, but i can only create a cursor after fetching at least one element - and therefor getting a cursor pointing after this element (So querys using this cursor would always loose this first element)Crabby
I get that cursor after running a query on the reversed-order query. Actually, you're right, I'm strictly not getting a cursor that points before the first element, I'm getting a cursor someplace after the first element in the reverse query, which corresponds to an element near the end of the forward query. So you get the illusion that it is before the first element if you think that the list is circular, but it is not. Probably, this could be solved if I started the query supplying a cursor to the first element of the forward query, but I don't know how to do that.Result
Does this cursor work in the forward query? I havnt tried, but from what i get from the docs it shouldnt. As said, im not sure if its possible to create a cursor pointing in front of the first element. However, using the reverse sort order trick you can use more to determine if there are elements before the ones on the current page (and therefor there must be at least one previous page)Crabby
R
-2

I have a workaround and not the best solution. it is baiscally redirecting back to the previous page.

<a href="javascript:history.back()">Previous</a>

I think PagedQuery has the capability but still waiting for someone to post a more comprehensive tutorial about it.

Romanticize answered 21/8, 2014 at 19:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.