• Python + Django4 搭建个人博客(十二):实现删除文章功能页面


    前文我们实现了分别实现了显示文章,创建文章等功能。

    Python + Django4 搭建个人博客(十一): 利用表单实现创建文章的功能页面_李威威wiwi的博客-CSDN博客本篇我们学习了使用Django用于处理表单的Form类,利用forms.ModelForm 类的继承功能,我们实现了表单和模型的直接关联。基于表单功能,我们完成了创建文章的功能页面。接下来两篇我们陆续完成剩下的文章修改和删除的功能页面。...https://blog.csdn.net/agelee/article/details/126644558

    本篇我们实现删除文章的功能。

    简单功能实现

    删除文章单从功能实现上面来说很简单,视图函数如下:

    1. # 删文章
    2. def article_delete(request, id):
    3. # 根据 id 获取需要删除的文章
    4. article = Article.objects.get(id=id)
    5. # 调用.delete()方法删除文章
    6. article.delete()
    7. # 完成删除后返回文章列表
    8. return redirect("list")
    • 与查询文章类似,因为需要知道具体应该删除哪一篇文章,因此必须传入文章的id;
    • 紧接着调用.delete()函数删除数据库中这篇文章的条目;
    • 删除成功后返回到文章列表。

    然后修改下路由配置文档

    1. urlpatterns = [
    2. path('admin/', admin.site.urls),
    3. path('hello/', views.hello),
    4. re_path(r'^$', views.article_list),
    5. path('list/', views.article_list, name='list'), # 展示文章
    6. path('detail//', views.article_detail, name='detail'), # 文章详情
    7. path('create/', views.article_create, name='create'), # 写文章
    8. # 增加生删除文章
    9. path('delete//', views.article_delete, name='delete'),
    10. ]

    最后修改模板,在详情页面detail.html增加一个删除文章的按钮。

    1. <div class="container">
    2. <h1 class="col-12 mt-4 mb-4">{{ article.title }}h1>
    3. <div class="col-12 alert alert-primary">
    4. <div class="col-12">
    5. <a>作者:{{ article.author }}a>
    6.  
    7. <a>{{ article.created|date:'Y-m-d H:i:s' }}a>
    8.  
    9. <a href="{% url "delete" article.id %}">删除文章a> #增加此项
    10. div>
    11. div>
    12. <div class="col-12">
    13. <p>{{ article.body }}p>
    14. div>
    15. div>

    运行服务器之后,可以看到已经增加了删除文章按钮。

    删除弹窗确认功能

    上面实现了一个简单的功能,不过有一个隐患,就是如果是不小心点到了删除按钮,可能连后悔的机会都没了。

    一般这种涉及到数据直接清除的动作,要加一个弹窗确认的动作,二次确认后才能直接删除数据库数据。

    实现这个功能我们可以使用Bootstrap的模态框的组件。

    模态框(Modal)是覆盖在父窗体上的子窗体。通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动。子窗体可提供信息交互等。

    detail.html中之前新增加的那行删除文章代码进行如下修改:

     "#" data-bs-toggle="modal" data-bs-target="#myModal">删除文章

    增加了模态框效果,点击此链接会跳弹出名为myModal的模态框。

    接着我们实现myModal模态框删除文章的功能。

    1. <div class="modal fade" id="myModal">
    2. <div class="modal-dialog modal-dialog-centered modal-sm">
    3. <div class="modal-content">
    4. <div class="modal-header">
    5. <h4 class="modal-title">确认删除h4>
    6. <button type="button" class="btn-close" data-bs-dismiss="modal">button>
    7. div>
    8. <div class="modal-body">
    9. 确认删除文章?
    10. div>
    11. <div class="modal-footer">
    12. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消button>
    13. <button type="button" class="btn btn-primary" data-dismiss="modal" onclick="confirm_delete()">
    14. 确定
    15. button>
    16. div>
    17. div>
    18. div>
    19. div>
    20. <script>
    21. // 删除文章的函数
    22. function confirm_delete() {
    23. location.href = '{% url "delete" article.id %}'
    24. }
    25. script>

    这里我们实际上实现了两个功能。

    • 实现了名为myModal的模态框,在模态框中增加了两个按钮:取消,确认。点击确认会调用JS函数confirm_delete()删除文章。
    • 编写了函数confirm_delete(),会调用Django的删除文章url:delete,实现删除功能。

    安全的方式

    可能你认为删除文章功能实现起来没什么难度,但是请注意,上面的方法是有隐患的。要继续深入探讨,就得提到跨域请求伪造攻击,也称为CSRF攻击了(Cross-site request forgery)。

    CSRF攻击

    CSRF攻击你可以理解为:攻击者盗用了你的身份,以你的名义发送恶意请求。还是拿删除文章举例:

    • 用户登录了博客网站A,浏览器记录下这次会话,并保持了登录状态;
    • 用户在没有退出登录的情况下,又非常不小心的打开了邪恶的攻击网站B
    • 攻击网站B在页面中植入恶意代码,悄无声息的向博客网站A发送删除文章的请求,此时浏览器误以为是用户在操作,从而顺利的执行了删除操作。

    由于浏览器的同源策略,CSRF攻击者并不能得到你的登录数据实际内容,但是可以欺骗浏览器,让恶意请求附上正确的登录数据。不要小看CSRF攻击的威力:倘若是你的银行账户具有此类安全漏洞,黑客就可以神不知鬼不觉转走你的所有存款。

    所以这里如何防范CSRF攻击的风险呢?方法是有的,即删除文章时用POST方法,并且校验csrf令牌。

    CSRF令牌

    前面我们讲到在 Django 中提交表单必须加csrf_token,这个就是CSRF令牌了,它防范CSRF攻击的流程如下:

    • 当用户访问 django 站点时,django 反馈给用户的表单中有一个隐含字段 csrf_token,这个值是在服务器端随机生成的,每次都不一样;
    • 在后端处理 POST 请求前,django 会校验请求的 cookie 里的 csrf_token 和表单里的 csrf_token 是否一致。一致则请求合法,否则这个请求可能是来自于 CSRF攻击,返回 403 服务器禁止访问。

    由于攻击者并不能得到用户的 cookie 内容(仅仅是靠浏览器转发),所以通常情况下是无法构造出正确的 csrf_token 的,从而防范了此类攻击。

    利用Form发送Post请求

    在Django中实现发送Post请求可以通过Form中指定请求方法。

    首先在删除文章按钮代码下面增加一个隐藏的Form表单:

    1. <a href="#" data-bs-toggle="modal" data-bs-target="#myModal">删除文章a>
    2. <form
    3. style="display:none;"
    4. id="safe_delete"
    5. action="{% url "delete" article.id %}"
    6. method="POST"
    7. >
    8. {% csrf_token %}
    9. <button type="submit">发送button>
    10. form>

    接着我们修改下我们的confirm_delete()函数。

    1. <script>
    2. // 删除文章的函数
    3. function confirm_delete() {
    4. document.getElementById("safe_delete").submit();
    5. }
    6. script>

    最后我们改造下视图函数:

    1. # 删文章
    2. def article_delete(request, id):
    3. print(request.method)
    4. if request.method == 'POST':
    5. # 根据 id 获取需要删除的文章
    6. article = Article.objects.get(id=id)
    7. # 调用.delete()方法删除文章
    8. article.delete()
    9. return redirect("list")
    10. else:
    11. return HttpResponse("仅允许post请求")

    之前我们的函数是直接调URL请求Django的视图删除函数。

    现在我们改造之后,删除文章的代码流程如下:

    • 点击删除文章链接时,弹出模态框
    • 点击模态框的确认按钮后,通过JS函数代码找到隐藏的Form,并提交表单。
    • 表单发起 POST 请求,并携带了 csrf 令牌(Django对所有的Post请求都通过中间件默认进行csrf 校验),从而避免了 csrf 攻击。

    结语

    本篇我们学习了如何实现删除文章的功能,同时使用了Bootstrap的模态框弹框,来进行删除文章的二次校验。

    涉及到删除功能,为了增加数据安全性,我们简单介绍了Django的csrf 令牌保护机制,并通过使用隐藏表单,发送Post请求的方式,启用了Django的crsf检验机制。

    删除功能实际上还有一个重要的校验:用户校验,我们还没涉及,后面在增加用户模块功能的时候我们再安排增加上。

    下一篇将学习如何更新文章。

  • 相关阅读:
    数据结构——顺序表
    GAMES101 作业0 环境配置 超详细小白教程
    uniapp项目实践总结(十九)版本更新和热更新实现方法
    java计算机毕业设计医院出入院管理系统源程序+mysql+系统+lw文档+远程调试
    [附源码]Python计算机毕业设计Django架构的博客平台设计
    Java多线程(2)
    Dev C++编写C/C++程序 出现[Error] ld returned 1 exit status报错分析及解决
    云原生周刊:KubeSphere 3.4.1 发布 | 2023.11.13
    世微 降压恒流驱动IC 景观亮化洗墙灯舞台灯汽车灯LED照明 AP5199S
    011-盛最多水的容器-力扣
  • 原文地址:https://blog.csdn.net/agelee/article/details/126702871