Django实战专题:开发专业博客(3)之仿微信评论点赞功能

在我们前两遍文章里,我们已经创建一个比较完善的Article模型,利用Django的通用视图开发了博客的管理后台,实现了文章的增删查改。我们还配置了CKEditor实现博客文章的富文本编辑(包括上传图片和显示代码)。在本文中我们将对该博客做进一步改进,利用AJAX技术实现仿微信评论的点赞功能。当登录用户点击大拇指按钮时,文章总点赞次数在页面无需刷新的情况下自动加1,当用户再次点击大拇指时,取消点赞,总点赞次数自动减1。非登录用户在点击大拇指按钮时,会被要求先登录。本文参考了部分Django By Example的内容。

如果你还没有阅读过本专题,请务必先阅读之前两篇文章:

实现思路

我们在Article模型里增加一个users_like的字段,记录点赞的用户,其与User是多对多的关系(如下所示)。有了这个字段,我们可以使用article.users_like.all查询点赞某篇文章的所有用户,还可以使用article.users_like.count来统计某篇文章的总点赞数。通过使用user.articles_liked.all可以查询某个用户所喜欢的所有文章条目。

# models.py

classArticle(models.Model):

"""文章模型"""

slug = models.SlugField('slug',max_length=60,blank=True)

body = RichTextUploadingField('正文')

pub_date = models.DateTimeField('发布时间',null=True)

.....

users_like = models.ManyToManyField(User,

related_name='articles_liked',blank=True)

当用户在前端页面点击大拇指按钮时,我们希望其触发一个AJAX请求到后台。这个AJAX请求发送的数据应包括文章id和动作(like和unlike)。因为request是全局变量,所以即使Ajax发送的数据里即使不包括用户,我们也可以知道request.user是谁。有了文章id,用户和动作,我们就可以轻易的处理请求,并返回Json格式的状态了。

我们现在需要在urls.py里新增一个名为article_like的url, 专门处理Ajax请求。

#urls.py

fromdjango.urlsimportpath,re_path

from.importviews

# namespace

app_name ='blog'

urlpatterns = [

re_path(r'^article/like/$',

views.article_like,name='article_like'),

]

上述url对应的视图函数如下所示:

# views.py

fromdjango.views.decorators.httpimportrequire_http_methods

fromdjango.contrib.auth.decoratorsimportlogin_required

@login_required

@require_http_methods(["POST"])

defarticle_like(request):

article_id = request.POST.get('id')

action = request.POST.get('action')

ifarticle_idandaction:

try:

article = Article.objects.get(id=article_id)

ifaction =='like':

article.users_like.add(request.user)

else:

article.users_like.remove(request.user)

returnJsonResponse({'status':'ok'})

except:

pass

returnJsonResponse({'status':'fail'})

上面这段代码是这么工作的:

我们使用@login_required和@require_http_methods两个装饰器用户必需要先登录才能点赞,而且只接收通过POST方式发送过来的请求。

如果发送过来的Ajax POST请求包括article_id和action两个参数。我们根据action对数据库进行更新。如果操作成功,就给前端返回Json格式的数据{"status":"ok"}。我们在模型的多对多字段上使用了 Django 提供的或者方法来执行多对多关系的建立和删除, 这个方法并save方法更快捷。

如果用户未登陆或某些操作未成功,我们给前端返回Json数据{"status":"fail"}

模板与Ajax代码

最后我们需要在article_detail模板加入下面2段代码,实现本文所需要的功能。

# blog/template/article_detail.html

第一段为html代码,主要用来展示点赞按钮和总点赞数。我们设置了data-id和data-action两个参数,便于Ajax通过DOM获取文章id和action。我们先判断当前用户是否在已点赞用户清单里,如果在的话,action变为unlike。如果不在的话,action为like。

{% if article.status == "p" %}

发布于{{ article.pub_date | date:"Y-m-j" }}浏览{{ article.views }}次

{% with total_likes=article.users_like.count users_like=article.users_like.all %}

data-action="{% if request.user in users_like %}un{% endif %}like"

class="like button">

class="glyphicon glyphicon-thumbs-up count">{{ total_likes }}

{% endwith %}

{% endif %}

第二段为JS代码, 如下所示。因为我们采用的是POST提交方式,Django默认POST是需要附上csrftoken的。本例中我们在Ajax请求发送前使用了jQuery的cookie库把crsftoken加入到请求头里(见beforeSend属性)。如果你不想要发送csrftoken,你还可以在视图里使用@crsf_exempt装饰器。

{% block js %}

{% endblock %}

上面这段代码是这么工作的。

我们通过JS获取文章id和action两个参数,通过Ajax POST请求发送到处理Ajax请求的url(blog/article/like)。

如果返回的status==ok,我们变换动作(action), 并对总点赞数进行更新(加1或减1)。

如果返回的status不等于ok,要么用户未登陆,要么用户进行了非法操作。此时我们通过设置window.location.href属性强行对用户进行跳转到登录页面。

注意:尽管我们已经在视图里使用了login_required装饰器, 我们还需要在JS代码里写明跳转链接,这样才能实现未登录用户点击点赞按钮后自动跳转到登录页面。这是因为如果你使用AJAX和服务器进行交互沟通,你从服务器得到的只是JSON格式数据,而并不是真的访问那个页面。

实战效果

最后实战效果如下。写了这么多,只是给前端页面增加了个不起眼的点赞按钮。看似简单的东西不一定简单。

小结

我们利用AJAX技术实现了仿微信评论的点赞功能,主要讲解了以下知识点:

利用add和remove方法实现了多对多关系的添加和删除

Ajax和Django视图的交互原理

利用Ajax获取crsftoken,发送POST请求

利用Ajax实现跳转

如果喜欢本文,欢迎点赞或关注我们的微信公众号。

2018.10.18

大江狗

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181018G0K24Z00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券