Evgenii Legotckoi
Evgenii Legotckoi21 сентября 2016 г. 12:12

Django - Урок 007. Добавление Pagination на основе django-bootstrap3

Количество статей на новом сайте начало приближаться к 10 штукам, поэтому в срочном порядке добавляю Pagination, чтобы была возможность пролистывать страницы на сайте. Но поскольку уже используется модуль django-bootstrap3 , то и Pagination будет использоваться из этого модуля. Зачем же делать лишнюю работу, когда уже всё сделано? Не так ли.

Для добавления Pagination необходимо:

  1. Использовать класс Paginator из django.core.pagination;
  2. Добавить в шаблон главной страницы bootstrap_pagination с привязкой ;
  3. Добавить проверку текущего номера страницы;
  4. И ... не добавлять ничего нового в шаблоны url.

Добавляем Paginator в представление

Paginator - это класс, который содержит текущую страницу, которая загружается при вызове метода page(), которому в качестве аргумента будет передан номер страницы. В нашем случае мы попытаемся забрать номер данной страницы, если он существует, то отобразим страницу или если вышли за количество страниц, то отобразим последнюю. Если номера не был передан, то вернём первую страницу.

from django.shortcuts import render_to_response
from django.views import View
from django.core.paginator import Paginator

from knowledge.models import *

# Представление сделано на основе класса View
class EIndexView(View):

    def get(self, request):
        context = {}
        # Забираем все опубликованные статье отсортировав их по дате публикации
        all_articles = Article.objects.filter(article_status=True).order_by('-article_date')
        # Создаём Paginator, в который передаём статьи и указываем, 
        # что их будет 10 штук на одну страницу
        current_page = Paginator(all_articles, 10)

        # Pagination в django_bootstrap3 посылает запрос вот в таком виде:
        # "GET /?page=2 HTTP/1.0" 200,
        # Поэтому нужно забрать page и попытаться передать его в Paginator, 
        # для нахождения страницы
        page = request.GET.get('page')
        try:
            # Если существует, то выбираем эту страницу
            context['article_lists'] = current_page.page(page)  
        except PageNotAnInteger:
            # Если None, то выбираем первую страницу
            context['article_lists'] = current_page.page(1)  
        except EmptyPage:
            # Если вышли за последнюю страницу, то возвращаем последнюю
            context['article_lists'] = current_page.page(current_page.num_pages) 

        return render_to_response('home/index.html', context)

Информация по URL-шаблону

Как я и говорил, я не менял шаблон url, но приведу его, чтобы не было непоняток.

from django.conf.urls import url

from . import views

app_name = 'home'
urlpatterns = [
    url(r'^$', views.EIndexView.as_view(), name='index'),
]

Кастомизируем шаблон страницы

Шаблон наследован от home/base.html и содержит заголовочную информацию и т.д., которая не интересна в данном случае.

По сути в контекст был передан объект Paginator с выбранными страницами и далее, как обычный queryset объектов через цикл развёрнут в ленту статей.

Но самое интересное то, что дальше мы загружаем модуль bootstrap3 и вставляем bootstrap_pagination, передавая ему в качестве контекста этот же самый article_lists.

{% extends 'home/base.html' %}
{% block page %}
    <h1>Публикации</h1>
    {% if article_lists %}
        {% for article in article_lists %}
            <article>
                <a href="{{ article.get_absolute_url }}">
                    <h2>{{ article.article_title }}</h2>
                </a>
                {{ article.desctription|safe }}
                <p><a class="btn btn-default btn-sm" href="{{ article.get_absolute_url }}">Читать далее</a></p>
                {% include 'knowledge/article_footer.html' %}
            </article>
        {% endfor %}
    {% endif %}
{% load bootstrap3 %}
{% bootstrap_pagination article_lists %}
{% endblock %}

Для Django рекомендую VDS-сервера хостера Timeweb .

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

Вадим Полшков
  • 8 октября 2018 г. 6:36

Как вы в своем шаблоне сделали в пагинации отображение 5 страниц потом ... и последние страницы?

