Объединение Django и Bootstrap 5 Modal с помощью Ajax
Как иметь кнопку/ссылку, которая может нацеливаться на объект pk, например, определенный пост с {{obj.pk}}, затем открыть модальное окно edit modal и delete modal.
Тогда модал может успешно редактировать и удалять без обновления, используя AJAX (Fetch API или Jquery). У меня есть проблема, чтобы нацелить модальное окно на открытие поста с определенным PK. Я не могу использовать id="editPost{{obj.id}}" или id="deletePost{{obj.id}}" для нацеливания модала, потому что тогда мне нужно поместить модал в forloop, тогда модал будет повторяться для каждого поста.
Вот часть кода:
{% for obj in page_obj %}
<li>
<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#editPost" href="{% url 'post-update' obj.pk %}">Edit Post</a>
</li>
<li>
<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#deletePost" href="{% url 'post-delete' obj.pk %}">Delete Post</a>
</li>
<div id="post{{obj.id}}" class="box-content">
<p class="box-text mb-2">{{ obj.content }}</p>
<span class="username">{{ obj.username }}</span>
</div>
{% endfor %}
<div class="modal fade" id="deletePost" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete Post?</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete your post?</p>
</div>
<div class="modal-footer">
<button type="button" class="rvg-button-small" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="rvg-button-small">Delete</button>
</div>
</div>
</div>
</div>
Способ достижения AJAX заключается в использовании
<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#editPost" onclick="EditPost('{{ obj.id }}')">
<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#deletePost" onclick="DeletePost('{{ obj.id }}')">
const DeletePost = (post_id) => {
fetch("/" + post_id + "/delete/", {
method: "POST",
credentials: 'same-origin',
headers: { "X-CSRFToken": getCookie("csrftoken") },
})
.then((res) => res.json())
.then((data) => {
document.getElementById(`post${post_id}`).remove()
console.log("successfully deleted")
}).catch((e) => alert("Error deleting post."));
}
Вы можете передавать аргументы вашему модалу с помощью data-<something>
, так же как это делает bootstrap с помощью data-bs-<something>
.
<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#deletePost" data-object-id="{{ obj.id }}" onclick="DeletePost()">
Тогда с помощью js, внутри DeletePost
вам нужно будет извлечь pk
или любой другой аргумент, который вы передадите ему. Подробнее о dataset
здесь.
Другой вариант - обернуть вашу функцию анонимной функцией для передачи аргументов внутренней функции и, наконец, вызвать внешнюю (анонимную) функцию.
В этом случае я использую синтаксис функции стрелки, но он эквивалентен обычному синтаксису для определений функций:
<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#deletePost" onclick="(() => { DeletePost({{ obj.id }}) })()">
Я бы рекомендовал первый вариант, так как (я думаю) он более гибкий для будущего использования, когда вам нужно передать более одного аргумента в функцию, но любой из них должен работать.