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

news/2024/5/5 22:59:26/文章来源:https://blog.csdn.net/agelee/article/details/126702871

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

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

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

简单功能实现

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

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

然后修改下路由配置文档

urlpatterns = [path('admin/', admin.site.urls),path('hello/', views.hello),re_path(r'^$', views.article_list),path('list/', views.article_list, name='list'),  # 展示文章path('detail/<int:id>/', views.article_detail, name='detail'),  # 文章详情path('create/', views.article_create, name='create'),  # 写文章# 增加生删除文章path('delete/<int:id>/', views.article_delete, name='delete'),
]

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

<!-- 文章详情 --><div class="container"><!--    <div class="row">--><!-- 标题及作者 --><h1 class="col-12 mt-4 mb-4">{{ article.title }}</h1><div class="col-12 alert alert-primary"><div class="col-12"><a>作者:{{ article.author }}</a>&nbsp<a>{{ article.created|date:'Y-m-d H:i:s' }}</a>&nbsp<a href="{% url "delete" article.id %}">删除文章</a>   #增加此项</div></div><!-- 文章正文 --><div class="col-12"><p>{{ article.body }}</p></div></div>

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

删除弹窗确认功能

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

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

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

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

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

 <a href="#" data-bs-toggle="modal" data-bs-target="#myModal">删除文章</a>

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

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

<!-- 模态框 --><div class="modal fade" id="myModal"><div class="modal-dialog modal-dialog-centered modal-sm"><div class="modal-content"><!-- 模态框头部 --><div class="modal-header"><h4 class="modal-title">确认删除</h4><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div><!-- 模态框主体 --><div class="modal-body">确认删除文章?</div><!-- 模态框底部 --><div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button><button type="button" class="btn btn-primary" data-dismiss="modal" onclick="confirm_delete()">确定</button></div></div></div></div><script>// 删除文章的函数function confirm_delete() {location.href = '{% url "delete" article.id %}'}</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表单:

 <a href="#" data-bs-toggle="modal" data-bs-target="#myModal">删除文章</a><!-- 新增一个隐藏的表单 --><formstyle="display:none;"id="safe_delete"action="{% url "delete" article.id %}"method="POST">{% csrf_token %}<button type="submit">发送</button></form>

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

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

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

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

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

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

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

结语

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_5774.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux Kernel TCP/IP Stack|Linux网络硬核系列

介绍Linux网络技术中最核心的部分--TCP/IP协议栈 。 我们先看一下抽象的网络协议栈模型 再按分层思想看Linux内核协议栈实现框架 1. socket layer socket框架 socket系统调用(socket,bind,listen,accept,send,recv等)BSD socket API协议栈sock抽象适配层tcp/udp/icmp/ra…

图论——欧拉回路

一、前置知识 1、连通、极大联通子图连通:图中任意两点皆可互达 极大连通子图:对连通图来说:是这个连通图本身 对非连通图来说: 有多个极大联通子图2、回路、简单回路、简单路径回路:从一个点到经过一些其他节点,再回到该点的一个路径。此时,除了起点和终点,其他节点也…

Python做一个中秋节嫦娥投食小游戏

山河远阔&#xff0c;烟火人间&#xff0c;又一年&#xff0c;千里婵娟~ 今天给大家带来的是给玉兔投喂月饼的小游戏。八月十五中秋夜晚&#xff0c;让我们对着月亮许愿&#xff1a;希望我们在意和在意我们的人&#xff0c;诸邪避退、百事无忌、平安喜乐、万事胜意。提前祝大家…

VMware Workstation虚拟机怎么和主机之间互传文件?

VMware Workstation虚拟机怎么和主机之间互传文件?前言 工具/材料 操作方法前言 在使用Windows 10工作时会遇到形形色色的问题,比如虚拟机需要与主机之间互传文件。那么如何进行设置呢?下面小编与你分享具体步骤和方法。 工具/材料 Windows 10操作系统 操作方法启动Windows …

前端JS-Day21

client系列:获得可视区域的相关信息clientWidth和offsetWidth区别:clientWidth只包含内容和padding,offsetWidth包含内容和内外边框。 立即执行函数:无需调用,直接执行。且独立创建了一个作用域。(function() {})(); (function(){}()); 两种写法 像素比:即devicePixe…

STM32使用串口空闲中断(IDLE)和 DMA接收一串数据流

STM32使用串口空闲中断&#xff08;IDLE&#xff09;和 DMA接收不定长数据 方法一、使用宏定义判断IDLE标志位 空闲的定义是总线上在一个字节的时间内没有再接收到数据&#xff0c;USART_IT_IDLE空闲中断是检测到有数据被接收后&#xff0c;总线上在一个字节的时间内没有再接…

spring cloud alibaba (一)

Spring Cloud Alibaba官网:https://spring.io/projects/spring-cloud-alibaba gitHub:https://github.com/alibaba/spring-cloud-alibaba这节主要目标:掌握nacos使用 了解服务与服务之间调用1、简介 1.1、什么是分布式 将一套系统拆分成不同子系统部署在不同服务器上(这叫分…

