0

0

Django 安全动态删除功能实现教程

花韻仙語

花韻仙語

发布时间:2025-11-20 14:32:14

|

850人浏览过

|

来源于php中文网

原创

django 安全动态删除功能实现教程

本教程详细介绍了如何在 Django 应用中实现一个安全、精确的动态删除功能。针对用户遇到的删除按钮总是删除第一篇文章而非指定文章的问题,我们将通过优化后端视图函数和前端模板,确保删除操作能够正确地关联到用户点击的特定文章,并提供严格的权限验证,避免误删并提升用户体验。

1. 问题分析与解决方案概述

在 Django Web 应用中,实现文章或任何资源的安全删除功能是一个常见需求。用户常遇到的问题是,当页面上展示多篇文章并为每篇文章提供一个删除按钮时,点击删除按钮后,弹出的确认对话框可能显示错误的标题,或者实际删除的不是用户期望的那篇文章,而是列表中的第一篇或最后一篇。

这通常是由于以下两个主要原因造成的:

  1. 前端模板渲染问题:如果删除确认对话框(Modal)被定义为页面上的一个静态元素,并且其内容(如文章标题和删除链接)在页面加载时就已绑定到某个特定的文章对象(例如,列表中的第一个或最后一个),那么无论用户点击哪个删除按钮,都将操作同一个静态 Modal,从而导致错误的文章信息显示和错误的删除行为。
  2. 后端视图权限不足:即使前端能够正确传递文章 ID,如果后端视图没有进行严格的权限验证(例如,只有文章作者才能删除自己的文章),也可能导致安全漏洞或误操作。

本教程将通过以下步骤解决这些问题:

  • 优化 Django 后端视图函数,确保删除操作的精确性和安全性。
  • 改进前端模板,利用 JavaScript 动态更新删除确认 Modal 的内容,使其与用户点击的特定文章关联。

2. 后端视图函数优化

Django 的 views.py 中的删除逻辑需要确保两点:一是能够精确找到要删除的文章;二是验证当前用户是否有权限删除该文章。

原始视图函数

@login_required()
def delete(request, id):
     poost = get_object_or_404(post, pk=id) # 注意这里的 'post' 应该是模型类名,通常首字母大写
     if request.user == poost.author:
          poost.delete()
          messages.error(request, f'Post deleted!')
          return redirect("/")

问题与改进

  1. 模型类名:get_object_or_404(post, pk=id) 中的 post 应该是指向您的文章模型类,通常模型类名首字母大写,例如 Post。
  2. 权限验证:if request.user == poost.author: 这一行已经提供了基本的权限验证,这是非常好的实践。我们可以将其与 get_object_or_404 结合,使代码更简洁且更安全。

优化后的视图函数

from django.shortcuts import get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
# 假设您的文章模型名为 Post
from .models import Post # 根据您的实际模型路径调整

@login_required
def delete(request, id):
    """
    删除指定ID的文章。
    只有文章作者本人才能删除自己的文章。
    """
    try:
        # 尝试获取指定ID且作者为当前用户的文章
        # 如果文章不存在或当前用户不是作者,则返回404错误
        article = get_object_or_404(Post, pk=id, author=request.user)
        article.delete()
        messages.success(request, f'文章 "{article.title}" 已成功删除!') # 使用 success 消息更合适
        return redirect("/")
    except Exception as e:
        messages.error(request, f'删除文章失败:{e}')
        return redirect("/")

代码解释:

  • get_object_or_404(Post, pk=id, author=request.user):这一行是关键改进。它不仅通过 pk=id 查找指定 ID 的文章,还同时通过 author=request.user 验证当前登录用户是否是该文章的作者。如果文章不存在,或者存在但当前用户不是其作者,get_object_or_404 将直接抛出 Http404 异常,从而阻止未授权的删除操作,并减少了后续的 if 判断。
  • messages.success:删除成功后使用 success 消息类型比 error 更符合语义。
  • try-except 块:虽然 get_object_or_404 会处理找不到对象的情况,但为了更健壮的错误处理和用户反馈,可以包裹在一个 try-except 块中,捕获其他潜在异常。

3. 前端模板改进:动态更新删除 Modal

原始模板中,删除 Modal 的内容 {{ post.title }} 和删除链接 {% url 'delete' post.id %} 是在页面加载时静态渲染的。如果 post.html 是一个用于展示多篇文章的列表模板,并且 Modal 定义在循环之外,那么 Modal 将只会获取到循环中最后一个 post 对象的数据。为了解决这个问题,我们需要使用 JavaScript 在 Modal 显示之前,动态地将正确文章的数据注入到 Modal 中。

