3 горизонтальные линии, бургер
3 горизонтальные линии, бургер
3 горизонтальные линии, бургер
3 горизонтальные линии, бургер

3 горизонтальные линии, бургер
Удалить все
ЗАГРУЗКА ...

Содержание



    Paginator Django, как сделать простой пагинатор ч. 1

    Часы
    02.04.2025
    /
    Часы
    11.03.2026
    /
    Часы
    4 минуты
    Глазик
    508
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0

    Вступление

    В этой статье описывается процесс создания пагинатора используя Django и HTMX. А в качестве UI-библиотеки - daisyUI. Это будет простой и без изысков пагинатор, необходимый минимум для работы. Так же в этой статье не будет описываться процесс создания и настройки виртуального окружения, и установки всех сопутствующих пакетов и модулей.
    Вот так, на примере моего нового сайта будут выглядеть кнопки пагинации
    Так же, данная статья является лишь одной из трёх статей про создание собственного пагинатора на Django. В этой, я лишь создам базу, основу, на которой мы доведём данный пагинатор до логического завершения. Во второй, мы добавим фильтры и сортировку. В третьей, добавим поле поиска. Итак, приступим.

    Пишем фронтенд

    Я предпочитаю начинать свою работу с фронтенда, а там как пойдёт ┐(シ)┌. Для начала, нам потребуется страница для размещения пагинатора и шаблоны для отрисовки загружаемого контента. Например, у меня есть домашняя страница, мне нужно вставить и подключить следующий шаблон.
    <div class="max-w-[1200px] w-[95%] mb-[50px]"> {% include 'parts/article-simple-paginator.html' with articles=articles %} </div>
    Не так важно во что ты обернёшь подключаемый шаблон. Я вот, собираюсь подгружать статьи и хочу чтобы они все были в столбик, но не слишком широкий. Важно то, что нужно передать переменную articles в подключаемый шаблон parts/article-simple-paginator.html. Откуда её взять, смотри в следующей главе, сейчас разберём другие составляющие наших шаблонов.
    Исходный код parts/article-simple-paginator.html:
    {% load static %} {% load i18n %} <div id="search-results" class="flex flex-col gap-[10px]"> {% include 'parts/article-cards.html' with articles=articles %} {% include 'parts/paginator-buttons.html' %} </div>
    Данный сниппет кода представляет собой флекс-бокс в колонку, для карточек статей и собственно кнопок пагинатора. Когда мы подключаем шаблон для отрисовки карточек статей, мы так же не забываем отправить туда articles переменную. После чего подключаем и пагинатор.
    Теперь, собственно говоря, про пагинатор и его кнопки, шаблон parts/paginator-buttons.html:
    {% load i18n %} {% load static %} <form id="pagination_buttons" class="join self-center"> {% csrf_token %} <input class="hidden" value="" name="one" type='text'> <input class="hidden" value="2" name="two" type='text'> <input class="hidden" value="3" name="three" type='text'> {% if is_articles_prev %} <button class="join-item btn" hx-post="?page=1" hx-target="#search-results" hx-replace-url="true" value="1" name="page" > {% trans '<<' %} </button> <button class="join-item btn" hx-post="?page={{articles_prev_page}}" hx-target="#search-results" hx-replace-url="true" value="{{articles_prev_page}}" name="page" > {% trans '<' %} </button> {% else %} <button class="join-item btn btn-disabled">{% trans '<<' %}</button> <button class="join-item btn btn-disabled">{% trans '<' %}</button> {% endif %} <button class="join-item btn btn-disabled">{{articles_start_page}}/{{articles_length}}</button> {% if is_articles_next%} <button class="join-item btn" hx-post="?page={{articles_next_page}}" hx-target="#pagination_buttons" hx-swap="outerHTML" hx-replace-url="true" value="{{articles_next_page}}" name="page" > {% trans '>' %} </button> <button class="join-item btn" hx-post="?page={{articles_length}}" hx-target="#search-results" hx-replace-url="true" value="{{articles_length}}" name="page" > {% trans '>>' %} </button> {% else %} <button class="join-item btn btn-disabled">{% trans '>' %}</button> <button class="join-item btn btn-disabled">{% trans '>>' %}</button> {% endif %} </form>
    Данный пагинатор реализован как форма с возможностью отправлять сразу несколько запросов. И отличаются эти запросы только номером следующей страницы. В самом начале я передаю csrf_token и несколько инпутов, они пока не нужны, но в следующей статье мы их дополним для реализации фильтрации и сортировки.
    Отправка формы происходит при помощи одного из механизмов работы вставки параметров в запрос. В моём случае я воспользовался механизмом автоматической вставки параметров в запрос ближайшей формы в которую обёрнуты мои кнопки.
    Он, пагинатор, состоит из 4-х кнопок и одной неактивной кнопки для показа текущей страницы пагинации и сколько ещё осталось. И вот как ведут себя эти кнопки:
    1. Кнопки >> и << отправляют на последнюю и первую страницу соответственно. Если пользователь уже на последней или первой странице, то эти кнопки отключаются.
    2. Кнопки > и < отправляют на следующую и предыдущую страницу соответственно. Если пользователь уже на последней или первой странице, то эти кнопки отключаются
    Кнопки << < и >> имеют значение в атрибуте hx-target="#search-results", то есть корневой элемент отображения статей и пагинатора. При нажатии весь узел заменяется, а не дополняется новыми статьями так, как в случае с кнопкой >
    На этом фронтенд часть завершена. Подводя итог, тебе нужны следующие шаблоны:
    1. parts/article-cards.html - для отрисовки карточек товаров
    2. parts/article-simple-paginator.html - комбинирует список карточек товаров и кнопки пагинации
    3. parts/paginator-buttons.html - интерфейс для управления пагинацией
    4. Место, куда можно было бы вставить parts/article-simple-paginator.html.

    Пишем бэкенд

    Перед тем как приступить к созданию бэкенда для пагинатора нужно обговорить несколько деталей. В частности, почему я не буду использовать REST API для пагинации.
    Это решение, на самом деле, продиктовано необходимостью моего сайта иметь пагинатор на главной странице, а не на отдельном разделе сайта, как это сделано уже на этом сайте. Плюс, я хочу чтобы у людей была возможность сохранять в закладках необходимые им страницы пагинации.
    Как ты мог заметить на всех кнопках пагинатора присутствует атрибут hx-replace-url. Он меняет старый URL на новый, по которому был отправлен запрос. Очень классная фича HTMX.
    Вот содержимое views.py файла, где находится представление для домашней страницы.
    from django.shortcuts import render from django.http import Http404 from django.core.paginator import Paginator from django.utils.translation import gettext as _ from django.utils.translation import get_language from django.views.generic import TemplateView from Backend.models import * class HomeView(TemplateView): template_name = 'domashnyaya.html' page_size = 2 def get_context_data(self, **kwargs): context = super(HomeView, self).get_context_data(**kwargs) return context def fetch(self, request, context, page_num, *args, **kwargs): # Filter out other languages versions and order by time published, newest first articles = Article.objects.filter(lang_type=get_language()).order_by('-time_published') # Create a paginator, build-in Django one paginator = Paginator(articles, self.page_size) pagination_length = paginator.num_pages # Check if page out of range if page_num > pagination_length or page_num <= 0: raise Http404() # Paginate to page page = paginator.page(page_num) is_prev = page.has_previous() is_next = page.has_next() page_articles = page.object_list # Update context context.update({ 'articles': page_articles, 'articles_start_page': page_num, 'articles_next_page': page_num + 1, 'articles_prev_page': page_num - 1, 'articles_length': pagination_length, 'is_articles_next': is_next, 'is_articles_prev': is_prev }) def post(self, request, *args, **kwargs): context = super(HomeView, self).get_context_data(**kwargs) page_num = int(request.POST.get('page', 1)) self.fetch(request, context, page_num, *args, **kwargs) return render(request, 'parts/article-simple-paginator.html', context=context) def get(self, request, *args, **kwargs): context = super(HomeView, self).get_context_data(**kwargs) page_num = int(request.GET.get('page', 1)) self.fetch(request, context, page_num, *args, **kwargs) return render(request, self.template_name, context=context)
    Данное представление создано в виде класса ибо, это удобно. И работает оно с двумя запросами, POST и GET. Различие их в том, куда они отрисовывают страницы пагинации. Если при GET запросе отрисовывается целая страница, то при POST запросе только необходимая часть, уже ранее известный тебе parts/article-simple-paginator.html шаблон.
    Метод fetch инкапсулирует общую логику между запросами GET и POST. В следующей статье мы расширим этот метод и добавим фильтрацию с сортировкой, ну а пока подключим данное представление в urls.py:
    from django.urls import path from .views import HomeView urlpatterns = [ path('', HomeView.as_view(), name='domashnyaya'), ]

    Заключение

    Не так уж и сложно на самом деле. Если, конечно, сравнивать это с тем, что мне пришлось написать для работы пагинатора на этом сайте. А чтобы его написать, пришлось писать огромное полотно JS-кода, и ещё больше кода для работы непосредственно кнопок пагинации.
    Ещё больше пришлось его переписывать ( ; ω ; )
    Так же, динамическая замена URL очень сильно упростила жизнь. Реализовать это на JS не сложно, но есть вещи, которые просто не хочется реализовывать своими силами.
    И вот так просто, можно реализовать пагинатор на Django используя HTMX.


    Не забудь поделиться, лайкнуть и оставить комментарий)

    Комментарии

    (0)

    captcha
    Отправить
    ЗАГРУЗКА ...
    Сейчас тут пусто. Буть первым (o゚v゚)ノ

    Другое

    Похожие статьи


    Что делать при попадании страниц пагинации в индекс и увеличении количества ошибок типа “Вариант страницы с тегом canonical”

    Часы
    02.03.2025
    /
    Часы
    11.03.2026
    Глазик
    472
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    О том, что делать если у вас произошёл резкий рост неканонических страниц в GSC или Яндекс Вебмастере. А так же, когда такое происходит и почему (Спойлер это пагинато и страницы …

    Как сделать кнопку загрузки контента используя Django, REST API, HTMx

    Часы
    01.04.2025
    /
    Часы
    11.03.2026
    Глазик
    462
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    В этой статье я опишу способ, как можно реализовать асинхронную загрузку контента(статей) при помощи кнопки "Больше", которая сделана при помощи Django, REST API, HTMx и стилизовано при помощи DaisyUI

    Как сделать простой пагинатор на Django и HTMx. Добавляем сортировку и фильтры ч. 2

    Часы
    08.04.2025
    /
    Часы
    11.03.2026
    Глазик
    492
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    В этой статье я опишу процесс и основные блоки кода, для того чтобы добавить сортировку и фильтрацию к пагинатору. Данный пагинатор написан на Django используя HTMx.

    Как добавить форму обратной связи на Django/Python и HTMx

    Часы
    11.04.2025
    /
    Часы
    11.03.2026
    Глазик
    840
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    В этой статье, я опишу как добавить на ваш Django-сайт форму обратной связи используя HTMx и немного DaisyUI, в качестве UI-библиотеки. Всё будет сделано на примере моего нового сайта. Но …

    Как добавить свою 404, 500 страницу в Django

    Часы
    12.04.2025
    /
    Часы
    11.03.2026
    Глазик
    936
    Сердечки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    Соединённые точки
    0
    В этой статье я опишу процесс создания страниц ошибок 404 и 500. Я покажу два основных способа как это сделать и то как можно быстро и легко настроить сервер для …

    Использованные термины


    Релевантные вопросы