django实现多级评论
实现原理:
在页面加载完成后,jQuery调用initComments()函数,initComments()函数会向后端发起Ajax请求,后端收到请求后,会把所有评论的数据以JSON格式返回到前端,然后前端再把评论的数据在页面上进行展示,评论的层级关系通过父级id来进行识别。
首先来看一下评论的表结构:
1 2 3 4 5 6 7 8 9 10 11 12 | # 评论表 class Comment(models.Model): # 要评论哪篇文章,外键指向文章表 comment_which_article = models.ForeignKey(to = 'Article' , on_delete = models.CASCADE, verbose_name = '评论的文章' , related_name = 'comment' ) # 评论内容,任意内容 comment_content = models.TextField(verbose_name = '评论内容' ) # 父级评论,指向评论表自己 # 如果父级评论为空,则为一级评论,否则为子级评论,可以有多级 parent_comment = models.ForeignKey(to = "self" , on_delete = models.CASCADE, related_name = 'son_comment' , null = True , blank = True , verbose_name = "父级评论" ) def __str__( self ): return self .comment_content |
然后看一下HTML页面的内容:
首先准备一个显示评论的区域:
1 2 3 4 5 6 7 8 9 10 | <! - - 此处是将要展示评论内容的区域 - - > <! - - 先放一个div,作为评论的显示div块 - - > <div id = "comment_div" > <! - - ul部分才是真正要展示评论的区域 - - > <! - - 评论将以列表的样式进行显示,先在这里放一个<ul>标签,拿到评论数据后,直接在<ul>下面添加<li>即可 - - > <! - - 设置 id = "comment_list" ,供后面选择标签时使用 - - > <ul id = "comment_list" > <! - - 后面的评论以<li>的样式放在此处 - - > < / ul> < / div> |
当页面加载完成后,调用 initComments() 函数向后端发起请求:
1 2 3 4 5 | / / 页面加载完成后执行的操作 / / 页面加载完成后,向后端发起请求,请求评论的数据 $(function (){ initComments(); }); |
再看看后端的视图如何给前端返回JSON数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from django.http import JsonResponse # 收到Ajax请求后的处理函数:comment() def comment(request): # 首先,获取到前端传过来的文章ID【article_id】, 才知道是那一篇文章的评论 article_id = request.GET.get( 'article_id' ) ''' 找到这篇文章下的所有评论数据; 以前都是获取到一个querySet,也就是类似一个列表,里面放了每一个评论数据的object对象; 但是这里,使用了.values()方法,获取到的数据将是下面这样的: [ {'id': 1, 'comment_which_article_id': 1, 'comment_content': '31232', 'parent_comment_id': None}, {'id': 2,'comment_which_article_id': 1,'comment_content': '123123123213','parent_comment_id': None}, {'id': 3, 'comment_which_article_id': 1, 'comment_content': '49831743141', 'parent_comment_id': 1}, {'id': 4, 'comment_which_article_id': 1, 'comment_content': '917491739491', 'parent_comment_id': 3}, {'id': 5, 'comment_which_article_id': 1, 'comment_content': '12313213213', 'parent_comment_id': 2}, {'id': 6, 'comment_which_article_id': 1, 'comment_content': '21321321321', 'parent_comment_id': 4} ] 这样的数据看似是一个列表,但是实际上还是一个querySet对象,因此将它转换成列表list(); 所以最后得到的comments,就是一个列表,列表的样子就是上面的数据的样子。 ''' comments = list (Comment.objects. filter (comment_which_article = article_id).values()) # 使用JsonResponse,将comments以JSON的形式返回给前端 # 这里必须加上safe=False,如果不加的话, 就会报错【具体为什么,我还没搞懂】 return JsonResponse(comments, safe = False ) |
最后看看这个前端的函数initComments() , 它向后端请求数据,并把数据在页面进行展示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | // initComments函数 function initComments() { // 通过jQuery的$.ajax({}) 向后端发送Ajax异步请求 $.ajax({ // 请求的路径是comment // 将文章的id传到后端,才能通过id获取到评论的数据 url: '/comment/?article_id={{ articleDetail.pk }}', // 请求的方法为:GET方法 type: 'GET', // 接受的返回的数据格式为:JSON格式 dataType: 'JSON', // 回调函数,请求成功后执行的操作 // 参数data,用于接收后端返回的JSON数据 success: function(data){ console.log(data); /* * $.each,循环遍历data数据,每循环一次,拿到数据的索引index和数据的值item, * item就是每一条数据,即:{'id': 1, 'comment_which_article_id': 1, 'comment_content': '31232', 'parent_comment_id': None} * */ $.each(data, function(index, item){ /* * 这里的变量 li,就是将要添加到已经准备好的< ul >标签中的< li >标签,其实就是评论的内容 * * $("< li >"): * 创建一个< li >标签 * * .attr('id', "id_" + item.id): * 将这个< li >标签的id属性值设置为 "id_" + item.id,【其中item.id就是评论自己的id值】 * * .append($('< a href="#">').text(item.comment_content)): * 在这个< li >标签里面再创建一个< a >标签,< a >标签的内容就是要显示的评论内容 * 【.text(item.comment_content):就是设置< a >标签的内容为评论的内容content】 * * .append($('< ul >')): * 由于每一条评论下面可能还有子评论,所以又在每一个< li >标签里面创建一个空的< ul >标签,用于放它的子评论 * * */ var li = $("< li >").attr('id', "id_" + item.id).append($('< a href="#">').text(item.comment_content)).append($('< ul >')); // 判断一下,如果没有父级评论,那就是一级评论 // 直接展示就可以了 if (!item.parent_comment_id){ // $('#comment_list').append(li): 展示一级评论 // 找到前面已经准备好的,id=comment_list的< ul >标签 // .append(li):在< ul >标签里面添加上面的 li $('#comment_list').append(li); }else { // else: 如果有父级评论,那就是子级评论 // 那就在父级评论对应的< li >下面的< ul >中添加 li // $("#id_" + item.parent_comment_id):找到父级评论对应的< li > // $("#id_" + item.parent_comment_id).children('ul'):找到父级评论对应的< li >里面的< ul > // .append(li):在找到的这个< ul >里面添加 li $("#id_" + item.parent_comment_id).children('ul').append(li); } }) } }) } </ script > |
效果:
前端接收到的数据:
页面的显示效果:
附言:
这只是一个多级评论展示的简单示例而已,并不完善,实际上多级目录,关系层级都可以这样来实现。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义