首页 > 其他分享 >实现文章评论功能

实现文章评论功能

时间:2023-10-26 21:23:37浏览次数:32  
标签:comment username 功能 parent request 评论 文章 id

设计思路

先写根评论
	先把整体的评论功能跑通
    1.书写前端获取用户评论的标签 可能点赞点踩有浮动带来的影响
        clearfix
    2.点击评论按钮发送ajax请求

    3.后端针对评论单独开设url处理
    	后端逻辑其实非常的简单非常的少

    4.针对根评论涉及到前端的两种渲染方式
    	1.DOM操作临时渲染评论楼
    		需要用到模版字符串
            // 临时渲染评论楼
            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>
            `
            // 将生成好的标签添加到ul标签内
            $('.list-group').append(temp);
    	2.页面刷新永久(render)渲染
            后端直接获取当前文章对应的所有评论 传递给html页面即可
            前端利用for循环参考博客园评论楼样式渲染评论
      
        3.评论框里面的内容需要清空
	
再写子评论
从回复按钮入手
	点击回复按钮发生了几件事
		1.评论框自动聚焦 .focus()
		2.将回复按钮所在的那一行评论人的姓名@出来并且换行
			@username\n
			
	 思考:
      	1.根评论和子评论点的是同一个按钮
      	2.根评论和子评论的区别
        	其实之前的ajax代码只需要添加一个父评论id即可
        	
        点击回复按钮之后 我们应该获取到根评论对应的用户名和主键值
        针对主键值 多个函数都需要用 所以用全局变量的形式存储
        
        针对子评论内容 需要切割出不是用户写的	@username\n
        
    后端parent字段本来就可以为空,所以传不传值都可以直接存储数据

    前端针对子评论再渲染评论楼的时候需要额外的判断
        {% if comment.parent_id %}
           <p>@{{ comment.parent.user.username }}</p>
        {% endif %}
           {{ comment.content }}
    
    前端parentId字段每次提交之后需要手动清空

后端代码

from django.db import transaction
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')
                parent_id = 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, article_id=article_id, content=content, parent_id=parent_id)
                back_dic['msg'] = '评论成功!'
            else:
                back_dic['code'] = 1001
                back_dic['msg'] = '用户未登录'
            return JsonResponse(back_dic)

前端页面代码

<body>   
{#    评论楼渲染开始#}
{# #1楼 2019-01-03 15:12 yuzhiboyou#}
<div>
    <ul class="list-group">
      {% for comment in comment_list %}
          <li class="list-group-item">
          <span>#{{ forloop.counter }}楼</span>
          <span>{{ comment.comment_time|date:'Y-m-d h:i' }}</span>
          <span>{{ comment.user.username }}</span>
          <span><a class="pull-right reply" username="{{ comment.user.username }}" comment_id="{{ comment.pk }}">回复</a></span>
          <div>
                {#判断当前评论是否为子评论 如果是需要渲染对应的评论人姓名@xxx#}
              {% if comment.parent_id %}
                  <p>@{{ comment.parent.user.username }}</p>
              {% 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 %}
{#    文章评论结束#}
</body>

js部分 其中包括了回复功能

<script>
// 设置一个全局parentID字段
let parentId = null;
// 用户点击评论按钮朝后端发送ajax请求
$('#id_submit').off().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 }}',
            'content': conTent,
            // 如果parentID没有值 那么就是null 后端存储null没关系因为数据库中允许为null
            'parent_id': parentId,
            'csrfmiddlewaretoken': '{{ csrf_token }}'
        },
        success:function (args){
            if(args.code == 1000){
                $('#errors').text(args.msg)

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

                // 临时渲染评论楼
                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>
                `
                // 将生成好的标签添加到ul标签内
                $('.list-group').append(temp);

                // 清空全局的parentId字段 要不然你不刷新页面继续评论的话一直是子评论
                parentId = null;
            }
        }
    })
})