3.1 修改删除按钮

Favird
Favird

极其棒且有价值的互联网资源目录!

下载

在每个文章的删除按钮上,添加 data-* 属性来存储该文章的 ID 和标题。

{% if user.is_authenticated and user == post.author %}
    <a href="{% url 'update' post.id %}" class="btn btn-primary btn-small">Edit</a>
    <!-- 修改后的删除按钮,添加 data-post-id 和 data-post-title 属性 -->
    <a href="#" class="btn btn-danger btn-small delete-post-btn"
       data-toggle="modal"
       data-target="#deleteConfirmationModal"
       data-post-id="{{ post.id }}"
       data-post-title="{{ post.title }}">
       Delete <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
         <path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6Z"/>
         <path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1ZM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118ZM2.5 3h11V2h-11v1Z"/>
       </svg>
    </a>
{% endif %}
  • delete-post-btn:一个自定义类,用于 JavaScript 选中所有删除按钮。
  • data-post-id="{{ post.id }}":存储当前文章的 ID。
  • data-post-title="{{ post.title }}":存储当前文章的标题。
  • data-target="#deleteConfirmationModal":将 Modal 的 ID 从 exampleModal 修改为 deleteConfirmationModal,以避免与可能存在的其他 Modal 冲突,并提高语义化。

3.2 修改删除确认 Modal

将 Modal 的定义放在页面的任意位置,但确保它只被定义一次(通常在页面的底部或父模板中)。删除 Modal 中的静态 {{ post.title }} 和 {% url 'delete' post.id %},替换为用于动态更新的占位符。

<!-- 删除确认 Modal,确保只定义一次 -->
<div class="modal fade" id="deleteConfirmationModal" tabindex="-1" role="dialog" aria-labelledby="deleteConfirmationModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="deleteConfirmationModalLabel">确认删除文章</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <p class="text-muted">您确定要删除文章 "<strong id="modalPostTitle"></strong>" 吗?此操作无法撤销。</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
        <!-- 删除按钮的 href 将通过 JavaScript 动态设置 -->
        <a id="confirmDeleteLink" href="#" class="btn btn-danger">删除</a>
      </div>
    </div>
  </div>
</div>
  • id="modalPostTitle":一个 <strong> 标签,用于显示动态的文章标题。
  • id="confirmDeleteLink":删除按钮的 <a> 标签,其 href 属性将通过 JavaScript 动态更新。

3.3 添加 JavaScript 逻辑

使用 jQuery(因为模板中使用了 data-toggle="modal" 和 data-dismiss="modal",这通常是 Bootstrap 的行为,而 Bootstrap 依赖 jQuery)来监听 Modal 的 show.bs.modal 事件,并在 Modal 显示前更新其内容。

将以下 JavaScript 代码添加到您的模板文件(例如 post.html 的 <script> 标签内,或一个单独的 JS 文件中并在模板中引用)。

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
$(document).ready(function() {
    $('#deleteConfirmationModal').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget); // 获取触发 Modal 的按钮
        var postId = button.data('post-id'); // 从按钮的 data-post-id 属性中获取文章 ID
        var postTitle = button.data('post-title'); // 从按钮的 data-post-title 属性中获取文章标题

        var modal = $(this);
        // 更新 Modal 中的文章标题显示
        modal.find('#modalPostTitle').text(postTitle);
        // 更新 Modal 中删除链接的 href 属性
        // 假设您的删除 URL 模式是 /delete/<int:id>
        modal.find('#confirmDeleteLink').attr('href', '/delete/' + postId);
    });
});
</script>

代码解释:

  • $('#deleteConfirmationModal').on('show.bs.modal', function (event) { ... });:这是一个 Bootstrap Modal 事件监听器。当 deleteConfirmationModal 即将显示时,内部的回调函数会被执行。
  • var button = $(event.relatedTarget);:event.relatedTarget 是触发 Modal 显示的 DOM 元素(即用户点击的删除按钮)。
  • button.data('post-id') 和 button.data('post-title'):通过 jQuery 的 data() 方法,可以方便地读取 HTML 元素上 data-* 属性的值。
  • modal.find('#modalPostTitle').text(postTitle);:找到 Modal 中 ID 为 modalPostTitle 的元素,并将其文本内容设置为从按钮获取的文章标题。
  • modal.find('#confirmDeleteLink').attr('href', '/delete/' + postId);:找到 Modal 中 ID 为 confirmDeleteLink 的链接,并将其 href 属性设置为正确的删除 URL。请确保 /delete/ 与您的 urls.py 中定义的删除路径一致。

