Paging Query Results¶
If you have a lot of results, you may only want to show a certain number at a time, allowing the user to click next and previous links to see pages of data. This is sometimes called pagination, and uses the verb paginate.
Call SQLAlchemy.paginate()
on a select statement to get a Pagination
object.
During a request, this will take page
and per_page
arguments from the query
string request.args
. Pass max_per_page
to prevent users from requesting too many
results on a single page. If not given, the default values will be page 1 with 20 items
per page.
page = db.paginate(db.select(User).order_by(User.join_date))
return render_template("user/list.html", page=page)
Showing the Items¶
The Pagination
object’s Pagination.items
attribute is the list of
items for the current page. The object can also be iterated over directly.
<ul>
{% for user in page %}
<li>{{ user.username }}
{% endfor %}
</ul>
Page Selection Widget¶
The Pagination
object has attributes that can be used to create a page
selection widget by iterating over page numbers and checking the current page.
iter_pages()
will produce up to three groups of numbers, separated by
None
. It defaults to showing 2 page numbers at either edge, 2 numbers before the
current, the current, and 4 numbers after the current. For example, if there are 20
pages and the current page is 7, the following values are yielded.
users.iter_pages()
[1, 2, None, 5, 6, 7, 8, 9, 10, 11, None, 19, 20]
You can use the total
attribute to show the total number of
results, and first
and last
to show the
range of items on the current page.
The following Jinja macro renders a simple pagination widget.
{% macro render_pagination(pagination, endpoint) %}
<div class="page-items">
{{ pagination.first }} - {{ pagination.last }} of {{ pagination.total }}
</div>
<div class=pagination>
{% for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
<a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a>
{% else %}
<strong>{{ page }}</strong>
{% endif %}
{% else %}
<span class=ellipsis>…</span>
{% endif %}
{% endfor %}
</div>
{% endmacro %}