Как разработчик, вам нужно будет создавать таблицы в своих веб-приложениях. Чтобы создать таблицу в Django, вы обычно реализуете набор API-интерфейсов на стороне сервера, которые передают данные клиенту, и используете библиотеку таблиц Javascript на стороне клиента. Но вы также можете реализовать HTML-таблицу. Недостатком этого подхода является то, что каждое действие, такое как сортировка или поиск, будет обновлять всю страницу. И это может быть неприятным опытом для пользователя. Но знаете ли вы, что есть лучший способ создавать таблицы? Эта статья покажет вам, как использовать Django и htmx для разработки функциональных и адаптивных таблиц.


Эта статья покажет вам, как создать таблицу с помощью django-tables2 и htmx. Таблица, которую я собираюсь реализовать, выглядит так:


Набросок таблицы


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


Пакеты, используемые для этого проекта


  1. [htmx] (https://htmx.org/). htmx — это небольшой Javascript, который поможет вам избежать Javascript. Усталость от Javascript реальна. Существует слишком много интерфейсных фреймворков, инструментов и опций Javascript. Интеграция некоторых из этих фреймворков в проект Django приводит к большой сложности. Вам нужно будет переключить контекст между Python и Javascript. Вам также необходимо понимать широкий набор инструментов, таких как node, npm, webpack и т. д. htmx позволяет разработчику Django придерживаться того, в чем Django хорош: на стороне сервера.

  1. [django-tables2] (https://github.com/jieter/django-tables2). Вы можете реализовать таблицу HTML, используя только Django, но есть способ легко создавать таблицы и управлять ими: django-tables2. Это приложение Django позволяет вам определять таблицы так же, как вы определяете модели Django. Он может автоматически генерировать таблицу на основе модели Django. Он поддерживает разбивку на страницы, сортировку таблиц на основе столбцов, пользовательские функции столбцов с помощью подклассов и многие другие функции.

  1. [фильтр джанго] (https://github.com/carltongibson/фильтр джанго). Я использую этот пакет для функции поиска. Он имеет API, похожий на ModelForm Django, и хорошо работает с django-tables2.

  1. [django-htmx] (https://github.com/adamchainz/django-htmx). Чтобы htmx работал, view Django должен иметь возможность определить, какой запрос сделан с использованием htmx, а какой нет. Вы можете создать свое промежуточное ПО или класс, который ваше представление может наследовать, чтобы справиться с этим. Но для этого проекта я использую django-htmx, потому что зачем изобретать велосипед. Он имеет промежуточное программное обеспечение, которое добавляет атрибут htmx к объекту request.

Как работает HTML


Прежде чем двигаться дальше, давайте поговорим о том, как работает htmx. Библиотека htmx дает вам доступ к AJAX. В ванильном HTML только <a> и <form> могут делать HTTP-запросы, и только события click и submit могут вызывать их. Кроме того, HTTP-запросы всегда заменяют весь экран. Но библиотека htmx преодолела все эти ограничения. Вы можете инициировать HTTP-запросы к любому элементу, который хотите. И это просто сделать, например (взято прямо с страницы htmx):





<кнопка hx-post="/clicked" hx-swap="outerHTML">


Нажми на меня



Когда вы нажимаете на кнопку, htmx выдает запрос AJAX к /clicked и заменяет всю кнопку HTML-ответом.


Я могу использовать ту же механику для стола. Все, что мне нужно сделать:


  1. Рендер всей страницы с первой страницей таблицы

  1. Когда вы запускаете какое-либо действие (сортировка, поиск, переход на определенную страницу), оно отправляет запрос AJAX на сервер.

  1. Сервер возвращает HTML-ответ (частичный HTML, только данные таблицы)

  1. Содержимое назначенного раздела заменяется новым HTML-ответом.

Для этого проекта я использую несколько атрибутов htmx, а именно:


  1. hx-получить. Чтобы отправить запрос GET на заданный URL.

  1. hx-триггер. Способ запуска запроса.

  1. hx-цель. Чтобы загрузить результат в целевой элемент.

  1. hx-своп. Чтобы поменять местами HTML, возвращенный в метод DOM.

  1. hx-индикатор. Сообщите пользователю, что что-то происходит, так как браузер не будет давать ему никакой обратной связи.

Модель


Во-первых, давайте создадим простую таблицу продуктов. Я сделаю стол из следующей модели.


продукты/models.py


из моделей импорта django.db


класс Продукт (модели.Модель):


Статус класса (модели.IntegerChoices):


АКТИВНЫЙ = 1, "Активный"


НЕАКТИВНО = 2, "Неактивно"


АРХИВИРОВАНО = 3, "Архивировано"


имя = модели.CharField(max_length=255)


категория = модели.CharField(max_length=255)


цена = модели.DecimalField(max_digits=10, decimal_places=2)


стоимость = модели.DecimalField (max_digits = 10, decimal_places = 2)


статус = модели.PositiveSmallIntegerField(choices=Status.choices)


защита str(я):


вернуть себя.имя


Таблица


Теперь я определю таблицу и укажу шаблон. Это переопределение шаблона необходимо, потому что мне нужно добавить некоторые атрибуты htmx к некоторым элементам. Мое определение таблицы выглядит следующим образом.


продукты/tables.py


импортировать django_tables2 как таблицы


from products.models импорт Продукт


класс ProductHTMxTable (таблицы. Таблица):


Мета класса:


модель = продукт


имя_шаблона = "таблицы/bootstrap_htmx.html"


Внутри шаблона bootstrap_htmx.html я расширяю исходный шаблон bootstrap4.html. Части, которые я расширяю, — это заголовки таблиц (используемые для сортировки) и часть разбиения на страницы. Обратите внимание, что hx-target указывает на div.table-container. Это связано с тем, что шаблон bootstrap4.html имеет контейнер div, который обертывает таблицу, а класс для контейнера – table-container. Htmx заменит данные div.table-container ответом сервера.


{# шаблоны/таблицы/bootstrap_htmx.html #}


{% расширяет "django_tables2/bootstrap4.html" %}


{% загрузить django_tables2 %}


{% загрузить i18n%}


{% блокировка table.thead%}


{% если table.show_header %}




{% для столбца в table.columns %}


<th {{ столбец.attrs.th.as_html }}


hx-get="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}"


hx-триггер = "щелчок"


hx-target="div.table-контейнер"


hx-своп = "внешний HTML"


hx-индикатор = ".прогресс"


стиль="курсор: указатель;">


{{столбец.header}}



{% конец для %}




{% конец%}


{% endblock table.thead %}


{# Блок пагинации переопределяет #}


{% блокировать разбивку на страницы.предыдущая%}



  • <div hx-get="{% querystring table.prefixed_page_field=table.page.previous_page_number %}"


    hx-триггер = "щелчок"


    hx-target="div.table-контейнер"


    hx-своп = "внешний HTML"


    hx-индикатор = ".прогресс"


    класс = "ссылка на страницу">



    {% транс 'предыдущий' %}