将 Django 和 Bootstrap 5 Modal 与 Ajax 结合使用

Posted

技术标签:

【中文标题】将 Django 和 Bootstrap 5 Modal 与 Ajax 结合使用【英文标题】:Combine Django and Bootstrap 5 Modal with Ajax 【发布时间】:2022-01-04 01:39:39 【问题描述】:

如何使用 obj.pk 拥有可以像某个帖子一样定位对象 pk 的按钮/链接,然后打开模态 edit modal 和 delete modal。

然后模态框可以使用 AJAX(Fetch API 或 Jquery)在不刷新的情况下成功编辑和删除。我有问题以模态为目标打开具有某些 PK 的帖子。我不能使用 id="editPostobj.id" 或 id="deletePostobj.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="postobj.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."));

【问题讨论】:

【参考方案1】:

您可以使用 data-&lt;something&gt; 以及 bootstrap 使用 data-bs-&lt;something&gt; 将参数传递给您的模式。

<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#deletePost" data-object-id=" obj.id " onclick="DeletePost()">

然后使用 js,在 DeletePost 内,您需要提取 pk 或您传递给它的任何其他参数。阅读更多关于datasethere的信息。

另一种选择是使用anonymous function 包装您的函数,以将参数传递给内部函数,最后调用外部(匿名)函数。

在这种情况下,我使用arrow function 语法,但等效于函数定义的常规语法:

<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#deletePost"  onclick="(() =>  DeletePost( obj.id ) )()">

我会推荐第一个选项,因为(我认为)当您需要将多个参数传递给函数但其中任何一个都应该工作时,它对于将来的使用更加灵活。

编辑: 我之前忘了提这个。如果您使用第一个选项,请确保在 html 元素中调用您的函数时传递事件,以便获取点击目标元素和附加到它的数据集。

您的元素应如下所示: &lt;a ... onclick="DeletePost(event)"&gt;.

您的 js 函数将接收事件作为参数:

const DeletePost = (event) => 
  const btn = event.target; // the clicked button.
  const object_id = btn.dataset.objectId;
  console.log(object_id); // should display the right id.

编辑 2:

为了能够在模态中调用您的 Django URL:

    删除 for 循环内 &lt;a&gt; 元素中的 href 属性,或将标签 &lt;a&gt; 替换为 &lt;button&gt;,保留引导程序显示模式所需的属性。 这将防止在不先显示模式的情况下过早调用您的 Django 视图。 同时保留data-object-id 属性。

    在模态代码中,将页脚中的 &lt;button&gt; 元素替换为如下内容:

<a id="delete-post-btn" class="rvg-button-small" href="% 'DeletePost' %">Delete</a>

请记住,在此阶段,href 不完整,因为缺少 object-id

    为modal创建一个事件监听器,监听事件'shown.bs.modal'知道modal什么时候打开并提取对象id完成href属性:
document
  .getElementById('deletePost')
  .addEventListener('shown.bs.modal', (event) =>  

    // The modal is open and the object-id can be extracted.
    event.preventDefault(); // this step may not be needed.
    const btn = event.relatedTarget; // this is the button that contains the data-<something> attrs
    const objectId = btn.dataset.objectId; 

    // Now we add the object-id value to the href.
    const modal_btn = document.getElementById('delete-post-btn');
    modal_btn.href += String(objectId);
  ) 

现在href 应该是完整的,并且按钮应该能够使用正确的 object-id 调用 Django 视图 URL。

【讨论】:

我用第一种方法试过了,但只得到对象的第一个元素,而不是我点击的那个 请更新您的问题,添加您如何从数据集中提取值。 @AwesomeLerman 我更新了我的答案,对如何从数据集中提取值进行了更多解释。 感谢您的回答,方法是成功的,但是如何使引导模式(弹出)中的按钮成为删除帖子的按钮? DeletePost( ) 函数当前位于下拉项中,而不是模式中的按钮中。模态在 forloop 之外,因此无法获取对象 ID。如何将数据集值从 DeletePost 函数传递到引导模式? 对不起,我是 javascript 新手:/

以上是关于将 Django 和 Bootstrap 5 Modal 与 Ajax 结合使用的主要内容,如果未能解决你的问题,请参考以下文章

django-bootstrap-v5 DecimalField 在 ModelForm 类中抛出错误

Django crudbuilder & Bootstrap 日期选择器

如何将 bootstrap 5 与 webpack 加载器一起使用?

将 Bootstrap 添加到 Inbulit 登录视图 Django

整合django和bootstrap框架

Django 和 Bootstrap:推荐啥应用程序? [关闭]