There are several ways to paginate items. The simplest is by using the paginate
method
on the Query Builder or an ORM query.
The paginate
method provided by Orator automatically takes care of setting
the proper limit and offset based on the current page.
By default, the current page needs to be specified.
However, as we’ll see it later, you can create a custom current page resolver.
First, let’s take a look at calling the paginate
method on a query generated by the query builder:
users = db.table('users').paginate(15, 2)
In this example, the first argument passed to paginate is the number of items we would like displayed “per page”
and the second is the current page we want to display. So, in this case, we want to retrieve 15
items on page 2
.
Warning
Currently, pagination operations that use a group_by
statement cannot be executed efficiently by Orator.
If you need to use a group_by
with a paginated result set, it is recommended that you query the database
and create a paginator manually.
You can also paginate ORM queries. In this example, we will paginate the User
model with 15
items per page
for the second page. As you can see, the syntax is nearly identical to paginating query builder results:
all_users = User.paginate(15, 2)
Of course, you can call paginate after setting other constraints on the query:
some_users = User.where('votes', '>', 100).paginate(15, 2)
If you only need “Next” and “Previous” pages in your pagination,
you have the option of using the simple_paginate
method to perform a more efficient query.
some_users = User.where('votes', '>', 100).simple_paginate(15, 2)
Sometimes you may wish to create a pagination instance manually, passing it a list of items.
You can do so by creating either a Paginator
or a LengthAwarePaginator
instance, depending on your needs.
The Paginator
class does not need to know the total number of items in the result set;
however, because of this, the class does not have methods to retrieve the index of the last page.
The LengthAwarePaginator
accepts almost the same arguments as the Paginator
,
except that it does require a count of the total number of items in the result set.
In other words, the Paginator
corresponds to the simple_paginate
method on the query builder
and the ORM, while the LengthAwarePaginator
corresponds to the paginate
method.
When you call the paginate
or simple_paginate
methods on a query builder or ORM query,
you will receive a paginator instance. When calling the paginate
method,
you will receive an instance of LengthAwarePaginator
. When calling the simple_paginate
method,
you will receive an instance of Paginator
. These objects provide several methods and attributes
that describe the result set. In addition to these helpers methods, the paginator instances are iterators
and may be looped as a list.
for user in some_users:
print(user.name)
You may also access additional pagination information via the following methods and attributes on paginator instances:
Method or attribute | Description |
---|---|
results.count() |
Returns the number of results on the current page |
results.current_page |
The current page of the paginator |
results.has_more_pages() |
Returns True if there is more pages else False |
results.last_page |
The number of the last page (Not available when using simple_paginate ) |
results.next_page |
The number of the next page if it exists else None |
results.per_page |
The number of results per page |
results.previous_page |
The number of the previous page if it exists else None |
results.total |
The total number of results (Not available when using simple_paginate |
The Orator paginator result classes expose the to_json
method,
so it’s very easy to convert your pagination results to JSON.
Be default, it will return the JSON formatted underlying Collection
:
some_users = User.where('votes', '>', 100).paginate(15, 2)
print(some_users.to_json())
Sometimes, you may want to compute the current page based on external parameters.
For that purpose, you can set a custom current page resolver on the Paginator
class.
In this example, the current page will be determined by a ?page
query string parameter:
from orator import Paginator
from flask import request
def current_page_resolver():
return int(request.args.get('page', 1))
Paginator.current_page_resolver(current_page_resolver)
So from now on, It is no longer necessary to specify the current page:
some_users = User.where('votes', '>', 100).paginate(15)