吴先生不爱吃辣

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

实现django评论树使用了三种方式

第一支种方式通过递归实现

缺点:每次查找parent_id的时候都要在ret所有的元素里面找一遍,找不到再在元素的children中寻找,一直找到为止

comment_list = [
        {'id': 1, 'content': 'Python最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 2, 'content': 'Java最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 3, 'content': 'PHP最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 4, 'content': '你最牛逼', 'user': '大王', 'parent_id': 1},
        {'id': 5, 'content': '我最牛逼', 'user': '张三', 'parent_id': 1},
        {'id': 6, 'content': '你最牛逼', 'user': '李四', 'parent_id': 4},
        {'id': 7, 'content': '你们都是垃圾...', 'user': '王老五', 'parent_id': 2},
        {'id': 8, 'content': '给我点赞哦...', 'user': '赵老六', 'parent_id': 3},
        {'id': 9, 'content': '什么东西啊...', 'user': '小李', 'parent_id': 8},
        {'id': 10, 'content': '见到你女友,交定你朋友...', 'user': '张三', 'parent_id': None},
        {'id': 11, 'content': '大家好,我是大胖...', 'user': '李四', 'parent_id': 6},
]
#评论列表的生成
#第一种方式基本递归,缺点每次查找都需要在ret所有的元素都找一遍,找不到在从儿子里面找一遍
#在在不到在在孙子里面找一遍,知道找到为止。重复寻找。
class Node:
    comment_list = [
        {'id': 1, 'content': 'Python最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 2, 'content': 'Java最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 3, 'content': 'PHP最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 4, 'content': '你最牛逼', 'user': '大王', 'parent_id': 1},
        {'id': 5, 'content': '我最牛逼', 'user': '张三', 'parent_id': 1},
        {'id': 6, 'content': '你最牛逼', 'user': '李四', 'parent_id': 4},
        {'id': 7, 'content': '你们都是垃圾...', 'user': '王老五', 'parent_id': 2},
        {'id': 8, 'content': '给我点赞哦...', 'user': '赵老六', 'parent_id': 3},
        {'id': 9, 'content': '什么东西啊...', 'user': '小李', 'parent_id': 8},
        {'id': 10, 'content': '见到你女友,交定你朋友...', 'user': '张三', 'parent_id': None},
        {'id': 11, 'content': '大家好,我是大胖...', 'user': '李四', 'parent_id': 6},
    ]
    #递归
    def digui(ret,row):
        for rt in ret:
            if rt['id'] == row['parent_id']:
                row['children'] =[]
                rt['children'].append(row)
                return
                #ret= [
                #     {'id': 1, 'content': 'Python最牛逼', 'user': '小李', 'parent_id': None,'children';[
                #                             {'id': 4, 'content': '你最牛逼', 'user': '大王', 'parent_id': 1},
                #                             {'id': 5, 'content': '我最牛逼', 'user': '张三', 'parent_id': 1},
                #     ]},
                #     {'id': 2, 'content': 'Java最牛逼', 'user': '小李', 'parent_id': None,'children';[]},
                #     {'id': 3, 'content': 'PHP最牛逼', 'user': '小李', 'parent_id': None,'children';[]},
                # ]
            # {'id': 6, 'content': '你最牛逼', 'user': '李四', 'parent_id': 4},
            else:
                Node.digui(rt['children'],row)
    # @property
    def create_tree(self,comment_list):
        ret = []
        for row in comment_list:
            if not row['parent_id']: # None
                row['children'] = []
                ret.append(row)
                # [
                #     {'id': 1, 'content': 'Python最牛逼', 'user': '小李', 'parent_id': None,'children';[]},
                #     {'id': 2, 'content': 'Java最牛逼', 'user': '小李', 'parent_id': None,'children';[]},
                #     {'id': 3, 'content': 'PHP最牛逼', 'user': '小李', 'parent_id': None,'children';[]},
                # ]
            else:#是回复的某个评论
                #for i in ret:
                    # if row['parent_id'] == i['id']:
                    #     i['children'].append(row)  #二级评论实现
                    # else:
                    #     找三层
                    Node.digui(ret,row)

        return ret

#第一种执行
# print(Node().create_tree(comment_list))
第一种方式

第二种方式通过列表和字典的引用方式查找

缺点是查找的复杂度没有第一种多,但是每次找parent_id还是需要comment_list中全部找一遍,并且还有在comment_list中添加元素,在ret中引用第一层的元素会增加内存的消耗。

#第二种查找方式,字典列表的引用方式
comment_list = [
        {'id': 1, 'content': 'Python最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 2, 'content': 'Java最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 3, 'content': 'PHP最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 4, 'content': '你最牛逼', 'user': '大王', 'parent_id': 1},
        {'id': 5, 'content': '我最牛逼', 'user': '张三', 'parent_id': 1},
        {'id': 6, 'content': '你最牛逼', 'user': '李四', 'parent_id': 4},
        {'id': 7, 'content': '你们都是垃圾...', 'user': '王老五', 'parent_id': 2},
        {'id': 8, 'content': '给我点赞哦...', 'user': '赵老六', 'parent_id': 3},
        {'id': 9, 'content': '什么东西啊...', 'user': '小李', 'parent_id': 8},
        {'id': 10, 'content': '见到你女友,交定你朋友...', 'user': '张三', 'parent_id': None},
        {'id': 11, 'content': '大家好,我是大胖...', 'user': '李四', 'parent_id': 6},
]
ret = []
for row in comment_list:
    row.update({'children':[]})

for item in comment_list:
    current_row = item
    current_row_parent_id = current_row['parent_id']
    if not current_row_parent_id:
        ret.append(item)
    else:
        for r in comment_list:
            if r['id'] == current_row_parent_id:
                r['children'].append(item) #把有parent_id的数据加入到comment_list对应ID的chilren列表中
                                            #而不是加入到rent中,因为是引用型ret中指向的内存地址是一致的

#缺点,当有不为空的parent_id的元素时,需要找comment_list中找一遍和parent_id相等的ID值,效率比递归的comment_list自身
#和子元素都找一遍的效率高,还有在comment_list中添加元素,在ret中引用第一层的元素会增加内存的消耗。
# print(ret)
# print(comment_list)
第二种方式

第三中方式基于hash查找

基于字典的查找方式

#第三种基于哈希查找,字典存储时会调用Python内部散列函数,将键(Key)作为参数进行转换,得到一个唯一的一个地址,然后将值
#存入这个地址中,所字典的查找也是基于哈希的,所以查找很快速
comment_list = [
        {'id': 1, 'content': 'Python最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 2, 'content': 'Java最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 3, 'content': 'PHP最牛逼', 'user': '小李', 'parent_id': None},
        {'id': 4, 'content': '你最牛逼', 'user': '大王', 'parent_id': 1},
        {'id': 5, 'content': '我最牛逼', 'user': '张三', 'parent_id': 1},
        {'id': 6, 'content': '你最牛逼', 'user': '李四', 'parent_id': 4},
        {'id': 7, 'content': '你们都是垃圾...', 'user': '王老五', 'parent_id': 2},
        {'id': 8, 'content': '给我点赞哦...', 'user': '赵老六', 'parent_id': 3},
        {'id': 9, 'content': '什么东西啊...', 'user': '小李', 'parent_id': 8},
        {'id': 10, 'content': '见到你女友,交定你朋友...', 'user': '张三', 'parent_id': None},
        {'id': 11, 'content': '大家好,我是大胖...', 'user': '李四', 'parent_id': 6},
]
#创建字典
ret = []
comment_list_dict = {}
for row in comment_list:
    row.update({'children':[]})
    comment_list_dict[row['id']] = row
print(comment_list_dict)
for item in comment_list:
    parent_row = comment_list_dict.get(item['parent_id'])
    if not parent_row:
        ret.append(item)
    else:
       parent_row['children'].append(item)
print(ret)
第三种方式

 回归前端,使用simple_tag

返回的数据为一个处理好的字典,回归给前端的时候使用自定义模板标签,在Html中调用直接使用模板方法使用

#__author:  Administrator
#date:  2016/12/26
from django import template
from django.utils.safestring import mark_safe
register = template.Library()

def diGui(children_list):
    html = ""
    for cv in children_list:
        b = '<div class="comment-box"><span>'
        b += cv['content'] + "</span>"
        b += diGui(cv['children'])
        b += "</div>"
        html += b
    return html

@register.simple_tag
def create_tree(comment_list):
    html = '<div class="comment-list">'
    for v in comment_list:
        a = '<div class="comment-box"><span>'
        a += v['content'] + "</span>"
        a += diGui(v['children'])
        a += "</div>"
        html += a

    return mark_safe(html)

"""
 function diGui(children_list){
                var html = "";
                $.each(children_list,function (ck,cv) {
                       var b = '<div class="comment-box"><span>';
                       b+= cv.content + "</span>";
                       b += diGui(cv.children);
                       b += "</div>";
                       html += b;
                 });
                return html;
            }


            function create_tree(data,$this) {
                 var html = '<div class="comment-list">';
                 $.each(data,function (k,v) {
                    var a = '<div class="comment-box"><span>';
                     a+= v.content + "</span>";
                     // 创建自评论
                     a += diGui(v.children);
                     a+= "</div>";
                     html += a;
                 });

                 html += "</div>";
                $this.after(html);
        }
    """
simple_tag
{% load laogao %}
{% create_tree comment_tree %}
<style>
        .comment-box{
            margin-left: 20px;
        }
</style>
HTML

 

posted on 2020-05-13 00:35  吴先生不爱吃辣  阅读(188)  评论(0编辑  收藏  举报