// 给回复按钮绑定事件
$('.reply').click(function () {
    // 需要评论对应的 评论人姓名 还需要评论的主键值
    // 获取用户名
    let commentUserName = $(this).attr('username');
    // 获取主键值 直接修改全局的变量名
    parentId = $(this).attr('comment_id');
    // 将拼接信息塞给评论区
    $('#id_comment').val('@' + commentUserName + '\n').focus()
})
</script>

标签:comment,username,功能,parent,request,评论,文章,id
From: https://www.cnblogs.com/piggthird/p/17790419.html

相关文章

  • 手撸移动便签功能
    实现原理  1.位置计算(相对视口)     1.获取鼠标点击坐标     2.获取元素的坐标    3.移动时鼠标位置   2.window.onmouseup=function(){console.log('不再监听移动')//moveBar.onmousedown=nullwindow.on......
  • 超好用的IDEA插件推荐!自带API调试功能
    大家好,今天给大家推荐一款超好用的IDEA插件,由API调试工具Apipost推出!支持在插件中获取token、支持代码完成后在插件中进行API调试,同时也保留了1.0版本部分功能如上传选择目录功能等。V1版本还会继续保留开源,方便各位进行自创魔改。V2版本目前已上架至IDEA插件商店,大家可以自行下......
  • 超好用的IDEA插件推荐!自带API调试功能
    大家好,今天给大家推荐一款超好用的IDEA插件,由API调试工具Apipost推出!支持在插件中获取token、支持代码完成后在插件中进行API调试,同时也保留了1.0版本部分功能如上传选择目录功能等。V1版本还会继续保留开源,方便各位进行自创魔改。V2版本目前已上架至IDEA插件商店,大家可以自行......
  • Sentinel产品功能介绍
    1.Sentinel产品功能介绍Sentinel是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。Sentinel具有以下特性:丰富的应用场景:Sentinel承接了阿里巴巴近10年的双十一......
  • vue中实现上传 ,下载功能
    上传功能(包括上传图片,上传文件)使用element组件库https://element.eleme.cn/#/zh-CN/component/upload<el-upload class="avatar-uploader":disabled="isUpload"action="":show-file-list="false":before-upload="beforeUplo......
  • 信息搜索:全文搜索功能是网站运营的助力点
    产品界面通常采用高信息密度和高交互密度的设计,这是为了满足用户对多功能和复杂业务的需求。为了使用户能够快速获取所需信息并完成任务,产品中广泛使用各种搜索功能,无论大小都会有搜索功能,以提高用户的信息获取和消费效率。而全文搜索是搜索功能中体验更好的一种模式。全文搜索功能......
  • 导医导诊功能主要特点
        随着医疗技术的不断发展和进步,现代医疗体系已经越来越注重医疗质量和效率的提高。其中,智慧门诊作为一种新型的医疗模式,通过引入智能化技术,为患者提供更加便捷、高效和个性化的就医体验。本文将从智慧门诊的概念、特点、应用和未来发展方向等方面进行分析和探讨。一、智......
  • 安科瑞ACX系列电瓶车智能充电桩的功能介绍
    功能:●电瓶车智能桩具备语音播报功能。●电瓶车智能充电桩可支持刷卡、扫码两种付费充电模式,具体设备支付功能以订货要求为准。扫码充电功能需与云平台联网后使用。●电瓶车智能充电充电桩可以按时间或电量充电。●电瓶车智能充电桩最大可外接10路插座,每个插座只支持一台电瓶车......
  • python博客园下载所有文章保存为Mardown
    简易代码importrequestsfrombs4importBeautifulSoupimportreimporthtml2textimportossession=requests.session()cookies={#换成自己的cookies}headers={'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/av......
  • Bluetooth SIG规划中的新功能简介
    原文https://mp.weixin.qq.com/s/VkgWb5odpoh0OemlkZW5Bw以下是当前正在进行的几个关键规范项目的概述[详细参考1]。更高频段(远)HFB (Higher Frequency Bands)目前正在进行一个规范开发项目是 Higher Frequency Bands,定义低功耗蓝牙@使用其他未经许可的频谱(包括6GHz频段......