当前位置: 首页 > 后端技术 > Python

用Django搭建个人博客:基于LocalStorage的点赞功能

时间:2023-03-26 13:30:37 Python

假设您的博客已经部署成功上线。你写了很多好文章,和粉丝互动,很有成就感。现在你想更进一步,努力提高文章质量,让文章更受读者欢迎,打造自己圈子里一流的博客。问题是如何判断一篇文章是否“流行”?靠浏览量是一种方法,但无法区分头条党和它的内容。靠评论数也是一个不错的方法,但是个人博客通常没有多少读者,好文章零评论也是很正常的。这时候,“赞”的功能就很重要了。如果大多数读者都点赞,就说明这篇文章真的很好。做之前先想好点赞的功能并不简单,实现的方式有很多种。不要急着去做,耐心想想:我们的博客需要什么样的点赞?首先,点赞需要用户登录吗?要求登录的好处是可以准确记录哪些用户、哪些文章被点赞(多对多关系),以便进行详细的数据分析。缺点是登录要求很繁琐,会阻止大多数旅游用户。博主往往不要求用户登录,毕竟小站通常用户不多,提高参与度是点赞的核心任务。万一有一天你的小站火了,给个需要用户登录“收藏夹”的交互功能吧!第二,用户可以重复点赞吗?很多视频平台的用户都可以疯狂点赞某位女主播,以此来表达自己非常非常的喜欢。这对于用户量大的平台来说不是问题,因为用户量增加后,几百个点赞只是九牛一毛。但是,博客网站很容易导致一些文章的点赞数为零,而一些文章的点赞数高得惊人。显然,这并不代表文章质量的差异。那么我们现在的政策是不要求用户登录,也不允许用户重复点赞。接下来的问题是,用户喜欢的相关数据记录到哪里呢?毫无疑问,点赞数必须存储在数据库中,以便随时检索和呈现数据。但问题是查看用户是否点赞的记录在哪里呢?是一种在数据库中记录用户IP地址的方法,但是你要处理记录IP和记录登录用户的关系,有点麻烦。另外,用户每点赞一次,都需要向后台发送一次验证请求,增加了服务器的负担。既然数据保存在后台数据库不好,那能不能保存在浏览器中呢?答案是肯定的,并且有Cookies和LocalStorage两种方式可以让你保存数据。两者主要区别如下:CookieLocalStorage特性的生命周期可以设置过期时间。默认是关闭浏览器过期,除非被清除,否则永久存储空间在4K左右,一般为5MB。与服务器的通信每次都会在HTTP头中携带,不参与。易于与服务器通信。本机界面不友好。本机接口是可以接受的。对比之后你会发现LocalStorage可以永久存储数据,存储空间大,不参与服务器通信。非常适合喜欢的需求。由于数据保存在浏览器中,所以不需要区分用户是否登录过:其实每次点赞都是检查当前浏览器是否已经点赞,而不是用户!也许你会反驳,用户换个浏览器,能不能反复点赞,更何况浏览器端的数据非常容易被篡改。但这有什么关系呢?像数据不需要很精确,就让他去吧。所有现代浏览器都支持LocalStorage功能。如果您仍在使用IE6,请考虑立即升级您的浏览器。总结一下,我们的点赞功能是这样的:不需要用户登录,不允许重复点赞。点赞数保存在服务器数据库中。点赞验证数据保存在浏览器的LocalStorage中。当用户点赞时,前端脚本会将其保存在LocalStorage中。检查您是否已经喜欢它;如果您还没有点赞过,您将向服务器发送点赞请求并记录数据。把自己的需求想清楚了,问题就迎刃而解了。接下来是代码实现。需要说明的是,以上分析并不是说其他??方法不好,只是博主觉得适合博客站点环境的技术路径。如果你心中还有另一个哈姆雷特,那就想办法实现它。代码实现准备本章的重点是前端,所以先写简单的后端代码,作为热身。有些读者一听到前端就头疼。我理解你的痛苦,但这也是必要的。你不能仅仅通过编写Python来制作一个漂亮的网站。由于点赞数需要保存在数据库中,所以需要修改文章模型:article/models.py...#文章模型类ArticlePost(models.Model):...#添加点赞统计likes=models.PositiveIntegerField(default=0)...Migratingdata:(env)>pythonmanage.pymakemigrations(env)>pythonmanage.pymigrate继续使用classviews:article/views.py...#Likes+1classIncreaseLikesView(查看):defpost(self,request,*args,**kwargs):article=ArticlePost.objects.get(id=kwargs.get('id'))article.likes+=1article.save()的returnHttpResponse('success')的作用是点赞数加1,返回成功。至于为什么成功,后面再说。最后是路由:article/urls.py...urlpatterns=[...#Like+1path('increase-likes//',views.IncreaseLikesView.as_view(),name='increase_likes'),]非常简单。剩下的就是专心写前端代码了。JS和Ajax需要做大量的前端工作,因为验证数据存储在浏览器中。先贴出完整代码(后面解释):templates/article/detail.html...

{{article.body|safe}}

