Status: | Work in progress |
---|
We start where the MovieDemo left off. See the ToscaSample tutorial or download the zipped ToscaWidgetsFormsExample (TODO: must be recreated, not currently available).
To have some sample data to work with, let’s populate the database
with some movies. Add these lines to websetup.py
(above
transaction.commit()):
movieDatas = [["Into the Wild", 2007],
["The Big Lebowsky", 1998],
["Pulp Fiction", 1994],
["Dead Man", 1995],
["Night on Earth", 1991],
["Genova", 2008],
["Snatch", 2000]]
movies = []
for data in movieDatas:
movie = Movie()
movie.title = data[0]
movie.year = data[1]
model.DBSession.add(movie)
After you set up your application and restart the server you should now have seven movies listed.
paster setup-app development.ini
paster serve --reload development.ini
With a model and some data set up, add webhelpers.paginate
to your
controller, and create an instance of paginate.Page
that you pass
to the template.
Import paginate in your controllers/root.py
and modify the
list()
method to look like this:
from webhelpers import paginate
@expose("toscasample.templates.movie_list")
def list(self, page=1):
"""List and paginate all movies in the database"""
movies = DBSession.query(Movie)
currentPage = paginate.Page(movies, page, items_per_page=5)
return dict(movies=currentPage.items, page='ToscaSample Movie list', currentPage=currentPage)
This creates and passes a paginate.Page
object to our template, so
we can use it there to access a pager()
.
The subset of items that should be displayed for the current page we
get from currentPage.items
and display them in the template like
we normally would.
Now the pagination can be displayed in the template like this:
Template code in templates/movie_list.html
:
<p class="pagelist">${currentPage.pager()}</p>
Now we add some padding to the pagelist and make it centered.
Create a file pagination.css in your public/css/ directory with the following contents and include it in style.css:
CSS in public/css/style.css
:
@import url("pagination.css");
CSS in public/css/pagination.css
:
.pagelist strong {
padding: 5px;
}
p.pagelist {
text-align: center;
}
Your movie listing should now look something like this:
TurboGears provides a convenient paginate() decorator that you can
combine with expose(). To use it, you simply have to pass it the
name of a collection to paginate. In controller/root.py
:
from tg.decorators import paginate as paginatedeco
@expose("toscasample.templates.movie_list_deco")
@paginatedeco("movies", items_per_page=5)
def decolist(self):
"""List and paginate all movies in the database using the
paginate() decorator."""
movies = DBSession.query(Movie)
return dict(movies=movies, page='ToscaSample Movie list')
In your template, you can now use the collection direction since it will be trimed to only contain the current page. You will also have have a basic page navigation with ${tmpl_context.paginators.movies.pager()}:
<ol>
<li py:for="movie in movies" py:content="movie">Movie title and year</li>
</ol>
<p class="pagelist">
${tmpl_context.paginators.movies.pager()}
</p>
Demonstrating some more formating arguments:
${currentPage.pager(format='~3~', page_param='page', show_if_single_page=True)}
See http://www.pylonshq.com/docs/en/0.9.7/thirdparty/webhelpers/paginate/ for more details.
You can pass any number of arguments to the pager function and they will be used to create the links to the other pages.
For example with the following code:
${currentPage.pager(param1='hi', param2='man')}
the resulting links will be:
and so on…
By default the url used to generate links will be the same of the page where the paginated data will be visible, this can be changed by passing the link argument to the pager function:
${currentPage.pager(link='/otherlink', param1='hi', param2='man')}
and the resulting link will be generated by using the provided url:
Let’s add previous and next links:
Modify the pagelist in templates/movie_list.html
to look like
this:
<p class="pagelist">
<a class="prevPage" href="/list?page=${currentPage.previous_page}"><<<</a>
${currentPage.pager(format='~3~', page_param='page', show_if_single_page=True)}
<a class="nextPage" href="/list?page=${currentPage.next_page}">>>></a>
</p>
Functional, but not very pretty:
Let’s add some images:
Note
These images are public domain - feel free to use them any way you like. Different sizes and the source *.psd are included in the project file.)
Change the pagelist code in templates/movie_list.html
:
<p class="pagelist">
<a class="prevPage" href="/list?page=${currentPage.previous_page}"> </a>
${currentPage.pager(format='~3~', page_param='page', show_if_single_page=True)}
<a class="nextPage" href="/list?page=${currentPage.next_page}"> </a>
</p>
Add this to the CSS in public/css/pagination.css
:
a.prevPage {
background: url("/images/icons/png/32x32/arrow-left.png") no-repeat;
padding-left: 18px;
padding-right: 18px;
padding-top: 12px;
padding-bottom: 15px;
text-decoration: none;
}
.nextPage {
background: url("/images/icons/png/32x32/arrow-right.png") no-repeat;
padding-left: 18px;
padding-right: 18px;
padding-top: 12px;
padding-bottom: 15px;
text-decoration: none;
}
And this is what the end result looks like: