Проблему разбивки выводимых записей на несколько страниц хорошо решает расширение Flask Flask-SQLAlchemy
. Это расширение поставляется с очень хорошим классом flask_sqlalchemy.Pagination()
.
Но как быть разработчикам, которые не хотят замедлять работу приложения, увеличивать потребление оперативной памяти сервера и повышать нагрузку на базу данных внедрением дополнительных абстракций, таких как ORM SQLAlchemy? Как быть с пагинацией разработчикам, которые используют в своих проектах "ванильный" SQL. Ответ прост, необходимо разработать свой класс пагинации или воспользоваться расширением flask-paginate
, которое не имеет зависимостей от ORM.
Модуль flask-paginate
представляет собой простое расширение фреймворка flask
для разбивки выводимых записей на несколько страниц, которое поддерживает разметку пагинации нескольких популярных CSS-фреймворков.
Разбивка на страницы (пагинация) в шаблоне
jinja2
выводится одним тегом{{ pagination.links }}
.
Bootstrap 5
;Bootstrap 4
;Bootstrap 3
;Bootstrap 2
;Bulma
;Foundation
;SemanticUI
;Materialize framework
;flask-paginate
в виртуальное окружение.# создаем виртуальное окружение, если нет
$ python3 -m venv .venv --prompt VirtualEnv
# активируем виртуальное окружение
$ source .venv/bin/activate
# обновляем `pip`
(VirtualEnv):~$ python3 -m pip install -U pip
# ставим модуль `flask-paginate`
(VirtualEnv):~$ python3 -m pip install -U flask-paginate
Если нужно отобразить информацию о разбивке на страницы (например "всего 100 записей, отображаются с 20 по 30") необходимо разместить jinja
тег {{ pagination.info }}
в шаблоне страницы в требуемом месте и добавить следующие строки CSS-разметки в файл проекта:
.pagination-page-info {
padding: .6em;
padding-left: 0;
width: 40em;
margin: .5em;
margin-left: 0;
font-size: 12px;
}
.pagination-page-info b {
color: black;
background: #6aa6ed;
padding-left: 2px;
padding: .1em .25em;
font-size: 150%;
}
В файле представлений Flask (например, users.py
):
from flask import Blueprint
from flask_paginate import Pagination, get_page_parameter
mod = Blueprint('users', __name__)
@mod.route('/')
def index():
search = False
# если в URL присутствует параметр поиска 'q'
q = request.args.get('q')
if q:
search = True
# определяем текущую страницу
page = request.args.get(get_page_parameter(), type=int, default=1)
# поиск пользователей
users = User.find(...)
pagination = Pagination(page=page, total=users.count(), search=search, record_name='users')
# `page` это номер текущей страницы, параметр URL (по умолчанию 'page') из которого
# он будет извлекаться. Можно настроить, например Pagination(page_parameter='p', ...)
# или установить `PAGE_PARAMETER` в файле конфигурации.
# Также можно настроить параметр URL, который будет передавать количество выводимых
# записей на одной странице, например Pagination(per_page_parameter='pp') или установить
# параметр `PER_PAGE` в файле конфигурации
return render_template('users/index.html',
users=users,
pagination=pagination,
)
И в шаблоне users.html
:
{# вывод информации о разбивке #}
{{ pagination.info }}
{# вывод самой пагинации #}
{{ pagination.links }}
{# Здесь можно вывести информацию #}
{# о записях пользователей #}
{# вывод самой пагинации #}
{{ pagination.links }}
Pagination()
.page
: номер текущей страницы;per_page
: сколько записей нужно отображать на одной странице;page_parameter
: имя (строка) параметра URL в GET запросе (например /?page=2&q=vasya
), для извлечения из запроса индекса текущей страницы (по умолчанию 'page'
);per_page_parameter
: имя (строка) параметра URL в GET запросе (например /?per_page=15&page=2&q=vasya
), для извлечения из запроса количества отображаемых записей на одной странице (по умолчанию 'per_page'
);inner_window
: количество отображаемых ссылок пагинации вокруг текущей страницы;outer_window
: количество отображаемых ссылок пагинации рядом с первой и последней страницей;prev_label
: текст для предыдущей страницы, по умолчанию '«'
next_label
: текст для следующей страницы, по умолчанию '»'
total
: общее количество записей для разбивки на страницы;css_framework
: используемый CSS-фреймворк, по умолчанию 'bootstrap'
, принимаемые строки: 'bootstrap'
, 'semantic'
, 'foundation'
, 'bulma'
, 'materialize'
;bs_version
: версия CSS-фреймворка bootstrap
, по умолчанию 2;display_msg
: настройка строки информации о разбивке на страницы, по умолчанию "displaying <b>{start} - {end}</b> {record_name} in total <b>{total}</b>"
;search
: если True
, то показывает строку с сообщением аргумента search_msg
, иначе будет выведено сообщение аргумента display_msg
;found
: количество найденных записей при поиске {found}
в строке аргумента search_msg
(по умолчанию равно аргументу total
);record_name
: текст {record_name}, отображаемый в строке аргумента search_msg
и display_msg
;search_msg
: настройка строки при поиске, по умолчанию "found <b>{found}</b> {record_name}, displaying <b>{start} - {end}</b>"
;link_size
: размер шрифта ссылок пагинации на страницы;alignment
: выравнивание ссылок по страницам;href
: добавляет пользовательский href
для ссылок пагинации - поддерживает формы с методом POST
. Строка URL должна содержать {0}
(см. str.format()
) для форматирования номера страницы;show_single_page
: если True
, то будет выводить пагинацию даже для одной страницы;anchor
: параметр привязки, добавляется к href
URL-страницы;format_total
: общий числовой формат, если True
, то 1,234
, по умолчанию False
(без запятой);format_number
: числовой формат начала и конца пагинации, если True
, то 1,234
, по умолчанию False
(без запятой);url_coding
: кодировка для кодировки URL, по умолчанию utf-8;bulma_style
: стиль ссылки на страницу для CSS-фреймворка bulma
.