Сортировка HTMX работает только один раз, рендеринг делает ее нерабочей
Я ссылаюсь на канал BugBytes на YouTube о сортируемом меню в Django.
(Django и HTMX #6 (часть 1) - Построение сортируемого интерфейса перетаскивания и падения )
https://www.youtube.com/watch?v=V-f_yYKUJo8
(Django и HTMX #6 (часть 2) - Построение сортируемого интерфейса перетаскивания и падения )
https://www.youtube.com/watch?v=5Fuwo4tVXmE
Некоторые люди столкнулись с той же проблемой, но нашли подсказку, как ее решить.
Я не мог иметь никакого подтекста.
Тот же вопрос найден в StackOverflow здесь. "Sortable JS breaks upon htmx rendering a partial"
И я не думаю, что ответ показывает какие-либо решения.
В моем случае, следуя обучающему видео BugBytes и репозиторию , я сделал следующие файлы Django.
books.html
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>List Books</title>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
</head>
<body>
<section id="book_list">
{% include 'list_books.html' %}
</section>
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
})
htmx.onLoad(function(content) {
var sortables = content.querySelectorAll(".sortable");
for (var i = 0; i < sortables.length; i++) {
var sortable = sortables[i];
new Sortable(sortable, {
animation: 150,
ghostClass: 'blue-background-class'
});
}
})
</script>
</body>
</html>
list_books.html
{% csrf_token %}
<form class="sortable" hx-post="{% url 'book_app:sort' %}" hx-trigger="end" hx-target="#book_list" hx-swap="innerHTML">
<div class="htmx-indicator">Updating...</div>
{% for book in all_books %}
<div>
<input type='hidden' name='book_order' value='{{ book.pk }}'/>
<p>#{{ book.order }} / {{ book.category.large_category }}/{{ book.category }}/{{ book.title }}</p>
</div>
{% endfor %}
</form>
urls.py
from django.urls import path
from . import views
app_name = 'book_app'
urlpatterns = [
path('books/', views.books, name='books'),
]
htmx_urlpatterns = [
path('sort/', views.sort, name='sort'),
]
urlpatterns += htmx_urlpatterns
views.py
def books(request):
all_books = Books.objects.all().order_by('order')
context = {
'all_books': all_books,
}
return render(request, 'books.html', context)
def sort(request):
books_order_list = request.POST.getlist('book_order')
print(books_order_list)
all_books = []
for idx, book_pk in enumerate(books_order_list, start=1):
book = Books.objects.get(pk=book_pk)
book.order = idx
book.save()
all_books.append(book)
context = {
'all_books': all_books,
}
return render(request, 'list_books.html', context)
models.py
from django.db import models
# Create your models here.
class LargeCategory(models.Model):
name = models.CharField(max_length=25)
def __str__(self):
return self.name
class SmallCategory(models.Model):
large_category = models.ForeignKey(LargeCategory, on_delete=models.CASCADE)
name = models.CharField(max_length=25)
def __str__(self):
return self.name
class Books(models.Model):
category = models.ForeignKey(SmallCategory, on_delete=models.CASCADE)
title = models.CharField(max_length=25)
order = models.PositiveSmallIntegerField(null=True, blank=True)
Я заметил, пока собирался разместить этот вопрос, что если я изменю целевой файл для рендеринга о функции sort() в файле views.py???
Поэтому я изменил функцию sort() в файле views.py следующим образом!!!
def sort(request):
books_order_list = request.POST.getlist('book_order')
print(books_order_list)
all_books = []
for idx, book_pk in enumerate(books_order_list, start=1):
book = Books.objects.get(pk=book_pk)
book.order = idx
book.save()
all_books.append(book)
context = {
'all_books': all_books,
}
return render(request, 'books.html', context)
Я изменяю целевой файл шаблона для рендеринга типа "list_books.html" на "books.html".
И наконец-то все работает нормально!!!
В обучающем видео от BugBytes целевой файл шаблона функции sort() в файле views.py при повторной проверке становится "film-list.html".
Надеюсь, это будет полезно для будущих студентов.
Потому что мало ресурсов для справки о HTMX и сортируемом классе этого.
Счастливое кодирование!!! :D!!