一、原理
#多級評論原理簡單原理,弄完之后發現基礎白學了
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>
