如何结合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
相关产品推荐
相关产品推荐

