Объединение 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 }}) })()">

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

Вернуться на верх