You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合Django、Bootstrap5 Modal与Ajax实现无刷新帖子编辑删除功能

实现方案

你可以直接复用全局的单个编辑、删除模态框,通过Bootstrap模态框自带的事件机制传递帖子ID,完全不需要把模态框放在循环里重复渲染,具体修改步骤如下:

第一步:修改循环内的操作按钮

给编辑、删除按钮新增data-post-id属性存储对应帖子的主键,删除冗余的内联点击事件和跳转链接:

{% for obj in page_obj %}
<li>
  <a class="dropdown-item edit-btn" data-bs-toggle="modal" data-bs-target="#editPost" data-post-id="{{ obj.pk }}" href="javascript:void(0);">
    编辑帖子
  </a>
</li>
<li>
  <a class="dropdown-item delete-btn" data-bs-toggle="modal" data-bs-target="#deletePost" data-post-id="{{ obj.pk }}" href="javascript:void(0);">
    删除帖子
  </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 %}

第二步:优化全局模态框结构

给删除、编辑模态框的确认按钮新增ID,方便绑定点击事件,你原来的删除模态框修改后如下:

<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">删除帖子?</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <p>确认要删除这条帖子吗?</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="rvg-button-small" data-bs-dismiss="modal">取消</button>
        <!-- 新增ID属性 -->
        <button type="button" class="rvg-button-small" id="confirmDeleteBtn">删除</button>
      </div>
    </div>
  </div>
</div>

编辑模态框也放在全局,不需要循环渲染,示例结构如下:

<div class="modal fade" id="editPost" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">编辑帖子</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <textarea id="editPostContent" class="form-control" rows="3"></textarea>
      </div>
      <div class="modal-footer">
        <button type="button" class="rvg-button-small" data-bs-dismiss="modal">取消</button>
        <button type="button" class="rvg-button-small" id="confirmEditBtn">保存修改</button>
      </div>
    </div>
  </div>
</div>

第三步:编写交互逻辑

通过监听模态框的显示事件获取对应帖子ID,点击确认后执行AJAX操作:

// 存储当前操作的帖子ID
let activePostId = null;
// 封装获取CSRF Token的方法
function getCookie(name) {
  let cookieValue = null;
  if (document.cookie && document.cookie !== '') {
    const cookies = document.cookie.split(';');
    for (let i = 0; i < cookies.length; i++) {
      const cookie = cookies[i].trim();
      if (cookie.substring(0, name.length + 1) === (name + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }
  return cookieValue;
}

// -------------------- 删除逻辑 --------------------
const deleteModal = document.getElementById('deletePost');
// 监听删除模态框显示事件,获取当前操作的帖子ID
deleteModal.addEventListener('show.bs.modal', function (event) {
  const triggerBtn = event.relatedTarget;
  activePostId = triggerBtn.getAttribute('data-post-id');
});
// 监听删除确认按钮点击
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
  if (!activePostId) return;
  fetch(`/${activePostId}/delete/`, {
    method: "POST",
    credentials: 'same-origin',
    headers: { "X-CSRFToken": getCookie("csrftoken") },
  })
  .then(res => res.json())
  .then(data => {
    // 关闭模态框
    const bsModal = bootstrap.Modal.getInstance(deleteModal);
    bsModal.hide();
    // 移除页面上的帖子元素
    document.getElementById(`post${activePostId}`).remove();
    activePostId = null;
  })
  .catch(e => {
    alert("删除帖子出错");
    activePostId = null;
  });
})

// -------------------- 编辑逻辑 --------------------
const editModal = document.getElementById('editPost');
const editContentInput = document.getElementById('editPostContent');
// 监听编辑模态框显示事件,拉取当前帖子的原有内容填充
editModal.addEventListener('show.bs.modal', function(event) {
  const triggerBtn = event.relatedTarget;
  activePostId = triggerBtn.getAttribute('data-post-id');
  // 调用你后端的帖子详情接口获取原有内容
  fetch(`/${activePostId}/detail/`)
  .then(res => res.json())
  .then(data => {
    editContentInput.value = data.content;
  })
  .catch(e => alert("加载帖子内容失败"));
});
// 监听编辑确认按钮点击
document.getElementById('confirmEditBtn').addEventListener('click', function() {
  if (!activePostId) return;
  const newContent = editContentInput.value.trim();
  if (!newContent) {
    alert("帖子内容不能为空");
    return;
  }
  fetch(`/${activePostId}/update/`, {
    method: "POST",
    credentials: 'same-origin',
    headers: {
      "X-CSRFToken": getCookie("csrftoken"),
      "Content-Type": "application/json"
    },
    body: JSON.stringify({content: newContent})
  })
  .then(res => res.json())
  .then(data => {
    const bsModal = bootstrap.Modal.getInstance(editModal);
    bsModal.hide();
    // 更新页面上的帖子内容
    document.querySelector(`#post${activePostId} .box-text`).textContent = newContent;
    activePostId = null;
  })
  .catch(e => {
    alert("编辑帖子出错");
    activePostId = null;
  });
})

内容的提问来源于stack exchange,提问作者Awesome Lerman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:06:06