喜欢{{article.likes}}
...{%blockscript%}...{%endblockscript%}代码内容比较多,我们拆开解释一下喜欢{{article.likes}}
上面的HTML代码功能很简单,它提供了一个like按钮,当按钮被点击时,会触发一个JavaScript函数调用validate_is_like。特别要注意'{%url'article:increase_likes'article.id%}'中使用的单引号。此处不得使用双引号。读者应该想一想原因。还记得csrf.js吗?我们已经在多级评论区介绍过了,这样ajax也可以通过csrf验证。如果您没有此文件,请单击链接下载。接下来是占篇幅最多的函数validate_is_like(),我们把里面的内容拆分一下。//取出LocalStorage中的数据letstorage=window.localStorage;conststorage_str_data=storage.getItem("my_blog_data");letstorage_json_data=JSON.parse(storage_str_data);//如果数据不存在,创建一个空字典如果(!storage_json_data){storage_json_data={}};在浏览器中,window对象是指当前浏览器窗口。它也是当前页面的顶级对象(即最高级对象),其他所有对象都是它的下属,localStorage也是如此。要验证数据,必须先获取数据。这里使用localStorage.getItem()接口检索数据。LocalStorage的存储方式虽然是标准的键值对类型(类似于Python字典),但奇怪的是存储的值只支持字符串类型。所以这里使用JSON.parse()将字符串还原为一个对象。当用户第一次点赞的时候,LocalStorage中肯定没有数据,所以if语句的作用就是创建一个空字典以供使用。//检查当前文章是否被点赞。如果是,status=trueconststatus=check_status(storage_json_data,id);if(status){layer.msg('我已经点赞了~');//如果我喜欢,我会立即退出该函数return;}else{//使用Jquery查找点赞数,并+1$('span#likes_number').text(likes+1).css('color','#dc3545');}然后立即调用check_status函数,查看用户是否已经对这篇文章点赞。如果点击,会有弹窗提示,validate_is_like函数会立即return终止,不会执行后面的代码;如果没有被点击,按钮的点赞数+1。但是此时后台数据库中的点赞数还没有更新。然后往下看。//使用ajax向后端发送post请求$.post(url,//post只是为了csrf验证,所以数据为空{},function(result){if(result==='success'){//尝试修改like数据try{storage_json_data[id]=true;}catch(e){window.localStorage.clear();};constd=JSON.stringify(storage_json_data);//尝试存储like数据toLocalStoragetry{storage.setItem("my_blog_data",d);}catch(e){//代码22错误意味着LocalStorage已满if(e.code===22){window.localStorage.clear();storage.setItem("my_blog_data",d);}};}else{layer.msg("与服务器通信失败..稍后再试~");}});这里尝试与后端通信并更新点赞。整个代码被$.post()包裹起来,其实就是一个Ajaxpost请求。function(result){...}是一个回调函数,只有在请求成功时才会执行,参数result为后端的返回值。如果通信成功,尝试将点赞的验证数据保存到LocalStorage。在发生任何错误时(尤其是LocalStorage已满的错误),LocalStorage中的所有数据将被清除,以便后续记录数据。可以看出博主采用的数据结构比较简单,像这样:{2:true,31:true...}key代表文章的id,boolean值代表点赞的状态。以上数据表示id为2和31的文章被点赞。读者可能希望以后喜欢文章、评论等内容,所以需要设计更复杂的数据结构。//辅助点赞主函数,验证点赞状态functioncheck_status(data,id){//尝试查询点赞状态try{if(idindata&&data[id]){returntrue;}else{返回错误;}}catch(e){window.localStorage.clear();返回假;};};至于check_status()函数,就很简单了。它的作用是检查是否被点赞,被点赞则返回true,否则返回false。整个JavaScript脚本就完成了。DebugInterface读者在调试过程中可能会遇到各种各样的问题。请按Ctrl+Shift+I打开浏览器控制台的Console界面,使用如下命令调试:localStorage:查看LocalStorage数据localStorage.clear():清除所有数据localStorage.getItem():获取某条数据localStorage.setItem():保存某条数据测试代码完成,然后打开文章详情页进行测试:点击赞按钮,点赞数+1;再次点击赞按钮,点赞数不会增加,会弹窗提示用户点击。您可以尝试随意关闭页面或浏览器,保存的点赞验证数据不会消失。这样就完成了一个简单的like函数。当然你还可以继续优化:没有被点赞的心应该显示成灰色,点过的爱心应该显示成红色,这样更人性化发送通知消息呢?...教程篇幅有限,不打算再深入下去,就当做给读者朋友们的课后作业,用心完成吧。喜欢你!第一个技巧:页面初始加载时,红心统一显示为灰色,然后调用JavaScript脚本比对LocalStorage中的数据,灵活使用Jquery改变已点赞红心的颜色红色的。综上所述,我们的博客项目现在有一个层次化的用户交互结构:pageview数据最轻,评估文章类型的流行度;like数据比较均衡,评价文章内容的受欢迎程度;评论数据是最繁琐的,但价值也是最高的。读者以后在开发功能的时候,也要像这样想清楚核心需求。还有一点需要说明的是,LocalStorage中只存储了非敏感和不重要的数据,不要过度依赖它。同样,为了便于解释,教程的代码文件变得越来越大。请在适当的时候将其拆分成多个更小的组件,以便于维护和重复使用。如有任何问题,请在杜赛个人网站留言,我会尽快回复。或者私信给我:dusaiphoto@foxmail.com项目完整代码:Django_blog_tutorial