评论详解

首先呢,评论有分为根评论和子评论,所谓的根评论呢,就是对当前文章进行评论,子评论呢,就是对别人的评论进行再次评论,怎么区别是根评论还是子评论呢,pid来判断

表结构设计:

class  Comment(models.Model):
    '''评论'''
    nid=models.AutoField(primary_key=True)
    articel=models.ForeignKey(to='Personal_Article',to_field='nid',verbose_name='评论文章',on_delete=models.CASCADE)
    comment_detail=models.TextField(max_length=200,verbose_name='评论内容')
    user=models.ForeignKey(to='UserInfo',to_field='nid',verbose_name='评论用户',on_delete=models.CASCADE)
    comment_time=models.DateTimeField(auto_now_add=True,verbose_name='评论时间')
    parrent_comment=models.ForeignKey(to='self',to_field='nid',verbose_name='父评论',null=True,blank=True,on_delete=models.CASCADE)
    ##有无父评论
    class  Meta:
        verbose_name_plural='评论表'
    def  __str__(self):
        return   self.comment_detail

根节点评论:

pid为空的时候

前端代码实现:(全部评论)

<div class="comment_list_div" style="padding-top: 50px">
        <p>评论列表</p>
        <ul class="comment_list">
            {% for  obj  in  all_comment %}
                <li class="list-group-item">
                    <div>
                        <a href="">#{{ forloop.counter }}楼</a>&nbsp;&nbsp;&nbsp;
                        <span style="color: gray">{{ obj.comment_time|date:'Y-m-d H:i' }}</span> &nbsp;&nbsp;
                        <a href="">{{ obj.user.username }}</a>
                        <a apply_username="{{ obj.user.username }}" replay_pid="{{ obj.pk }}"
                           class="pull-right  apply">回复</a>
                    </div>


                    <!--假如obj是由父评论的时候,就显示出父评论出来-->
                    {% if  obj.parrent_comment %}
                        <div class="son_comment well">
                            <p>@{{ obj.parrent_comment.user.username }} 评论:{{ obj.parrent_comment.comment_detail }}</p>
                        </div>
                    {% endif %}



                    <!--显示出子评论或者是根评论(正常的评论)-->
                    <div class="comment_detail">
                        <p>{{ obj.comment_detail }}</p>
                    </div>
                </li>
            {% endfor %}

        </ul>
    </div>

评论框:

    <div id="comment_form_container">
        <script type="text/javascript" src="//mention.cnblogs.com/bundles/mention.js?id=20160615"></script>
        <div id="commentform_title">发表评论</div>
        <span id="tip_comment" style="color:Red"></span>
        <p>
            昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50"
                      value="{{ request.session.username }}">
        </p>
        <div class="commentbox_main">
            <div class="commentbox_title">
                <div class="commentbox_title_left">评论内容:</div>
            </div>
            <div class="clear"></div>
            <textarea id="tbCommentBody" class="comment_textarea"></textarea>
        </div>
        <p id="commentbox_opt">
            <input id="btn_comment_submit" type="button" class="comment_btn" value="提交评论">
            <span id="span_comment_canceledit" style="display:none"><a href="javascript:void(0);"
                                                                       onclick="return CancelCommentEdit()">不改了</a></span>
            <a href="javascript:void(0);" onclick="return logout();">退出</a>
            <a id="commentbox_opt_sub" href="javascript:void(0);" title="订阅后有新评论时会邮件通知您"
               onclick="commentManager.Subscribe()">订阅评论</a>
        </p>
        <div id="tip_comment2" style="color:Red"></div>
        <p>
            [Ctrl+Enter快捷键提交]
        </p>
        <div style="display:none">
            <span id="comment_edit_id"></span><span id="span_parentcomment_id"></span>
            <span id="span_parent_id"></span>
            <span id="span_comment_replyto"></span>
            <span id="span_comment_posted"></span>
        </div>
    </div>
    {% csrf_token %}

