Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #1745 (closed documentation: fixed)

Opened 11 years ago

Last modified 10 years ago

[Recipe] RESTful pagination using the @paginate decorator

Reported by: streawkceur Owned by: Chris Arndt
Priority: normal Milestone: 1.1.x bugfix
Component: Documentation Version: 1.0
Severity: normal Keywords: doc update
Cc:

Description

Originally, I wanted to post this at the Wiki-page  http://docs.turbogears.org/1.0/PaginateDecorator, but the comments are disabled and I cannot edit the page as it seems to be write-protected.

So I post it here. It's nothing much, just a little hint how to get around those ugly URL query parameters that @paginate generates.

Say have this simple controller

class Users(Controller):
    @expose(...)
    @paginate('users')
    def index(self):
        return dict(users=User.query())

${tg.paginate.get_href(page)} would generate an URL like this: /users?users_tgp_no=2&users_tgp_limit=5 That's not beautiful.

But it's quite simple to achieve pagination with URLs like these: /paginate1/page/2.

You just have to create an additional exposed method page that will "translate" the requested page into the desired kwarg and call the original method:

    @expose()
    def page(self, page):
        return self.index(users_tgp_page=page)

Basically that's it. But you cannot use paginate.get_href anymore. I generated the URLs manually in my (Genshi) template:

# Generate RESTful pagination URLs: /foo/bar/page/42
import cherrypy
base = cherrypy.request.path
if not base.endswith('/'):
    base += '/'
current_page_path = '/page/' + str(tg.paginate.current_page) + '/'
if base.endswith(current_page_path):
    base = base[:-len(current_page_path)+1]

You then just create links like this:

<a href="${base}page/$page" py:if="page != tg.paginate.current_page">$page</a>

Maybe anyone can make use of this (or add it to the Wiki) :)

P.S.: If you want a RESTful pagination for any other method than index, you have to create an additional controller with an index and page method and attach this controller to the parent.

Change History

comment:1 Changed 11 years ago by streawkceur

Can even be done without an additional method:

    @expose(..)
    @paginate('users')
    def index(self, user_id=None):
        if user_id is not None: # Show a specific user
            return self.show(user_id)
        return dict(users=User.query()) # Show all users

=>

    @expose(..)
    @paginate('users')
    def index(self, user_id=None, page=None):
        if user_id == 'page': # Paginate
            return self.index(users_tgp_no=page)
        elif user_id is not None: # Show a user
            return self.show(user_id)
        return dict(users=User.query()) # Show all users

And then use URLs like /users/page/123. This only adds two lines to your exposed method instead of 4 lines for an additional method (incl. blank line).

comment:2 Changed 11 years ago by streawkceur

On Mar 13, 3:32 pm, Thomas Wittek <streawkc...@googlemail.com> wrote:
> Can even be done without an additional method:
>    def index(self, user_id=None, page=None):
> And then use URLs like /users/page/123.

I had rejoiced (and posted) too soon. Unlike I assumed, CP doesn't use positional args for missing kwargs as Python does. So this doesn't work. :(

comment:3 Changed 11 years ago by Chris Arndt

  • Milestone set to __unclassified__
  • Summary changed from RESTful pagination using the @paginate decorator to [Recipe] RESTful pagination using the @paginate decorator

comment:4 Changed 10 years ago by jorge.vargas

  • Milestone changed from __unclassified__ to 1.x

comment:5 Changed 10 years ago by Chris Arndt

  • Type changed from enhancement to documentation
  • Milestone changed from 1.x to 1.1.x bugfix

comment:6 Changed 10 years ago by Chris Arndt

  • Status changed from new to closed
  • Resolution set to fixed
Note: See TracTickets for help on using tickets.