2018.7.13-点赞踩和多级评论功能总结

点赞功能的实现

 首先在文章内容下写出两个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样式就行了。

原文地址:https://www.cnblogs.com/yu-jie/p/9308385.html