Я тоже так хочу сделать, но у меня пока что все страницы выводит. Вот мой код в шаблоне

														<div class="col-xs-5">
															<div class="pagination">
																<ul>
                                                                    {% if product.has_previous %}
																	<li><a href="?page=1{{ product.previous.num_pages }}"><|</a></li>
																	<li><a href="?page={{ product.previous_page_number }}"><</a></li>
                                                                    {% endif %}

                                                                    {% for i in product.paginator.page_range %}
                                                                      {% if product.number == i %}
                                                                        <li class="active"><a href="">{{ i }}</a></li>
                                                                      {% else %}
                                                                        <li><a href="?page={{ i }}">{{ i }}</a></li>
                                                                      {% endif %}
                                                                    {% endfor %}

                                                                    {% if product.has_next %}
																	<li><a href="?page={{ product.next_page_number }}">></a></li>
																	<li><a href="?page={{ product.paginator.num_pages }}">>|</a></li>
                                                                    {% endif %}
																</ul>
														    </div>
														</div>

Evgenii Legotckoi
  • 8 октября 2018 г. 7:09

я использую django-bootstrap4 и там уже есть эта возможность, поэтому выглядеть будет так в коде

{% bootstrap_pagination article_lists pages_to_show=5 %}

Просто поиграйтесь со значением pages_to_show

Вадим Полшков
  • 8 октября 2018 г. 12:24

спасибо, получилось у меня на bootstrap3 тоже самое.

Плохо, что нет возможности отредактировать свой пост после публикации я там не правильно выбрал стиль кода.

Evgenii Legotckoi
  • 9 октября 2018 г. 3:06

я добавлю редактирование ))) просто сейчас занят совсем другим функционалом. Для добавления редактирования нужно разработать единый механизм, который бы позволял использовать один Дженерик для разных типов контента, поскольку таких комментариев под разными видами контента будет тьма.

Вадим Полшков
  • 9 октября 2018 г. 3:56

понятно.
Еще вопрос по пагинации. У меня она работает, но я так и не понял, как у вас меняется страница автоматом т.е. если сейчас выведено с 1 по 5 то после нажатия на 4 автоматом справа появляется 5? У меня сейчас в этом же порядке, чтоб попасть на 5 нужно нажать на три точки блин ...

Evgenii Legotckoi
  • 9 октября 2018 г. 4:01

Не понял вопроса... В смысле меняется без перезагрузки всей страницы? или что именно?

Я гляну код, как на сайте сделано, но после работы. я не помню всех параметров которые там прописываю... Хотя того, что я вам написал должно быть достаточно...

У меня как бы тоже при выведенных от 1 до 4 нужно нажать на три точки, чтобы попасть на 5ю страницу.


Вадим Полшков
  • 9 октября 2018 г. 4:13

У вас после нажатия на 4стр. 5 появляется сразу после обновления страницы. А у меня после нажатия на 4стр. и обновления страницы 5 не появляется а только ... и поэтому, что перейти на страницу 5 мне нужно нажать на многоточее.
Т.е. у вас не нужно нажимать на ... т.к. следующая цифра страницы сразу появляется. Вот как это работает пока не понял.

Evgenii Legotckoi
  • 9 октября 2018 г. 4:21

Полагаю, что у вас отсутствует компонент page или каким-то образом номер страницы неправильно устанавливается... Либо, возможно имеете забагованную версию django-bootstrap3, тоже может быть ...

Вадим Полшков
  • 9 октября 2018 г. 4:38

у меня сейчас так в коде шаблона, не знаю у вас так же или нет? или я может чет упустил?

Evgenii Legotckoi
  • 9 октября 2018 г. 4:39

покажите python код, больше похоже на то, что у вас сам объект products корявый

Вадим Полшков
  • 9 октября 2018 г. 4:49

вот эта функция, делал по документации джанго

def shop(request):
    context = {}
    products = Product.objects.filter(is_active=True)
    brands = Brand.objects.all()
    paginator = Paginator(products, 1)
    page = request.GET.get('page')
    products = paginator.get_page(page)
    context['products'] = products
    context['brands'] = brands
    return render(request, 'shop/shop.html', context)
Evgenii Legotckoi
  • 9 октября 2018 г. 4:55

хм... я гляну после работы, что у меня там в коде есть, я для пагинации уже давно дженерик написал и код для пагинации уже не пишу, поэтому там, возможно, есть нюанс, о котором я забыл, который касается django-bootstrap*.


Вадим Полшков
  • 9 октября 2018 г. 4:58

ага, спасибо буду ждать ответ.

Evgenii Legotckoi
  • 9 октября 2018 г. 5:02

Погоди-те как... А вас шаблон неправильный...

<div class="pagination">

Там точно не нужен, поскольку bootstrap_pagination генерирует всё, что нужно.

Вот минимально рабочий вариант пагинатора со списком объектов

