Домой Edit me on GitHub

2020-12-05

Каналы передачи данных | Сетевое программирование | Базы данных | Основы Веб-программирования

Пагинация

В Интернете под пагинацией понимают показ ограниченной части информации на одной веб-странице (например, 10 результатов поиска или 20 форумных трэдов). Она повсеместно используется в веб-приложениях для разбиения большого массива данных на страницы и включает в себя навигационный блок для перехода на другие страницы.

Paginate

Модуль paginate делит список статей на страницы. Номер страницы передается методом GET, в параметре page. По умолчанию берется первая страница.

p = paginate.Page(
    items,
    page=1,
    items_per_page=42
)

Пример Mako шаблона, использующего Bootstrap4 для пагинации.

<%inherit file="base.mako"/>

<%block name="content">
  <h2>${tag.title()}</h2>
  <br/>
  <div class="row">
    %for item in p:
      <div class="col">
        <div class="row">
          <a href="${_static_prefix}/item/${item.id}.html"> 🔗 </a>
        </div>
        <br/>
        <div class="row">
          <pre id='id-${item.id}' width=100%>
            ${item.text}
          </pre>
        </div>
      </div>
    %endfor
  </div>

  # https://v4-alpha.getbootstrap.com/components/pagination/
  <div class="row">
    <nav aria-label="Page navigation example">
      <ul class="pagination">
        ${p.pager(
          url="../$page/index.html".format(tag),
          link_attr={'class': 'page_link'},
          link_tag=lambda page: '<li class="page-item {} {}"><a class="page-link" href="{}">{}</a></li>'.format(
          'active' if page['type'] == 'current_page' else '',
          'disabled' if not len(page['href'].strip()) else '',
          page['href'],
          page['value']
          )
        )}
      </ul>
    </nav>
  </div>
</%block>
../../_images/bootstrap.png

Bootstrap4 pagination

Блог

Данные

См.также

Для начала наполним блог случайными статьями при помощи функции generate_lorem_ipsum из пакета jinja2.utils.

models.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from jinja2.utils import generate_lorem_ipsum

ARTICLES = []

for id, article in enumerate(range(100), start=1):
    title = generate_lorem_ipsum(
        n=1,         # Одно предложение
        html=False,  # В виде обычного текста
        min=2,       # Минимум 2 слова
        max=5        # Максимум 5
    )
    content = generate_lorem_ipsum()
    ARTICLES.append(
        {'id': id, 'title': title, 'content': content}
    )
../../_images/long_list_blog_articles.png

Много статей не помещаются на экран

Paginate

views.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class BlogIndex(BaseBlog):

    def __iter__(self):
        self.start('200 OK', [('Content-Type', 'text/html')])

        # Get page number
        from urllib.parse import parse_qs
        values = parse_qs(self.environ['QUERY_STRING'])

        # Wrap articles to paginated list
        from paginate import Page
        page = values.get('page', ['1', ]).pop()
        paged_articles = Page(
            ARTICLES,
            page=page,
            items_per_page=8,
        )

        yield str.encode(
            env.get_template('index.html').render(
                articles=paged_articles
            )
        )
templates/index.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{% extends "base.html" %}

{% block title %}Index{% endblock %}

{% block content %}
    <div class="blog__title">Simple Blog</div>
    <a href="/article/add" class="blog__button">add article</a>
    <div class="blog-list">
        {% for article in articles %}
            <div class="blog-list__item">
                <div class="blog-list__item-id">{{ article.id }}</div>
                <a href="/article/{{ article.id }}" class="blog-list__item-link">{{ article.title }}</a>
                <div class="blog-list__item-action">
                    <a href="/article/{{ article.id }}/edit" class="blog-list__item-edit">edit</a>
                    <a href="/article/{{ article.id }}/delete" onclick="return confirm_delete();"
                        class="blog-list__item-delete">delete</a>
                </div>
            </div>
        {% endfor %}
    </div>
    <div class="paginator">
        {{ articles.pager(url="?page=$page") }}
    </div>
{% endblock %}

В результате на каждой странице отображаются только 8 статей.

../../_images/blog_with_page.png

Блог со страницами

Previous: Статика Next: WebOb