js代码如下:(评论)

    <script>//评论的时候,根评论
        var pid = "";//默认一提交评论就是根评论

        //回复的时候,下面是是子评论,pid值也发生变化,子评论
        //点点击这个回复按钮的时候,就可以跳到文本框进行回复
        $('.list-group-item  .apply').click(function () {
            $("#tbCommentBody").focus();//跳到这个框里面,光标,让光标集中到哪里
            var apply_username = "@" + $(this).attr("apply_username") + $(this).attr("replay_pid") + "\n";//得到当前的要回复的用户名,换行,光标下一行
            $('.comment_textarea').val(apply_username);

            //得到是谁进行的评论
            pid = $(this).attr("replay_pid");//拿到当前要回复的pk,相同的人评论pk可能不同
            alert("pid改变", pid)//var是局部变量
        });


        $(".comment_btn").click(function () {
            //提交评论内容
            var article_id = '{{ obj.article.pk }}';//当前文章的pk
            var content = $('.comment_textarea').val();
            $.ajax({
                url: '/blog/article/comment/',
                type: 'post',
                data: {
                    'article_id': article_id,
                    'pid': pid,
                    'content': content,
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
                },
                success: function (data) {
                    alert('suc');
                    var name = data.msg.username;
                    var content = data.msg.content;
                    var comment_time = data.msg.create_time;


                    //dom操作
                    var add_ele = "<li  class=\"list-group-item\">\n" +
                        "                <div>\n" +
                        "                    <span style=\"color: gray\">" + comment_time + "</span>   &nbsp;&nbsp;\n" +
                        "                    <a  href=\"\">" + name + "</a>\n" +
                        "                </div>\n" +
                        "                <div  class=\"comment_detail\">\n" +
                        "                    <p>" + content + "</p>\n" +
                        "                </div>\n" +
                        "                </li>";
                    $('.comment_list').append(add_ele);//dom操作

                    //当提交评论之后,当前的文本框清除掉评论内容
                    $('.comment_textarea').val('');

                    pid = '';//提交完之后pid清空,正常又是跟评论,否则pid有值,还是子评论
                }
            });
        });


    </script>

如果是pid为空的时候,说明是根节点评论

就发送ajax请求,传3个参数过去,一个是当前文章的id,还有评论的内容,还有pid,还有要带一个csrf过去,否则post请求是会被403禁止的csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()

当前文章的pk值obj,article.pk,

评论的内容var content = $('.comment_textarea').val();

pid=""

如果是子节点评论的话

pid就是当前要对它进行评论的用户(已经评论过),就是自己点击回复该评论的用户,评论内容和文章的id是和上面的根节点评论的完全相同

//回复的时候,下面是是子评论,pid值也发生变化,子评论
        //点点击这个回复按钮的时候,就可以跳到文本框进行回复
        $('.list-group-item  .apply').click(function () {
            $("#tbCommentBody").focus();//跳到这个框里面,光标,让光标集中到哪里
            var apply_username = "@" + $(this).attr("apply_username") + $(this).attr("replay_pid") + "\n";//得到当前的要回复的用户名,换行,光标下一行
            $('.comment_textarea').val(apply_username);

            //得到是谁进行的评论
            pid = $(this).attr("replay_pid");//拿到当前要回复的pk,相同的人评论pk可能不同
            alert("pid改变", pid)//var是局部变量
        });

dom操作:

dom操作就是临时的将当前评论的数据加到评论列表的下面,再次刷新的时候就会正常显示出来了

如果是对当前文章的评论就是根评论,ajax会接收到参数data,里面有username(当前登录的用户,也就是评论的了),content(当前用户评论的内容) ,create_time(当前评论的时间),此时parrent_comment_id是为空的,接收到之后呢,进行处理,下面进行判断如果parrent_comment存在值的话,当前父评论下面就有值了

评论列表  
<!--假如obj是由父评论的时候,就显示出父评论出来--> {% if obj.parrent_comment %} <div class="son_comment well"> <p>@{{ obj.parrent_comment.user.username }} 评论:{{ obj.parrent_comment.comment_detail }}</p> </div> {% endif %}

下面的dom操作,不管是不是根节点评论还是子节点评论都是放在评论列表的最下面显示出来,一样的处理方式

  success: function (data) {
                    alert('suc');
                    var name = data.msg.username;
                    var content = data.msg.content;
                    var comment_time = data.msg.create_time;


                    //dom操作
                    var add_ele = "<li  class=\"list-group-item\">\n" +
                        "                <div>\n" +
                        "                    <span style=\"color: gray\">" + comment_time + "</span>   &nbsp;&nbsp;\n" +
                        "                    <a  href=\"\">" + name + "</a>\n" +
                        "                </div>\n" +
                        "                <div  class=\"comment_detail\">\n" +
                        "                    <p>" + content + "</p>\n" +
                        "                </div>\n" +
                        "                </li>";
                    $('.comment_list').append(add_ele);//dom操作

                    //当提交评论之后,当前的文本框清除掉评论内容
                    $('.comment_textarea').val('');

                    pid = '';//提交完之后pid清空,正常又是根评论,否则pid有值,还是子评论
                }
            });
        });

后端实现代码如下:

文章详情表(article_detail)

def Article_Detail(request, article_name):
    # 得到所有的评论,当前文章的所有评论
    article_pk = models.Personal_Article.objects.filter(title=article_name).get().pk
    ##去评论表里面去评论
    all_comment = models.Comment.objects.filter(articel_id=article_pk).all()

    ##判断存不存在当前这个文章
    all_tilte = models.Personal_Article.objects.values('title')
    for title in all_tilte:
        if article_name == title['title']:
            detail_obj = models.Article_detail.objects.filter(article__title=article_name).all()
            return render(request, 'article_detail.html', locals())
    return HttpResponse('not find 这个文章')

