删除文章
既然有了写文章的功能,那当然也必须要有删除文章的功能了。
不安全的方式
有了之前的学习做铺垫,删除文章实现起来就比较简单了。
首先增加一个视图函数:
与查询文章类似,因为需要知道具体应该删除哪一篇文章,因此必须传入文章的
id
;紧接着调用
.delete()
函数删除数据库中这篇文章的条目;删除成功后返回到文章列表。
这里与上一章一样,不对用户的身份进行限制,即任何人都可以删除任意文章。当然这样肯定是不符合常理的,等到我们学习了用户管理的知识后,再回头来修改。
然后写入路由信息:
这里几乎与文章详情的写法一样,没有新的内容。再次注意文章的id是如何传递到视图中的。
最后我们希望能够在文章详情的页面进行删除的操作(当然也可以在专门的管理文章的页面中),因此修改模板detail.html
:
这里增加了一个调用article_delete
视图函数的链接,并且将article.id
传递进去。
运行开发服务器,可以发现已经能够正常的删除文章了:

增加弹窗
功能已经实现了,但是还有个小问题没有解决:万一我只是不小心点到了链接,辛辛苦苦写的文章就被删除了,岂不是欲哭无泪了?
很容易想到的一个解决方法,就是点击删除按钮是出现一个弹窗,确认后再进行删除,确保用户不是误操作的。
弹窗是很常用的功能,但是想写出一个美观好用的弹窗却不容易。幸运的是我们不需要重复造轮子,早就有革命先驱做好相关的功能了,这里我们选择使用Layer弹窗组件。
layer是一款备受青睐的web弹层组件,具备全方位的解决方案。首先到官网下载Layer插件: Layer
解压后将里面的**layer文件夹(含有layer.js的)**直接复制到项目的static
文件夹下。
为了未来在所有页面都能使用Layer弹窗功能,在base.html
中通过标签引入:
layer插件依赖jquery才能正常工作,因此要在jquery的后面引入layer。
再次改写模板文件detail.html
:
<a>
标签中增加了onclick
属性,表示在点击链接时调用后面的confirm_delete()
函数。confirm_delete()
函数中调用了layer弹窗组件 ,对弹窗的标题、 正文以及确定键进行了定义。location.href
是点击确定键后应该前往的地址,即删除文章的url。 (当然Layer组件远不止这些用法,具体可在官方文档中查阅)。通过
onclick
实现了功能逻辑,因此href
链接就不需要再跳转了。
保存所有文件后刷新页面,很好,达到了理想的效果:

安全的方式
可能你认为删除文章功能实现起来没什么难度,但是请注意, 上面的方法是有隐患的 。要继续深入探讨,就得提到跨域请求伪造攻击 ,也称为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
的,从而防范了此类攻击。原理就是这样,下面来看看如何实现安全的删除功能。
代码实现
首先修改删除文章的链接,以及点击它时调用的函数:
代码流程如下:
点击删除文章链接时,弹出 layer 弹窗
弹窗不再发起 GET 请求,而是通过 Jquery 选择器找到隐藏的表单,并点击发送按钮
表单发起 POST 请求,并携带了 csrf 令牌,从而避免了 csrf 攻击
接着添加表单提交的url:
最后就是将新的删除视图写好:
可能你要问了,没发现哪行代码校验了csrf
令牌啊?放心,默认配置下所有的 POST 请求都由 Django 中间件帮你验证了。另外视图一定要限制为 POST 请求,即if request.method == 'POST'
必须有,就请读者思考一下原因吧。
总结
本章新增了删除博客文章的功能,并且使用了弹窗组件优化了用户体验。
另一个重要的知识点就是CSRF攻击的防范。记住一条,凡是重要的数据操作,都应该考虑带有 csrf 令牌的 POST 请求;或者更简单的方法,数据查询用 GET,数据更改用 POST。
注意这个删除文章的功能并没有对用户身份进行验证。别急,等到讲完用户管理之后再来处理。
下一章将学习如何更新文章,准备好继续作战吧。
项目完整代码: Django_blog_tutorial