一、原理
#多级评论原理简单原理,弄完之后发现基础白学了 msg_list = [ {'id':1,'content':'xxx','parent_id':None}, {'id':2,'content':'xxx','parent_id':None}, {'id':3,'content':'xxx','parent_id':None}, {'id':4,'content':'xxx','parent_id':1}, {'id':5,'content':'xxx','parent_id':4}, {'id':6,'content':'xxx','parent_id':2}, {'id':7,'content':'xxx','parent_id':5}, {'id':8,'content':'xxx','parent_id':3}, ] #python里面的apend之类的东西都是引用的原来数据的内从地址,对原数据进行操作的话 #我们引用的数据也会发生一样的变化(字典列表之类的) #骗子的方法 # for i in msg_list: # i['child']=[] # for i in range(len(msg_list)-1,-1,-1): # if msg_list[i]['parent_id']: # msg_list[msg_list[i]['parent_id'] - 1]['child'].append(msg_list[i]) # new_msg_list = [i for i in msg_list if i['parent_id'] is None] # print(new_msg_list) #老师讲的方法 # v=[row.setdefault('child',[]) for row in msg_list] #这和地下的第一个for循环的作用是一样的,给每一个元素加一个'child':[] # print(msg_list) #如果我们想加快索引(快点找到数据的话)就建一个字典的数据结构 msg_list_dict={} #加快索引,节省时间 for item in msg_list: item['child']=[] msg_list_dict[item['id']]=item #字典中key为item['id'],value为item #把字典数据结构填上数据,能够加快索引,而且我们数据还是占得原来的内从空间 #我们只是引用了数据的内容空间,所以不存在新的数据结构浪费空间一说 result=[] for item in msg_list: pid=item['parent_id'] if pid: #如果parent_id不为空,说明它是子级,要把自己加入对应的父级 msg_list_dict[pid]['child'].append(item) else: #如果为空,说明他是父级,要把它单独领出来用 result.append(item) #result就是我们最终要的结果,因为这里面全是引用,所有数据的内存地址都没有变 #只不过被多个数据结构引用了而已 print(result)
二、精简版
views代码
def comments(request,nid): res={'status':True,'data':None,'msg':None} try: comment_list = models.Comment.objects.filter(article_id=nid).values() com_list = list(comment_list) # 所有的评论,列表套字典 com_list_dict = {} # 建立一个方便查找的数据结构字典 for item in com_list: # 循环评论列表,给每一条评论加一个child:[]就是让他装对他回复的内容 item['create_time'] = str(item['create_time']) item['child'] = [] com_list_dict[item['nid']] = item result = [] for item in com_list: rid = item['reply_id'] if rid: # 如果reply_id不为空的话,那么就是说明他是子评论,我们要把他加入对应的评论后面 com_list_dict[rid]['child'].append(item) else: result.append(item) print(result) # comment_str = comment_tree(result) # 这是在服务器上递归完之后,然后在传到前端,但是这样会增加服务器压力 #所以这种方式我们直接就不用了 res['data']=result except Exception as e: res['status']=False res['mag']=str(e) return HttpResponse(json.dumps(res))
HTML代码
<style> .comment{ margin-left:20px; } </style> <body> <div id="commentArea"> </div> </body> <script src="/static/jquery-3.2.1.js"></script> <script> //自定义JS中字符串格式化方法 String.prototype.Format=function (arg) { //console.log(this,arg); //this,当前调用方法的字符串,arg为Format方法传入的参数 //return '666'; //return,格式化之后获取的新内容,return啥就替换为啥 var temp = this.replace(/{(w+)}/g,function (k,kk) { // k相当于{(w+)},kk相当于(w+)要替换的东西,arg一般是一个字典 return arg[kk]; }); return temp; }; $(function () { //发送Ajax请求,获取所有评论的信息 //列表 //JS生成结构 var token=$.cookie('csrftoken'); $.ajax({ url:"/comments-{{ article_obj.nid }}.html", type:"GET", dataType:"JSON", success:function (arg) { if (arg.status){ var comment=commentTree(arg.data); $('#commentArea').append(comment); }else{ alert(arg.msg); } } }) }); //多级评论递归函数,js函数里面也有return,自己写js字符串格式化 //pyhton中字符串的方法都是str下的,js中是String.prototype下找的 function commentTree(commentList) { var comment_str="<div class='comment'>"; $.each(commentList,function (k,row) { var temp="<div class='content'>{content}</div>".Format({content:row.content}); comment_str += temp; if (row.child.length>0){ comment_str += commentTree(row.child); } }); comment_str += '</div>'; return comment_str } </script>