comment部分如下:

# 评论
def Comment(request):
    print('进入评论页面')
    res = {'status': 0, 'msg': {}}
    print(request.POST)
    username = request.session['username']
    article_id = request.POST.get('article_id')
    content = request.POST.get('content')
    user_pk = models.UserInfo.objects.filter(username=username).get().pk
    pid = request.POST.get('pid')
    ##创建数据
    print('pid', pid, type(pid))
    if pid:
        print('子评论', content, type(content))
        # content = content.split('\n', 1)[1:][0]  ##去掉前面的@yunxin\n评论内容
        print(content)
        res['msg']['pid'] = pid  ##dom也可以是子评论下面呀
        obj = models.Comment.objects.create(articel_id=article_id, comment_detail=content, user_id=user_pk,
                                            parrent_comment_id=pid)
    else:
        print('根评论')
        ##根评论,pid=0
        obj = models.Comment.objects.create(articel_id=article_id, comment_detail=content, user_id=user_pk)
    # dom操作需要返回的值
    res['msg'] = {
        'username': username,
        'content': content,
        'create_time': obj.comment_time.time()
    }

    return JsonResponse(res)

后端代码接收到之后呢,就对ajax请求过来的数据进行校验,判断当前的pid是否存在

如果是存在的话,说明是根节点评论

obj = models.Comment.objects.create(articel_id=article_id, comment_detail=content, user_id=user_pk),后面不用加上parrent_coment_id

如果是子节点评论的话
pid就存在值,此时还需要对这个评论内容进行切割@yunxin\n 内容,去掉前面的内容,
content = content.split('\n', 1)[1:][0]
创建评论的数据到数据库里面
obj = models.Comment.objects.create(articel_id=article_id, comment_detail=content, user_id=user_pk,parrent_comment_id=pid)
返回前台数据做dom处理:
返回的数据有username(当前评论的用户),content(当前评论的内容),create_time(评论的时间),dom操作的时候可以在下面创建一条评论的数据出来,在此刷新的时候就会正常显示


前端完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/components/my_style.css">
    <link rel="stylesheet" href="/static/components/bootstrap.min.css">
    <script src="/static/components/jquery-3.1.1.js"></script>