4. URL 配置 (urls.py)

您的 urls.py 配置已经能够正确捕获文章 ID,因此无需修改。

from django.urls import path
from . import views
# from .views import PostUpdateView # 如果PostUpdateView不是类视图,可能不需要这样导入

urlpatterns = [
    # ... 其他URL模式
    path('delete/<int:id>', views.delete, name='delete'), # 确保这里的 'delete' 对应您的视图函数名
    # ... 其他URL模式
]

这里的 path('delete/<int:id>', views.delete, name='delete') 定义了一个 URL 模式,它会捕获一个整数类型的 id 并将其作为参数传递给 views.delete 函数。前端 JavaScript 中 '/delete/' + postId 的构造与此模式完美匹配。

5. 注意事项与最佳实践

  • CSRF 保护:对于删除操作,最佳实践是使用 POST 请求,并包含 CSRF 令牌。虽然本教程的解决方案使用了 GET 请求(通过 <a> 标签),但在生产环境中,强烈建议将删除操作设计为 POST 请求。这可以通过在 Modal 中使用一个包含 CSRF 令牌的 <form> 标签来实现,表单提交到删除 URL。
    <!-- 推荐使用表单提交删除请求 -->
    <form id="deleteForm" method="post" action="">
        {% csrf_token %}
        <button type="submit" class="btn btn-danger">删除</button>
    </form>
    <script>
    // 在 JS 中更新表单的 action 属性
    modal.find('#deleteForm').attr('action', '/delete/' + postId);
    </script>

    对应的 views.py 需要检查 request.method == 'POST'。

  • 用户反馈:使用 Django 的 messages 框架为用户提供清晰的操作反馈(成功、失败)。
  • 前端样式:确保 Modal 的样式与您的网站主题一致,提供良好的用户体验。
  • 错误日志:在后端视图中加入适当的错误日志记录,

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python Web 框架 Django 深度开发
Python Web 框架 Django 深度开发

本专题系统讲解 Python Django 框架的核心功能与进阶开发技巧,包括 Django 项目结构、数据库模型与迁移、视图与模板渲染、表单与认证管理、RESTful API 开发、Django 中间件与缓存优化、部署与性能调优。通过实战案例,帮助学习者掌握 使用 Django 快速构建功能全面的 Web 应用与全栈开发能力。

166

2026.02.04

jquery插件有哪些
jquery插件有哪些

jquery插件有jQuery UI、jQuery Validate、jQuery DataTables、jQuery Slick、jQuery LazyLoad、jQuery Countdown、jQuery Lightbox、jQuery FullCalendar、jQuery Chosen和jQuery EasyUI等。本专题为大家提供jquery插件相关的文章、下载、课程内容,供大家免费下载体验。

156

2023.09.12

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

335

2023.10.13

jquery删除元素的方法
jquery删除元素的方法

jquery可以通过.remove() 方法、 .detach() 方法、.empty() 方法、.unwrap() 方法、.replaceWith() 方法、.html('') 方法和.hide() 方法来删除元素。更多关于jquery相关的问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

406

2023.11.10

jQuery hover()方法的使用
jQuery hover()方法的使用

hover()是jQuery中一个常用的方法,它用于绑定两个事件处理函数,这两个函数将在鼠标指针进入和离开匹配的元素时执行。想了解更多hover()的相关内容,可以阅读本专题下面的文章。

515

2023.12.04

jquery实现分页方法
jquery实现分页方法

在jQuery中实现分页可以使用插件或者自定义实现。想了解更多jquery分页的相关内容,可以阅读本专题下面的文章。

312

2023.12.06

jquery中隐藏元素是什么
jquery中隐藏元素是什么

jquery中隐藏元素是非常重要的一个概念,在使用jquery隐藏元素之前,需要先了解css样式中关于元素隐藏的属性,比如display、visibility、opacity等属性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

128

2024.02.23

jquery中什么是高亮显示
jquery中什么是高亮显示

jquery中高亮显示是指对页面搜索关键词时进行高亮显示,其实现办法:1、先获取要高亮显示的行,获取搜索的内容,再遍历整行内容,最后添加高亮颜色;2、使用“jquery highlight”高亮插件。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

183

2024.02.23

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

37

2026.03.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号