点赞功能的实现
首先在文章内容下写出两个div标签,并绑定点击事件,此事件函数需要传入的参数有本标签对象、文章id、判断赞还是踩的参数:
<div>
<span onclick="up_down_click(this, {{ select_article.nid }}, 1);">赞</span>
<i id="up_screen">{{ select_article.up_count }}</i>
</div>
<div>
<span onclick="up_down_click(this, {{ select_article.nid }}, 0);">踩</span>
<i id="down_screen">{{ select_article.down_count }}</i>
</div>
利用jq写好将相关参数传到后台的逻辑,注意csrf_token的获取:
function up_down_click(ths, article_id, val) {
$.ajax({
url: '/up_down_click/',
data: {'val': val, 'article_id': article_id, 'csrfmiddlewaretoken': '{{csrf_token}}', },
type: 'POST',
dataType: 'JSON',
success:function (arg) {
//接收服务器处理后的数据要做的事
}
})
}
配置好路由:
path('up_down_click/', views.up_down_click), # 点赞踩功能
然后就是写up_down_click()函数的问题了,写此函数的时候需要注意几点,1.想好传送到后台的数据结构。2.由于赞踩在数据库中分有两个表,所以要绑定事务操作。具体写法如下:
def up_down_click(request):
"""
赞踩处理
:param request:
:return:
"""
response = {'code': 1000, 'msg': None} # 发送至前台的处理信息。1001代表赞,1002代表踩,1000代表有错误
try:
user_id = request.session.get('user_id')
v = int(request.POST.get('val')) # 接收赞踩参数,1为赞 0为踩
article_id = request.POST.get('article_id')
obj = models.UpDown.objects.filter(user_id=user_id, article_id=article_id).first() # 查询是否已经点过赞或者踩过
if obj: # 如果赞踩过
response['msg'] = '已经赞踩过'
print('已经赞踩过')
else: # 如果没有赞踩过
with transaction.atomic(): # 事务操作,绑定两次数据库操作
if v: # 赞记录收录
models.UpDown.objects.create(user_id=user_id, article_id=article_id, up=True)
models.Article.objects.filter(nid=article_id).update(up_count=F('up_count') + 1)
response['code'] = 1001
else: # 踩记录收录
models.UpDown.objects.create(user_id=user_id, article_id=article_id, up=True)
models.Article.objects.filter(nid=article_id).update(down_count=F('down_count') + 1)
response['code'] = 1002
except Exception as e:
response['msg'] = str(e) # 错误信息存入msg字段
print(json.dumps(response))
return HttpResponse(json.dumps(response))
最后就是前台jq对数据的处理,利用.text()和Number()函数可以将对应标签内的个数自增,完整处理代码如下:
function up_down_click(ths, article_id, val) {
$.ajax({
url: '/up_down_click/',
data: {'val': val, 'article_id': article_id, 'csrfmiddlewaretoken': '{{csrf_token}}', },
type: 'POST',
dataType: 'JSON',
success:function (arg) {
var num_up = $("#up_screen");
var num_down = $("#down_screen");
if(arg.code == '1001'){
num_up.text(Number(num_up.text())+1);
}else if(arg.code == '1002'){
num_down.text(Number(num_down.text())+1);
}else{
//显示错误信息
}
}
})
}
多级评论功能的实现
首先是对数据库数据的处理,对于这个相应的算法我在这篇博客中已经详细分析过,这里贴上代码:
def get_talk_list(request):
"""
处理评论列表数据
:param request:
:return:
"""
article_id = request.POST.get('article_id')
# 获取评论
talk_list = models.Comment.objects.filter(article_id=article_id).values('nid', 'user__username', 'content',
'reply_id')
"""
处理评论数据
"""
msg_2_list = {}
for i in talk_list:
i['child'] = []
msg_2_list[i['nid']] = i
result = []
for item in talk_list:
if item['reply_id']:
msg_2_list[item['reply_id']]['child'].append(item)
else:
result.append(item)
# print(json.dumps(result))
return HttpResponse(json.dumps(result))
最重要的还是利用处理后的数据将对应多级评论显示在页面上,想了想算法,估计会用到递归,如果将这些逻辑写到服务器上势必会消耗大量服务器资源,所以利用js写在页面上是最好的选择,对于js不是太熟练的我只好硬着头皮上了:D。
再写算法之前,第一个要处理的事情就是怎么接受服务器处理好的数据,在页面框架加载完成后利用ajax接收数据我觉得是个不错的选择:
$(function () {
$.ajax({
url: '/talk_list/',
data: {'article_id': {{ select_article.nid }}, 'csrfmiddlewaretoken': '{{csrf_token}}', },
type: 'POST',
dataType: 'JSON',
success:function (args) {
console.log(args);
}
});
});
下面就是递归算法,利用字符串拼接的想法,将所有评论用对应div包裹,返回最后的结果,其中注意js对于JSON数据的处理方法:
function talk_screen(obj) {
let comment_str = "<div class='comment'>";
$.each(obj, function (n, value) {
let tpl = "<div class='content'>"+value.content+"</div>"; // 每一条评论数据用div包裹
//console.log(value.content);
comment_str += tpl;
console.log(comment_str);
if (value.child != ''){ // 递归边界
//console.log(value.child);
let child_str = talk_screen(value.child);
comment_str += child_str;
}
});
comment_str += "</div>"; // 封口
return comment_str;
}
最后利用.html()方法将数据放入对于div中显示出来:
$('#talk_list').html(talk_screen(args));
最后加上一些css样式就行了。