</head>
<body>
{% for  obj in detail_obj %}
    <div class="header_body">
        <h1 id="article_title">{{ obj.article.title }}</h1>
        <span>上传作者:{{ obj.article.user.username }}</span>
        <span>发布时间:{{ obj.article.create_time }}</span>
    </div>
    {{ obj.content|safe }}



    <div id="div_digg  " class="pull-right" style="width: 120px">
        <div class="diggit  action">
            <span class="diggnum" id="digg_count">{{ obj.article.up_count }}</span>
        </div>
        <div class="buryit  action" style="left: 200px">
            <span class="burynum" id="bury_count">{{ obj.article.down_count }}</span>
        </div>
        <div class="clear  "></div>
        <div class="diggword" id="digg_tips" style="color: red">
        </div>
    </div>





    <div class="comment_list_div" style="padding-top: 50px">
        <p>评论列表</p>
        <ul class="comment_list">
            {% for  obj  in  all_comment %}
                <li class="list-group-item">
                    <div>
                        <a href="">#{{ forloop.counter }}楼</a>&nbsp;&nbsp;&nbsp;
                        <span style="color: gray">{{ obj.comment_time|date:'Y-m-d H:i' }}</span> &nbsp;&nbsp;
                        <a href="">{{ obj.user.username }}</a>
                        <a apply_username="{{ obj.user.username }}" replay_pid="{{ obj.pk }}"
                           class="pull-right  apply">回复</a>
                    </div>


                    <!--假如obj是由父评论的时候,就显示出父评论出来-->
                    {% if  obj.parrent_comment %}
                        <div class="son_comment well">
                            <p>@{{ obj.parrent_comment.user.username }} 评论:{{ obj.parrent_comment.comment_detail }}</p>
                        </div>
                    {% endif %}



                    <!--显示出子评论或者是根评论(正常的评论)-->
                    <div class="comment_detail">
                        <p>{{ obj.comment_detail }}</p>
                    </div>
                </li>
            {% endfor %}

        </ul>
    </div>





    <div id="comment_form_container">
        <script type="text/javascript" src="//mention.cnblogs.com/bundles/mention.js?id=20160615"></script>
        <div id="commentform_title">发表评论</div>
        <span id="tip_comment" style="color:Red"></span>
        <p>
            昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50"
                      value="{{ request.session.username }}">
        </p>
        <div class="commentbox_main">
            <div class="commentbox_title">
                <div class="commentbox_title_left">评论内容:</div>
            </div>
            <div class="clear"></div>
            <textarea id="tbCommentBody" class="comment_textarea"></textarea>
        </div>
        <p id="commentbox_opt">
            <input id="btn_comment_submit" type="button" class="comment_btn" value="提交评论">
            <span id="span_comment_canceledit" style="display:none"><a href="javascript:void(0);"
                                                                       onclick="return CancelCommentEdit()">不改了</a></span>
            <a href="javascript:void(0);" onclick="return logout();">退出</a>
            <a id="commentbox_opt_sub" href="javascript:void(0);" title="订阅后有新评论时会邮件通知您"
               onclick="commentManager.Subscribe()">订阅评论</a>
        </p>
        <div id="tip_comment2" style="color:Red"></div>
        <p>
            [Ctrl+Enter快捷键提交]
        </p>
        <div style="display:none">
            <span id="comment_edit_id"></span><span id="span_parentcomment_id"></span>
            <span id="span_parent_id"></span>
            <span id="span_comment_replyto"></span>
            <span id="span_comment_posted"></span>
        </div>
    </div>
    {% csrf_token %}
    <script>
        //点赞的或踩的时候
        $('div  .action').click(function () {
            var is_up = $(this).hasClass('diggit');//这边的is_up是布尔值,但是在传过来的时候不是['True']的形式
            //判断当前点击的是否有这个属性赞或者是踩
            {#var  article_title=$("#article_title").text()#}
            var article_id = '{{ obj.article.pk }}';//取到当前点赞或踩的文章值


            $.ajax({
                url: '/blog/article/up_down/',
                type: "post",
                data: {
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
                    is_up: is_up,
                    'article_id': article_id,//需要3个参数,一个是赞或者踩,一个是文章id,一个是赞或者踩的用户
                },
                success: function (data) {
                    if (data.status) {
                        //点赞踩成功
                        if (is_up) {
                            var val = $("#digg_count").text();//字符串
                            val = parseInt(val) + 1;
                            $("#digg_count").text(val);//点赞成功
                        } else {
                            var val = $("#bury_count").text();//字符串
                            val = parseInt(val) + 1;
                            $("#bury_count").text(val);//点赞成功
                        }
                    } else {

                        if (data.msg) {
                            $(".diggword").html('您已经赞过');
                        } else {
                            $(".diggword").html('您已经踩过');
                        }
                        setTimeout(function () {
                            $(".diggword").html('');
                        }, 5000)//设置时间消失
                    }
                }
            })
        });


        //评论的时候,根评论
        var pid = "";//默认一提交评论就是根评论

        //回复的时候,下面是是子评论,pid值也发生变化,子评论
        //点点击这个回复按钮的时候,就可以跳到文本框进行回复
        $('.list-group-item  .apply').click(function () {
            $("#tbCommentBody").focus();//跳到这个框里面,光标,让光标集中到哪里
            var apply_username = "@" + $(this).attr("apply_username") + $(this).attr("replay_pid") + "\n";//得到当前的要回复的用户名,换行,光标下一行
            $('.comment_textarea').val(apply_username);

            //得到是谁进行的评论
            pid = $(this).attr("replay_pid");//拿到当前要回复的pk,相同的人评论pk可能不同
            alert("pid改变", pid)//var是局部变量
        });


        $(".comment_btn").click(function () {
            //提交评论内容
            var article_id = '{{ obj.article.pk }}';//当前文章的pk
            var content = $('.comment_textarea').val();
            $.ajax({
                url: '/blog/article/comment/',
                type: 'post',
                data: {
                    'article_id': article_id,
                    'pid': pid,
                    'content': content,
                    csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
                },
                success: function (data) {
                    alert('suc');
                    var name = data.msg.username;
                    var content = data.msg.content;
                    var comment_time = data.msg.create_time;


                    //dom操作
                    var add_ele = "<li  class=\"list-group-item\">\n" +
                        "                <div>\n" +
                        "                    <span style=\"color: gray\">" + comment_time + "</span>   &nbsp;&nbsp;\n" +
                        "                    <a  href=\"\">" + name + "</a>\n" +
                        "                </div>\n" +
                        "                <div  class=\"comment_detail\">\n" +
                        "                    <p>" + content + "</p>\n" +
                        "                </div>\n" +
                        "                </li>";
                    $('.comment_list').append(add_ele);//dom操作

                    //当提交评论之后,当前的文本框清除掉评论内容
                    $('.comment_textarea').val('');

                    pid = '';//提交完之后pid清空,正常又是跟评论,否则pid有值,还是子评论
                }
            });
        });


    </script>



{% endfor %}

</body>
</html>

猜你喜欢

转载自www.cnblogs.com/yunxintryyoubest/p/10724991.html