评论系统在一个博客中至关重要,是一个最直接的交流媒介。如何实现一个嵌套的评论呢?这里主要讨论嵌套的展示,评论数据提交部分比较简单,就略过。
首先,来看一张表,如下所示,其中我们最关注2个字段,一个是comment_id
,另外一个是comment_parent
,也就是说靠这两个字段定位父子关系,数据为0可以认为上面没有父节点了,否,则反。
mysql> SELECT comment_id,comment_post_id,comment_author,comment_author_email,comment_date,comment_parent FROM wp_comments WHERE comment_post_ID = 1 AND ( comment_approved = '1' OR ( comment_author = '回复2.2' AND comment_author_email = 'root@root.com' AND comment_approved = '0' ) ) ORDER BY comment_date_gmt; +------------+-----------------+----------------+----------------------+---------------------+----------------+ | comment_id | comment_post_id | comment_author | comment_author_email | comment_date | comment_parent | +------------+-----------------+----------------+----------------------+---------------------+----------------+ | 1 | 1 | Mr WordPress | | 2014-09-24 19:29:15 | 0 | | 13 | 1 | 评论1 | test@test.com | 2014-10-28 08:58:21 | 0 | | 14 | 1 | 评论2 | test@test.com | 2014-10-28 08:58:36 | 0 | | 15 | 1 | 评论3 | test@test.com | 2014-10-28 08:58:55 | 0 | | 16 | 1 | 回复1 | root@root.com | 2014-10-28 09:00:16 | 13 | | 17 | 1 | 回复1.1 | root@root.com | 2014-10-28 09:00:31 | 16 | | 18 | 1 | 回复2 | root@root.com | 2014-10-28 09:00:46 | 14 | | 19 | 1 | 回复2.1 | root@root.com | 2014-10-28 09:01:08 | 18 | | 20 | 1 | 回复2.1.1 | root@root.com | 2014-10-28 09:02:05 | 19 | | 21 | 1 | 回复2.2 | root@root.com | 2014-10-28 09:02:23 | 18 | | 22 | 1 | 评论4 | root@root.com | 2014-10-28 09:40:00 | 0 | | 23 | 1 | 回复2.1.1.1 | root@root.com | 2014-10-28 09:41:29 | 20 | | 24 | 1 | 回复2.1.1.2 | test@test.com | 2014-10-29 05:14:01 | 20 | | 25 | 1 | 回复4 | test@test.com | 2014-10-29 07:58:07 | 22 | | 26 | 1 | abc啊嘎嘎 | test@test.com | 2014-10-29 10:31:15 | 0 | | 27 | 1 | 2.2.1 | root@root.com | 2014-10-30 12:25:18 | 21 | +------------+-----------------+----------------+----------------------+---------------------+----------------+ 16 rows in set (0.00 sec)
然后,再次看这张表,发现其实这张表是一棵树的存放,不信,我把节点(comment_id跟comment_parent)摘下来,看看,比如,13的子节点有16,16的子节点是17,依次处理后,结果如下:
1 13 16 17 14 18 19 20 23 24 21 27 15 22 25 26
所以,我们要写一段程序把上面的数据库出来的数据变成多叉树,这时候想到了json,json就很方便存放这些数据结构,然后出来一段代码如下:
#turn into json data dic={} stack=[] for c in comments: dic[c.comment_id]={'self':c,'level':0} if c.comment_parent!=0: if 'children' in dic[c.comment_parent]: dic[c.comment_parent]['children'].insert(0,dic[c.comment_id]) pass else: dic[c.comment_parent]['children']=[dic[c.comment_id]]#{c.comment_id:c} dic[c.comment_id]['level']= dic[c.comment_parent]['level']+1 else: stack.insert(0,dic[c.comment_id])
不过看不懂?没关系,慢慢看,继续看下面结果,你就懂的,这段程序输入的comments是:
[<Comments: 1>, <Comments: 13>, <Comments: 14>, <Comments: 15>, <Comments: 16>, <Comments: 17>, <Comments: 18>, <Comments: 19>, <Comments: 20>, <Comments: 21>, <Comments: 22>, <Comments: 23>, <Comments: 24>, <Comments: 25>, <Comments: 26>, <Comments: 27>]
输出的是stack变量,它的结果为:
[{'level': 0, 'self': <Comments: 26>}, {'children': [{'level': 1, 'self': <Comments: 25>}], 'level': 0, 'self': <Comments: 22>}, {'level': 0, 'self': <Comments: 15>}, {'children': [{'children': [{'children': [{'level': 3, 'self': <Comments: 27>}], 'level': 2, 'self': <Comments: 21>}, {'children': [{'children': [{'level': 4, 'self': <Comments: 24>}, {'level': 4, 'self': <Comments: 23>}], 'level': 3, 'self': <Comments: 20>}], 'level': 2, 'self': <Comments: 19>}], 'level': 1, 'self': <Comments: 18>}], 'level': 0, 'self': <Comments: 14>}, {'children': [{'children': [{'level': 2, 'self': <Comments: 17>}], 'level': 1, 'self': <Comments: 16>}], 'level': 0, 'self': <Comments: 13>}, {'level': 0, 'self': <Comments: 1>}]
仔细观察每一层输出的[HTML_REMOVED]最后一个数字,有没有发现树是倒过来了,这个没关系,就是要倒过来,后面遍历的时候使用栈操作,children是指下面的子节点,self是自身的comment,本level是层次,代码不细说了,自己看,接下来要用到上面的stack变量的结果作为下面程序的输入:
result=[] while len(stack)>0: top=stack.pop() #result.append(top) if 'children' not in top: result.append((top['level'],top['self']) ) else: c=top['children'] l=top['level'] s=top['self'] result.append( (l,s)) stack=stack+c pass
然后结果是这样,前面的数字就是level,就是缩进的层次,后面就是一个comment对象:
[(0, <Comments: 1>), (0, <Comments: 13>), (1, <Comments: 16>), (2, <Comments: 17>), (0, <Comments: 14>), (1, <Comments: 18>), (2, <Comments: 19>), (3, <Comments: 20>), (4, <Comments: 23>), (4, <Comments: 24>), (2, <Comments: 21>), (3, <Comments: 27>), (0, <Comments: 15>), (0, <Comments: 22>), (1, <Comments: 25>), (0, <Comments: 26>)]
最后,完成遍历,我们得到了层次信息,这样,在用css显示去控制层次就很方便了。本博客评论就是这么写的,有兴趣可以看看源码。
总结,利用类似json这样的数据结构,可以很好的把多叉树放入其中,然后利用栈遍历方法,把位置跟节点层次安顺序输出,方便展示。