zoukankan      html  css  js  c++  java
  • 多级评论的实现思路

    一、表结构

    class UserInfo(models.Model):
        """用户表"""
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
        email = models.CharField(max_length=32,null=True)
    
        def __str__(self):
            return self.username
    
    class NewsCategory(models.Model):
        """新闻类型表"""
        caption = models.CharField(max_length=16)
        def __str__(self):
            return self.caption
    
    class NewsInfo(models.Model):
        """新闻表"""
        title = models.CharField(max_length=32,verbose_name="标题")
        summary = models.CharField(max_length=255,verbose_name="简介",null=True)
        url = models.CharField(max_length=255,verbose_name="URL",null=True)
        avatar = models.CharField(max_length=255,verbose_name="文章配图",null=True)
        ctime = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')
        category = models.ForeignKey(to="NewsCategory",verbose_name="类别")
        author = models.ForeignKey(to="UserInfo",verbose_name="作者")
    
        # 点赞和评论时,记着更新like_count,comment_count。自增1/自减1: F 实现
        like_count = models.IntegerField(default=0)
        comment_count = models.IntegerField(default=0)
    
        def __str__(self):
            return self.title
    
    class Comment(models.Model):
        """评论记录表"""
        content = models.CharField(max_length=255,verbose_name="评论内容")
        user = models.ForeignKey(to="UserInfo",verbose_name="评论者")
        news = models.ForeignKey(to="NewsInfo",verbose_name="评论的文章")
        ctime = models.DateTimeField(auto_now_add=True,verbose_name='评论时间')
    
        """多级评论需要 自关联"""
        parent = models.ForeignKey("Comment",related_name="pid",null=True,blank=True)
    
        def __str__(self):
            return self.content
    
    class Like(models.Model):
        """点赞记录表"""
        user = models.ForeignKey(to="UserInfo",verbose_name="点赞者")
        news = models.ForeignKey(to="NewsInfo",verbose_name="点赞的文章")
        ctime = models.DateTimeField(auto_now_add=True,verbose_name="点赞时间")
    
        # 建立联合唯一索引,限定每个用户给每篇文章只能点赞一次
        class Meta:
            unique_together = [
                ('user','news'),
            ]
    

      

    二、相关数据结构

    1. 从数据库读出的数据:
    
    [
        {'id': 1, 'user': 'alex', 'content': '灌我鸟事', 'parent_id': None},
        {'id': 2, 'user': 'alex', 'content': '管我鸟事', 'parent_id': None},
        {'id': 3, 'user': 'eric', 'content': '你个文盲', 'parent_id': 1},
        {'id': 4, 'user': 'egon', 'content': '好羡慕你们这些没脸的人呀', 'parent_id': 2},
        {'id': 5, 'user': 'alex', 'content': '你是流氓', 'parent_id': 3},
        {'id': 6, 'user': 'alvin', 'content': '双击666', 'parent_id': 5},
        {'id': 7, 'user': 'alex', 'content': '智障啊 ->_->', 'parent_id': 6},
        {'id': 8, 'user': 'alex', 'content': '你冷酷无情', 'parent_id': 4},
        {'id': 9, 'user': 'eric', 'content': '你无理取闹', 'parent_id': 4},
        {'id': 10, 'user': 'standby', 'content': '赶紧买个瓜围观', 'parent_id': 8},
        {'id': 11, 'user': 'cindy', 'content': '前排卖水了啊', 'parent_id': 10},
        {'id': 12, 'user': 'egon', 'content': '一群土老帽...', 'parent_id': None},
    ]
    
    
    
    2. 需要构造成如下结构:
    
    [
        {
            'parent_id': None,
            'id': 1,
            'content': '灌我鸟事',
            'children': [
                {
                    'parent_id': 1,
                    'id': 3,
                    'content': '你个文盲',
                    'children': [
                        {
                            'parent_id': 3,
                            'id': 5,
                            'content': '你是流氓',
                            'children': [
                                {
                                    'parent_id': 5,
                                    'id': 6,
                                    'content': '双击666',
                                    'children': [
                                        {
                                            'parent_id': 6,
                                            'id': 7,
                                            'content': '智障啊->_->',
                                            'children': [
                                                
                                            ],
                                            'user': 'alex'
                                        }
                                    ],
                                    'user': 'alvin'
                                }
                            ],
                            'user': 'alex'
                        }
                    ],
                    'user': 'eric'
                }
            ],
            'user': 'alex'
        },
        {
            'parent_id': None,
            'id': 2,
            'content': '管我鸟事',
            'children': [
                {
                    'parent_id': 2,
                    'id': 4,
                    'content': '好羡慕你们这些没脸的人呀',
                    'children': [
                        {
                            'parent_id': 4,
                            'id': 8,
                            'content': '你冷酷无情',
                            'children': [
                                {
                                    'parent_id': 8,
                                    'id': 10,
                                    'content': '赶紧买个瓜围观',
                                    'children': [
                                        {
                                            'parent_id': 10,
                                            'id': 11,
                                            'content': '前排卖水了啊',
                                            'children': [
                                                
                                            ],
                                            'user': 'cindy'
                                        }
                                    ],
                                    'user': 'standby'
                                }
                            ],
                            'user': 'alex'
                        },
                        {
                            'parent_id': 4,
                            'id': 9,
                            'content': '你无理取闹',
                            'children': [
                                
                            ],
                            'user': 'eric'
                        }
                    ],
                    'user': 'egon'
                }
            ],
            'user': 'alex'
        },
        {
            'parent_id': None,
            'id': 12,
            'content': '一群土老帽...',
            'children': [
                
            ],
            'user': 'egon'
        }
    ]
    
    
    
    3. 最后拼接HTML,返回给前端进行展示
    

      

     三、代码实现

    def format_comments2(li):
        dic = {}
        for item in li:
            item["children"] = []
            dic[item["id"]] = item
    
        result = []
        for item in li:
            pid = item['parent_id']
            if pid:
                dic[item["parent_id"]]["children"].append(item)
            else:
                result.append(item)
        return result
    
    def build_comments_tree2(result):
        tpl = """
        <div class="item">
            <div class="title">{0}:{1} <a href="">回复</a></div>
            <div class="body">{2}</div>
        </div>
        """
        html = ""
        """递归遍历所有子评论"""
        for item in result:
            if not item["children"]:
                html += tpl.format(item["user"],item["content"],"")
            else:
                html += tpl.format(item["user"],item["content"],get_comment_tree(item["children"]))
        return html
    
    
    
    
    def format_comments(comment_list):
        """
        把相关评论的列表集合转换成如下的格式 方便在build_comments_tree里构造HTML  
        也可以在后端把构造好的列表传递给前端 用js来构造HTML
        [
            {
                'id':comment_id,
                'content':'具体评论内容',
                'user':'评论人',
                'parent_id':id/None,
                'children':[
                    {},
                    {},
                    ...
                ]
            },
            ...
        }
        """
        formated_list = []
        tmp_list = []
        for comment in comment_list:
            cid = comment['id']
            pid = comment.get('parent_id')
            dic = {'id': cid, 'user': comment['user'], 'content': comment['content'], 'parent_id': pid, 'children': []}
            tmp_list.append(dic)
            if not pid:
                formated_list.append(dic)
            else:
                for item in tmp_list:
                    if item['id'] == pid:
                        item['children'].append(dic)
                        break
        return formated_list
    
    def build_comments_tree(formated_list):
        tpl = """
            <div class="item">
                <div class="comment">{0}:{1}<a href="" class="reply">回复</a></div>
                <div class="body">{2}</div>
            </div>
            """
        html = ""
        """深度优先搜索:递归遍历所有子评论"""
        for item in formated_list:
            children = item.get('children')
            if children:
                html += tpl.format(item['user'], item['content'], build_comments_tree(children))
            else:
                html += tpl.format(item['user'],item['content'],"")
        return html
    
    
    
    def comment_tree(request):
        comment_list = [
            {'id': 1, 'user': 'alex', 'content': '灌我鸟事', 'parent_id': None},
            {'id': 2, 'user': 'alex', 'content': '管我鸟事', 'parent_id': None},
            {'id': 3, 'user': 'eric', 'content': '你个文盲', 'parent_id': 1},
            {'id': 4, 'user': 'egon', 'content': '好羡慕你们这些没脸的人呀', 'parent_id': 2},
            {'id': 5, 'user': 'alex', 'content': '你是流氓', 'parent_id': 3},
            {'id': 6, 'user': 'alvin', 'content': '双击666', 'parent_id': 5},
            {'id': 7, 'user': 'alex', 'content': '智障啊 ->_->', 'parent_id': 6},
            {'id': 8, 'user': 'alex', 'content': '你冷酷无情', 'parent_id': 4},
            {'id': 9, 'user': 'eric', 'content': '你无理取闹', 'parent_id': 4},
            {'id': 10, 'user': 'standby', 'content': '赶紧买个瓜围观', 'parent_id': 8},
            {'id': 11, 'user': 'cindy', 'content': '前排卖水了啊', 'parent_id': 10},
            {'id': 12, 'user': 'egon', 'content': '一群土老帽...', 'parent_id': None},
        ]
        # result = format_comments2(li)
        # html = build_comments_tree2(result)
        result = format_comments(comment_list)
        html = build_comments_tree(result)
        return render(request,'demo.html',{'html':html})
    

      

    {% load staticfiles %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .body{
                margin-left: 30px;
            }
            .be_hidden {
                display: none;
            }
        </style>
    </head>
    <body>
    
    
    <h1>所有评论</h1>
    {{ html|safe }}
    
    <script src="{% static "js/bootstrap.min.js" %}"></script>
    <script src="{% static "js/jquery-3.2.1.min.js" %}"></script>
    <script>
        $(function () {
            $('.comment').click(function () {
                if ($(this).next().hasClass('be_hidden')){
                    $(this).next().removeClass('be_hidden')
                }else{
                    $(this).next().addClass('be_hidden')
                }
            })
        })
    </script>
    
    
    </body>
    </html>
    

    四、前端展示

    作者:Standby一生热爱名山大川、草原沙漠,还有妹子
    出处:http://www.cnblogs.com/standby/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    【Office Web Apps】在 SharePoint 中使用 Office Web Apps
    css轮廓
    css定位
    css盒子模型 css3盒子相关样式
    css常用操作
    css3选择器
    强制换行和禁止换行
    text-transform 字母的大小写
    css hack
    JavaScript基本语法
  • 原文地址:https://www.cnblogs.com/standby/p/7823013.html
Copyright © 2011-2022 走看看