<div id="articles-list">
    {% load bootstrap_pagination from bootstrap3 %}
    {% for article in object_list %}
        {% include 'knowledge/article_preview.html' %}
    {% endfor %}
    {% bootstrap_pagination object_list pages_to_show="10" %}
</div>

Код взят вот из этой статьи


Вадим Полшков
  • 9 октября 2018 г. 5:44

У вас на той странице написано

article_preview.html - этот шаблон рассматривать не будем, поскольку он не интересен для нас в данном случае
наверно как раз это самое интересное будет в моем случае, могу предположить, что там сам код пагинации, по которому проходит итерация. Можно его посмотреть?

Evgenii Legotckoi
  • 9 октября 2018 г. 5:52

Нету там никакой пагинации от слова - "совсем". Там просто кусок шаблона который отвечает за отрисовку превью одного объекта статьи.

Вот в этой одной строчке вся пагинация

{% bootstrap_pagination object_list pages_to_show="10" %}


Вадим Полшков
  • 9 октября 2018 г. 5:58

понял, ок пошаманю еще немного, если не получиться то и фиг с ним так тоже вполне сойдет.

Вадим Полшков
  • 9 октября 2018 г. 6:20

В общем добился я такого эффекта в пагинации как у вас след.образом. У меня в категории к примеру 8 записей, вот чтоб пагинация так работала нужно в {% bootstrap_pagination products pages_to_show=4 %} поставить ровно половину т.е. скрывать 4стр. Теперь получается, что видимых 5стр. и если нажать на 5 то 6-я автоматом и появляется и т.д. как у вас.
Спасибо за помощь!

Evgenii Legotckoi
  • 9 октября 2018 г. 6:23

А, вот в чём дело было... получается, что у вас просто контента не хватало, чтобы был задействован весь функционал пагинатора

Вадим Полшков
  • 9 октября 2018 г. 6:32

получается да, сейчас делаю новый проект и пока много не добавлял контента так чисто для проверки и тестов, но когда ограничил ровно на половину, то заработало как надо.

RS
  • 1 сентября 2021 г. 15:45
  • (ред.)

а как быть если нет базы и запроса в БД, а данные приходят по запросу в api стороннего сервера, а клиент серверное приложение на django и я хочу реализовать пагинацию на стороне django. В апи я могу пердвать limit, offset, и получать count всех записей
Что тогда нужно передавать в класс пагинатора (вместо all_articles) как тут

кроме количества записей на страницы и как в дальнейшем делать запрос что бы пагинатор работал правильно

Evgenii Legotckoi
  • 12 октября 2021 г. 1:45

Просто список каких-нибудь объектов передавайте, который дёрнули ищ api стороннего сервера

from django.core.paginator import Paginator
objects = ['john', 'paul', 'george', 'ringo']
p = Paginator(objects, 2)

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
m
  • moreSpb
  • 18 марта 2024 г. 12:32

C++ - Тест 003. Условия и циклы

  • Результат:85баллов,
  • Очки рейтинга6
в

C++ - Тест 003. Условия и циклы

  • Результат:50баллов,
  • Очки рейтинга-4
l

C++ - Тест 005. Структуры и Классы

  • Результат:91баллов,
  • Очки рейтинга8
Последние комментарии
k
kmssr8 февраля 2024 г. 15:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко4 февраля 2024 г. 22:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 7:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 5:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik18 декабря 2023 г. 18:01
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
P
Pisych27 февраля 2023 г. 1:04
Как получить в массив значения из связанной модели? Спасибо, разобрался:))
AC
Alexandru Codreanu19 января 2024 г. 8:57
QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…
BlinCT
BlinCT27 декабря 2023 г. 5:57
Растягивать Image на парент по высоте Ну и само собою дял включения scrollbar надо чтобы был Flickable. Так что выходит как то так Flickable{ id: root anchors.fill: parent clip: true property url linkFile p…
Дмитрий
Дмитрий10 января 2024 г. 1:18
Qt Creator загружает всю оперативную память Проблема решена. Удалось разобраться с помощью утилиты strace. Запустил ее: strace ./qtcreator Начал выводиться весь лог работы креатора. В один момент он начал считывать фай…
Evgenii Legotckoi
Evgenii Legotckoi12 декабря 2023 г. 3:48
Побуквенное сравнение двух строк Добрый день. Там случайно не высылается этот сигнал textChanged ещё и при форматировани текста? Если решиать в лоб, то можно просто отключать сигнал/слотовое соединение внутри слота и …

Следите за нами в социальных сетях