flex常用布局

公共样式:<style>* {margin: 0;padding: 0;}.has-flex {display: flex;}</style> 垂直居中 子元素左右分布 css.father-one {width: 100%;height: 200px;background-color: #fffcef;align-items: center; /*纵轴)方向上的对齐方式。*/justify-content: space-bet…

5.2 创建个人中心页面-前端部分

&#x1f60a;如果写的可以帮到你&#xff0c;可以点个赞吗&#xff0c;你的支持就是我写下去的动力。&#x1f60a; 本文阅读大概 10 分钟, 自己写加思考大概 1 ~ 2 小时。建议&#xff1a;代码可以手抄&#xff0c; 但不要复制。 1. 整体框架 2. 前端页面布局 使用 bootstra…

达梦数据库图形化工具

图形化工具列表 (1)DM数据库配置助手 (2)DM服务查看器 (3)DM管理工具 (4)DM控制台工具 (5)DM数据库迁移工具 (6)DM性能监测工具图形化工具详解 界面展示DM数据库配置助手[dmdba@localhost tool]$ ./dbca.sh DM服务查看器DM管理工具DM控制台工具DM数据库迁移工具DM性能监测工具功…

马拉车算法

这篇博客写的非常清晰 https://zhuanlan.zhihu.com/p/549242325 给定一个字符串,问有多少个以 k,f,c 结尾的回文子串。#include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long const int maxn=1e6+5; int n,sum; ll len[maxn…

22-09-04 西安 谷粒商城(01)MySQL主从复制、MyCat读写分离、MyCat分库分表

人人尽说江南好&#xff0c;游人只合江南老。 春水碧于天&#xff0c;画船听雨眠。 MySQL主从复制 mysql主从复制&#xff1a;分摊读写压力&#xff08;cpu计算压力&#xff09; 写交给主库&#xff0c;读有主从分摊处理&#xff08;原因是写操作较少&#xff0c;读操作较多&…

面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!

由于现在大多计算机都是多核CPU,多线程往往会比单线程更快,更能够提高并发,但提高并发并不意味着启动更多的线程来执行。更多的线程意味着线程创建销毁开销加大、上下文非常频繁,你的程序反而不能支持更高的TPS。 时间片 多任务系统往往需要同时执行多道作业。作业数往往大…

ABAP-LP01和PDF打印机配置

事务代码SPAD1.LP01配置2.PDF配置

Netty+WebSocket整合STOMP协议

1.STOMP协议简介 常用的WebSocket协议定义了两种传输信息类型:文本信息和二进制信息。类型虽然被确定,但是他们的传输体是没有规定的,也就是说传输体可以自定义成什么样的数据格式都行,只要客户端和服务端约定好,得到数据后能够按照约定的语义解析数据就好。相较于Http协议…

猿创征文|我的后端成长之路(985科班两年,我发现了大学正确打开方式)

零.前言 当看到官方的这个活动的时候&#xff0c;我突然感到手指充满了力量&#xff0c;好像是我的键盘要向我尖端放电&#xff0c;谁还不是怀着满腔的热忱来写这篇文章帮助未来的学弟学妹们避坑呢&#xff1f;(其实是为了活动的奖励&#x1f917;)。不过不要在意这些细节&…

本地连接是干什么的?

当您创建家庭或小型办公网络时&#xff0c;运行 windows XP Professional 或 windows XP home edition 的计算机将连接到局域网 (Lan)。 安装 windows XP 时&#xff0c;将检测您的网络适配器&#xff0c;而且将创建本地连接。 像所有其他连接类型一样&#xff0c;它将出现在…

【深蓝学院】- Multiplane Images and Neural Rendering

01 view Synthesis problem Definition 02 View synthesis with multiplane Image(MPI) MPI的缺陷&#xff1a; 不是真正的三维表达不同视角观测的RGB是不变的 与MPI不一样的地方&#xff1a;不是手工设计的&#xff0c;而是整体输入 不同视角的RGB是不一样的 缺陷&#xff1…

Pytorch优化器全总结(一)SGD、ASGD、Rprop、Adagrad

目录 写在前面 一、 torch.optim.SGD 随机梯度下降 SGD代码 SGD算法解析 1.MBGD&#xff08;Mini-batch Gradient Descent&#xff09;小批量梯度下降法 2.Momentum动量 3.NAG(Nesterov accelerated gradient) SGD总结 二、torch.optim.ASGD随机平均梯度下降 三、torc…

【手把手】ios苹果打包——遇见项目实战|超详细的教程分享

六年代码两茫茫&#xff0c;不思量&#xff0c;自难忘 6年资深前端主管一枚&#xff0c;只分享技术干货&#xff0c;项目实战经验 关注博主不迷路~ 文章目录前言weex介绍eeui介绍一、安装CocoaPods1.CocoaPods介绍2.CocoaPods的安装二、登录开发者中心四、添加测试手机设备五、…