设为首页 收藏本站
查看: 459|回复: 1

七、BBS根评论与子评论如何实现

[复制链接]
累计签到:528 天
连续签到:1 天
发表于 2022-11-12 14:44:49 | 显示全部楼层 |阅读模式
前期思路# 文章评论
我们先写跟评论
再写子评论
前端HTML代码{#评论楼开始#}
    <div>
    <ul class="list-group">
        {% for comment in comment_list %} # 文章的视图函数把comment_list对象传过来,comment_list = models.Comment.objects.filter(article=article_obj)
            <li class="list-group-item">
            <span>#{{ forloop.counter }}</span>
            <span>{{ comment.comment_time|date:'Y-m-d h:i:s' }}</span>
            <span>{{ comment.user.username }}</span> <!--.user跨到userinfo表,.username在继承的abstract里面找到username属性-->
            <span><a class="pull-right reply" username="{{ comment.user.username }}" comment_id="{{ comment.pk }}">回复</a></span>
            <div>
{# 判断当前评论是否是子评论 如果是则需要渲染对应的评论人名#}
                {% if comment.parent_id %}
                    
<p>@{{ comment.parent.user.username }}</p>  <!--子评论如何拿到根评论的名字,还是跨表通过parent就可以了-->
                {% endif %}
                {{
comment.content }}
            
</div>
            </li>
        {% endfor %}
   
</ul>
    </div>
{#评论楼结束#}{#文章样式评论开始#}
    {% if request.user.is_authenticated %} # 判断登录的用户才能评论
        
<div>
            <p><span class="glyphicon glyphicon-comment"></span>发表评论</p>
            <div>
                <textarea name="comment" id="id_comment" cols="60" rows="10"></textarea>
            </div>
            <button class="btn btn-primary" id="id_submit">提交评论</button>
            <span style="color: red" id="errors"></span>
        </div>
    {% else %} # 非登录用户跳转登录、注册页面
            
<li><a href="{% url 'login' %}">登录</a></li>
             <li><a href="{% url 'reg' %}">注册</a></li>
    {% endif %}{#文章样式评论结束#}
前端JS代码// 设置一个全局标志位置,为了让子评论的值可以传递到后端
    let parentId =null
// 用户点击评论朝后端发送ajax请求
    $('#id_submit').click(function (){
        
// 获取用户评论的内容
        let conTent=$('#id_comment').val()
        
// 判断是否是子评论,如果是则需要手动将@username名字去除掉
        if(parentId){
            
// 先找到\n对应的索引 然后利用切片 但是切片是顾头不顾尾 搜易索引索引+1
            let indexNum = conTent.indexOf('\n') +1 ;
            conTent=conTent.slice(indexNum) // indexNum所有的数据切除,只保留后面的部分
        }
        
$.ajax({
            
url: '/comment/',
            type: 'post',
            data:{
               
'article_id': '{{ article_obj.pk }}',
                // 如果后端没有值 那么就是null 后端存储null没有任何关系
                'parent_id':parentId,
                'content':conTent,
                'csrfmiddlewaretoken':'{{csrf_token}}'
            },
            success:function (args){
               
if(args.code==1000){
                    
$('#errors').text(args.msg)
                    
//利用ajax success回调结果俩实现两个功能
                    // 1、将评论区内容清空
                    // 2
、搭建一个临时的评论楼到评论去底部

                    // 1、将评论区里面的内容清空
                    $('#id_comment').val('')

                    // 2、临时渲染评论楼
                    let userName = '{{ request.user.username }}'
                    let temp = `
                    <li class="list-group-item">
                        <span>${userName}</span>
                        <span><a href="#" class="pull-right">回复</a></span>
                        <div>
                            ${conTent}
                        </div>
                    </li> `
                    // 将生成好的标签加到到评论楼里面去,append尾部追加一个临时的评论楼
                    $('.list-group').append(temp);
                    // 要清空全局的parentId字段
                    parentId =null

                }
            }
        })
    })

// 用户进行子评论
    $('.reply').click(function (){
        
// 用户名字和评论id
        let commentUserName =$(this).attr('username')
        // 修改全局的parent_id ,如果全部变量为可变类型的时候不用加global申明和python一样的用法
        parentId =$(this).attr('comment_id')
        // 跳转到textarea中,把@+作者名字+换行添加进去
        $('#id_comment').val('@'+commentUserName+'\n').focus()
    })

后端代码:from django.db import transaction # 利用事务同时提交两个models语句
def comment(request):
    # 自己也可以给自己的文章经行评论
    if request.is_ajax():
        back_dic = {
'code': 1000, 'msg': ''}
        
if request.method == 'POST':
            # 后端也可以再次校验是否登录
            if request.user.is_authenticated():
                article_id = request.POST.get(
'article_id')
                content = request.POST.get(
'content')
                parentId = request.POST.get(
'parent_id') # 如果是根评论这个值是可以为空的
                # 要操作两张表一个是文章表com_num 另外一个COMMENT
                with transaction.atomic():
                    models.Article.objects.filter(
pk=article_id).update(comment_num=F('comment_num')+1)
                    models.Comment.objects.create(
user=request.user,content=content,article_id=article_id,parent_id=parentId)
                back_dic[
'msg']='评论成功'
            else:
                back_dic[
'code']=1001
                back_dic['msg']='用户未登录'
            return JsonResponse(back_dic) # 只接收post请求,get请求就不返回了


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-1002695-1-1.html 上篇帖子: 六、BBS只点赞点踩如何是实现 下篇帖子: 八、后台搭建、添加文章、防止XSS攻击、上传图片、修改头
累计签到:528 天
连续签到:1 天
 楼主| 发表于 2022-11-12 14:55:21 | 显示全部楼层
// 用户进行子评论分解
子评论思路
    点击回复按钮发生了几件事
        1、评论框自动聚焦
        2、将回复按钮所在的那一行评论人的姓名进行拼接
        3、自动换行

    $('.reply').click(function (){
        //
用户名字和评论id
        let commentUserName =$(this).attr('username')
        parentId =$(this).attr('comment_id')
        //
跳转到textarea中,把@+作者名字+换行添加进去
        $('#id_comment').val('@'+commentUserName+'\n').focus()
    })=================================================
后端代码if request.user.is_authenticated():
    article_id = request.POST.get('article_id')
    content = request.POST.get('content')
    parentId = request.POST.get('parent_id')
    #
直接操作评论表存储数据
    with transaction.atomic():
        models.Article.objects.filter(pk=article_id).update(comment_num=F('comment_num')+1)
        models.Comment.objects.create(user=request.user,content=content,article_id=article_id,parent_id=parentId)=============================================================
【思路整理】子评论的所有所及基本全部集中在前端JSHTML代码中点击回复按钮发生了几件事

[1首先在回复的标签中,创建一个点击事件,我们设置自己设置一个类为 class=‘reply’方便查找,为什么在这里不直接设置id呢,因为这个实在for循环里面的,可能会有多个相同id存在,就不合符id唯一的特性了,用类比较符合规范,见明字意
[2我们要进行子评论的时候要拿到跟评论的id和评论人的姓名,我们可以把标签当作临时容器自己定义属性,再去通过attr方法拿到值

eg<span><a class="pull-right reply" username="{{ comment.user.username }}" comment_id="{{ comment.pk }}">回复</a></span>
        let commentUserName =$(this).attr('username')

        parentId =$(this).attr('comment_id');》》这个后面会有引入到另外一个函数内的概念,暂时先放着
[3在把获取到底值进行拼接然后在取获取焦点,那么第一阶段算是实现了
// 跳转到textarea中,把@+作者名字+换行添加进去
        $('#id_comment').val('@'+commentUserName+'\n').focus()
    })


4、当我们在子评论在textarea点击提交的时候,我们还是走Ajax请求,但是子评论和跟评论的区别是子评论会多一个parent_id
那么这个时候我们想发送子评论的时候就要parent_id带上,但是parent_id在另外的函数里面怎么办呢?这个就可以用到刚才我们
在标签中获取的parentId,首先设置一个全部标志位 let parentId =null ,只有跟评论时候那么这个parentId是为空的,没有关系
我们后端代码允许parent字段为空,但如果进行了子评论了,就会有原先的null就会带上跟评论的id做标识,提交数据的时候,数据
也会显示parent_id有跟评论的id了,这样就可以完成子评论的初步功能了


5、但是我们还会发现,在保存数据内容的时候,还会自动把我们当时拼接的@和用户名一起保存到数据里面,这个显示是不合理的,那么
我们接下来就是要将这个去除,那么怎么去除呢?首先我们得先判断一下我们这个是不是子评论,是的话我们在去除,我们可以回想一下当时
我们拼接的时候是以"\n",作为结尾的,所以我们只要拿到"\n"所在的索引,我们再利用切片,但是切片是顾头不顾尾的,所以我们在拿索引的
时候还要在加1,然后用切片方法
        // 判断是否是子评论,如果是则需要手动将@username名字去除掉
        if(parentId){
            //
先找到\n对应的索引 然后利用切片 但是切片是顾头不顾尾 索引索引+1
            let indexNum = conTent.indexOf('\n') +1 ;
            conTent=conTent.slice(indexNum) //
indexNum所有的数据切除,只保留后面的部分
        }


6、那么经过以上的方法还是会发现渲染到时候会有问题,因为正常渲染的时候都是会有@人名加内容的,如何解决呢
那么我们只有在HTML部分的代码用if判断,如果是子评论我们则渲染对象的人名和下面的内容,如果是跟评论
我们直接走{{comment.content}}就行,因为我们把数据库保存信息时,把人名+@手动去除了,所以我们在手动加回来
{#判断当前评论是否是子评论 如果是则需要渲染对应的评论人名#}
                {% if comment.parent_id %}
                    <p>@{{ comment.parent.user.username }}</p>
                {% endif %}
                {{ comment.content }}
            </div>
            </li>
        {% endfor %}
    </ul>
    </div>



7、还会有一个问题就是,当你进行子评论完了后,在此进行跟评论时候,你会发现,一致都是子评论了,没有楼层的显示了,这个是什么原因呢?
原来是我们一开始定义的parentId是有值的,一致会带有跟评论的id,所以当我们在发送ajax后我们还要把parentId的值为空,这样下一次在进行
评论的时候,才会变成根评论
// 将生成好的标签加到到评论楼里面去
  $('.list-group').append(temp);
  //
要清空全局的parentId字段
parentId =null

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表