• 7.博客系统| 评论功能(文章评论,评论的评论)


    根评论:对文章的评论;

    子评论:对评论的评论;

    区别:是否有父评论。

    评论的流程:

      1构建样式

      2提交根评论

      3显示根评论

        --------render显示

        --------Ajax显示

      4提交子评论

      5显示子评论

        --------render显示

        --------Ajax显示

      6评论树的显示

        楼层结构:

        111

        222

        333

        树形结构:(有父子关系,楼层的深度、层级)

            111

            222

              444

                555

            333

    1.评论样式

    article_detail.html

      <div class="clearfix">  //评论和点赞在一行,这是由于点赞和反对做了一个浮动,而评论又在正常文档中,导致它的浮动没有清除;清除浮动在bootstrap里边加个clearfix
        <div id=“div_digg...”>
      </div>
    {# 评论样式#} <div class="comments"> <p>发表评论</p> <p>昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50" value="{{ request.user.username }}"></p> <p>评论内容:</p> <textarea name="" id="comment_content" cols="60" rows="10"></textarea> //没有必要放到form表单中,因为要Ajax提交;textarea为内联标签,给下面button加了个p标签。 <p> <button class="btn btn-default commment_btn">提交评论</button> // </p> </div>

    article_detail.css

    input.author{
        background-image: url("/static/font/icon_form.gif"); //引入图标
        background-repeat: no-repeat;
        border: 1px solid #ccc;
        padding: 4px 4px 4px 30px;
         300px;
        font-size: 13px;
        background-position: 3px -3px;
    }

    2.提交(保存)根评论

    客户端浏览器发 点赞或者评论按钮给服务端,触发一个事件(给它绑定一个click事件)发送请求,用户一点击就给服务器发请求了,有专门的视图函数接收这个请求,提交评论信息交给comment视图函数,视图函数构建一个评论对象保存到数据库里边,然后再把响应交给回调函数(ajax发完请求给它个回调) ,通过响应结果来判断如果对这个dom操作

    views.py

    #评论
    def comment(request):
        print(request.POST)
        article_id = request.POST.get("article_id") #评论文章;user不用传,create_time不用传(评论的时间就是入库的时间),评论表的字段。
        pid = request.POST.get("pid") 
        content = request.POST.get("content") #评论内容
        user_id = request.user.pk #当前登录人的id
        comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,parent_comment_id=pid) //pid是为空的,传给父评论
    
        return HttpResponse("comment")

    article_detail.html

    //评论请求
            $(".commment_btn").click(function () {
                var pid = ""
                var content = $("#comment_content").val(); //找到这个标签,val就是取里边的内容
                $.ajax({
                    url:"/comment/",
                    type:"post",
                    data:{
                        "csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val(),
                        "article_id":"{{ article_obj.pk }}",
                        "content":content,
                        "pid":pid //父评论的id,默认为空。根评论没有
                    },
                    success: function (data) { //success回调函数
                        console.log(data)
                        //清空评论框 
                        $("#comment_content").val("");
    
                    }
                })
            })

     

    3.render显示根评论(还有一种是Ajax)

    views.py

    def article_detail(request, username, article_id):
        '''
        文章详情页
        :param request:
        :param username:
        :param article_id:
        :return:
        '''
        user = models.UserInfo.objects.filter(username=username).first() #个人站点对象
        blog = user.blog
        article_obj = models.Article.objects.filter(pk=article_id).first() #拿到文章对象,要传到模板里边去
        # context = get_classification_data(username)
        comment_list = models.Comment.objects.filter(article_id=article_id) #拿出用户访问那篇文章的id 
        return render(request, "article_detail.html", locals())

     article_detail.html

    <p>评论列表</p>
            <ul class="list-group comment_list">
                {% for comment in comment_list %}  //for循环这个comment_list
                <li class="list-group-item"> //每次循环生成一个 li标签
                    <div>
                        <a href="">#{{ forloop.counter }}楼</a> &nbsp;&nbsp;
                        <span>{{ comment.create_time | date:"Y-m-d H:i" }}</span>
                        <a href=""><span>{{ comment.user.username }}</span></a>
                        <a href="" class="pull-right">回复</a>
                    </div>
                    <div class="comment_con">
                        <p>{{ comment.content }}</p>
                    </div>
                </li>
                {% endfor %}
                
            </ul>

    Ajax显示评论

    点提交按钮,发Ajax请求;

     Ajax请求在对应的视图函数生成一个comment对象,然后我们响应给它的是comment对象相关的三个键值字典,字典返回给这个回调函数,拿到object对象构建一个标签,把标签字符串样式放在了页面的某个url里边去了完成了dom操作。

    success: function (data) {
                        console.log(data);
                        var create_time = data.create_time;  //取出这三组变量,把这三个变量插入到下面反引号里边,关于js必须用+不断的去拼接,现在用ES6反引号的语句就很简洁了
                        var username = data.username;
                        var content = data.content;
    
                        var s =`  //反斜杠 ;构建一个标签字符串像上边那样放到这个样式里边 ;通过dom操作放到这个url中
                                <li class="list-group-item">
                                <div>
                                    <span>${create_time}/span>  //用反引号把字符串包起来,再用${}语法把它插入进来,js里边的只能用+拼,ES6很像python的语法
                                    <a href=""><span>${ username }</span></a>
                                </div>
                                <div class="comment_con">
                                    <p>${content}</p>
                                </div>
                                </li> `;
                        $("ul.comment_list").append(s);

    views.py

    #评论
    def comment(request):
        print(request.POST)
        article_id = request.POST.get("article_id")
        pid = request.POST.get("pid")
        content = request.POST.get("content")
        user_id = request.user.pk
        comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,parent_comment_id=pid)
        response = {}  #这个就是返回给回调函数的那个data。 
        response["create_time"] = comment_obj.create_time.strftime("%Y-%m-%d %X")
        response["username"] = request.user.username #当前评论人
        response["content"] = content
        return JsonResponse(response) #返回一个字典,JsonResponse会帮我们做序列化操作;
        #return HttpResponse("comment")

    先点提交按钮发ajax请求,在对应的视图函数中生成一个对象,响应给它的是comment相关信息-三个键值组成的字典,把字典返回给success回调函数,success拿到那个字典 拿到object对象,构建一个标签,把标签字符串放到页面的某个ul里边去了,完成一个dom操作。(在数据库里边生成一个comment记录,同时在页面上看到提交的这条评论信息了)

    4. 回复按钮事件

    一点击回复按钮,就@这条评论的评论人;  定光标、赋文本值。

    <div>
                        <a href="">#{{ forloop.counter }}楼</a> &nbsp;&nbsp;
                        <span>{{ comment.create_time | date:"Y-m-d H:i" }}</span> &nbsp;&nbsp;
                        <a href=""><span>{{ comment.user.username }}</span></a>
                        <a class="pull-right reply_btn" username= "{{ comment.user.username }}">回复</a>
    </div>
    //回复按钮事件
            $(".reply_btn").click(function () {
                $('#comment_content').focus();  //聚焦
                var val="@"+$(this).attr("username")+"
    "; //赋值,父评论的名字
                $('#comment_content').val(val)
            })

    5.提交子评论

    <div>
        <a href="">#{{ forloop.counter }}楼</a> &nbsp;&nbsp;
        <span>{{ comment.create_time | date:"Y-m-d H:i" }} </span> &nbsp;&nbsp;
        <a href=""><span>{{ comment.user.username }}</span></a>
        <a class="pull-right reply_btn" username= "{{ comment.user.username }}" comment_pk="{{ comment.pk }}">回复</a> //给每个回复的按钮多加一个自定义的属性
    </div>
    //评论请求
            var pid = "";
            $(".commment_btn").click(function () {
                var content = $("#comment_content").val();  //把评论内容取出来
    
                if(pid){                     //判断pid是否为空。
                    var index=content.indexOf("
    ")
                    content = content.slice(index+1)
                }
    //清空评论框
     pid = "",  //加上它可以清除小bug(你不刷新时,不点击回复按钮之间输入pid则为子评论)
     $("#comment_content").val("");
     //回复按钮事件
            $(".reply_btn").click(function () {
                $('#comment_content').focus();
                var val="@"+$(this).attr("username")+"
    ";
                $('#comment_content').val(val);
    
                pid = $(this).attr("comment_pk")
            })

     

    6.Ajax显示子评论

    应该重新构建标签字符串,从视图中拿到父评论的相关信息,加到s字符串里边

    7.评论树的显示

    权限展示成树形结构,用递归

    评论树的请求数据

    <div class="comments list-group">
            <p class="tree_btn">评论树</p>
            <div class="comment_tree">
    {#        <div class="comment_item" comment_id = "1">#}
    {#            <span>111</span>#}
    {#            <div class="comment_item" comment_id = "4">#}
    {#                <span>444</span>#}
    {#                <div class="comment_item" comment_id = "5">#}
    {#                    <span>555</span>#}
    {#            </div>#}
    {#            </div>#}
    {#        </div>#}
    {#        <div class="comment_item" comment_id = "2">#}
    {#            <span>222</span>#}
    {#        </div>#}
    {#        <div class="comment_item" comment_id = "3">#}
    {#            <span>333</span>#}
    {#        </div>#}
            </div>
        <script>
            $(".tree_btn").click(function () {
                $.ajax({
                    url:"/get_comment_tree/",
                    type:"get",
                    data:{                                    data是views里return传来的ret值
                        article_id : "{{ article_obj.pk }}"
                    },
                    success:function(data){
                        console.log(data);
                        $.each(data, function (index, comment_object) {
                            var pk = comment_object.pk;
                            var content = comment_object.content;
                            var parent_comment_id = comment_object.parent_comment_id;
                            var s = `<div class="comment_item" comment_id=` + pk + `><span>` + content + `</span></div>`
    
                            if(!parent_comment_id){
                                $(".comment_tree").append(s);
                            }else{
                                $("[comment_id = "+parent_comment_id+"]").append(s);
                            }
                        })
                    }
                })
            })
        </script>

    views.py

    def get_comment_tree(request):
        article_id = request.GET.get("article_id")
        ret = list(models.Comment.objects.filter(article_id=article_id).values("pk", "content", "parent_comment_id"))
    
    
        return JsonResponse(ret, safe=False)

    根评论的序号一定大于子评论的序号

    ret = list(models.Comment.objects.filter(article_id=article_id).order_by("pk").values("pk", "content", "parent_comment_id"))
        return JsonResponse(ret, safe=False)
    <script>
            $.ajax({
                    url:"/get_comment_tree/",
                    type:"get",
                    data:{
                        article_id : "{{ article_obj.pk }}"
                    },
                    success:function(comment_list){
                        console.log(comment_list);
                        $.each(comment_list, function (index, comment_object) {
                            var pk = comment_object.pk;
                            var content = comment_object.content;
                            var parent_comment_id = comment_object.parent_comment_id;
                            var s = `<div class="comment_item" comment_id=` + pk + `><span>` + content + `</span></div>`
    
                            if(!parent_comment_id){
                                $(".comment_tree").append(s);
                            }else{
                                $("[comment_id = "+parent_comment_id+"]").append(s);
                            }
                        })
                    }
                });
    {#        $(".tree_btn").click(function () {#}
    {#            $.ajax({#}  把ajax放在外边,就不用点击了才能看到评论数了。
    {#                url:"/get_comment_tree/",#}
    {#                type:"get",#}
    {#                data:{#}
    {#                    article_id : "{{ article_obj.pk }}"#}
    {#                },#}
    {#                success:function(comment_list){#}
    {#                    console.log(comment_list);#}
    {#                    $.each(comment_list, function (index, comment_object) {#}
    {#                        var pk = comment_object.pk;#}
    {#                        var content = comment_object.content;#}
    {#                        var parent_comment_id = comment_object.parent_comment_id;#}
    {#                        var s = `<div class="comment_item" comment_id=` + pk + `><span>` + content + `</span></div>`#}
    {##}
    {#                        if(!parent_comment_id){#}
    {#                            $(".comment_tree").append(s);#}
    {#                        }else{#}
    {#                            $("[comment_id = "+parent_comment_id+"]").append(s);#}
    {#                        }#}
    {#                    })#}
    {#                }#}
    {#            })#}
    {#        })#}
        </script>

    评论事务操作

    from django.db import transaction
    #
    事务操作 with transaction.atomic(): comment_obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content,parent_comment_id=pid) models.Article.objects.filter(pk=article_id).update(comment_count=F("comment_count")+1)

    评论的邮件发送

    EMAIL_HOST = 'smtp.exmail.qq.com' #如果是163改成 smtp.163.com

    EMAIL_POST = 465

    EMAIL_HOST_USER = ' '               #账号

    EMAIL_HOST_PASSWORD = ' '    #密码

    #DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

    EMAIL_USE_SSL = True

  • 相关阅读:
    tornado中form表单验证详解
    关于tornado中session的总结
    Linux常用命令
    css3动画属性详解 与超酷例子
    keepalive高可用的健康检查
    keepalive的nginx防火墙问题
    安装配置hadoop
    tmux的简单快捷键
    部署使用elk
    k8s搭建部署
  • 原文地址:https://www.cnblogs.com/shengyang17/p/9425072.html
Copyright © 2020-2023  润新知