django中的多级评论
需求分析
一般论坛中有评论和子评论,这样很容易就成了一个评论树,比如以下情况,先看数据结构:
#nid,评论内容,跟帖对象(None为根评论)
(1, '111', None),
(2, '222', None),
(3, '33', None),
(9, '999', 5),
(4, '444', 2),
(5, '555', 1),
(6, '666', 4),
(7, '777', 2),
(8, '888', 4),
可以使用递归来处理,先把数据通过有序字典,key为对象,value为有序字典,依次类推!
代码部分
views.py:
from django.shortcuts import render
import collections
# Create your views here.
def tree_search(d_dic, comment_obj):
# 在comment_dic中一个一个的寻找其回复的评论
# 检查当前评论的 reply_id 和 comment_dic中已有评论的nid是否相同,
# 如果相同,表示就是回复的此信息
# 如果不同,则需要去 comment_dic 的所有子元素中寻找,一直找,如果一系列中未找,则继续向下找
for k, v_dic in d_dic.items():
# 找回复的评论,将自己添加到其对应的字典中,例如: {评论一: {回复一:{},回复二:{}}}
if k[0] == comment_obj[2]:
d_dic[k][comment_obj] = collections.OrderedDict()
return
else:
# 在当前第一个跟元素中递归的去寻找父亲
tree_search(d_dic[k], comment_obj)
def build_tree(comment_list):
comment_dic = collections.OrderedDict()
for comment_obj in comment_list:
if comment_obj[2] is None:
# 如果是根评论,添加到comment_dic[评论对象] = {}
comment_dic[comment_obj] = collections.OrderedDict()
else:
# 如果是回复的评论,则需要在 comment_dic 中找到其回复的评论
tree_search(comment_dic, comment_obj)
return comment_dic
comment_list = [
(1, '111', None),
(2, '222', None),
(3, '33', None),
(9, '999', 5),
(4, '444', 2),
(5, '555', 1),
(6, '666', 4),
(7, '777', 2),
(8, '888', 4),
]
def comment(request):
comment_dict = build_tree(comment_list)
return render(request, 'comment.html', {'comment_dict': comment_dict})
model.py
from django.db import models
# Create your models here.
class SendMsg(models.Model):
nid = models.AutoField(primary_key=True)
code = models.CharField(max_length=6)
email = models.CharField(max_length=32, db_index=True)
times = models.IntegerField(default=0)
ctime = models.DateTimeField()
class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32, unique=True)
password = models.CharField(max_length=32)
email = models.CharField(max_length=32, unique=True)
ctime = models.DateTimeField()
class NewsType(models.Model):
nid = models.AutoField(primary_key=True)
caption = models.CharField(max_length=32)
class News(models.Model):
nid = models.AutoField(primary_key=True)
user_info = models.ForeignKey('UserInfo')
news_type = models.ForeignKey('NewsType')
title = models.CharField(max_length=32, db_index=True)
url = models.CharField(max_length=128)
content = models.CharField(max_length=50)
favor_count = models.IntegerField(default=0)
comment_count = models.IntegerField(default=0)
ctime = models.DateTimeField()
class Favor(models.Model):
nid = models.AutoField(primary_key=True)
user_info = models.ForeignKey('UserInfo')
news = models.ForeignKey('News')
ctime = models.DateTimeField()
class Meta:
unique_together = (("user_info", "news"),)
class Comment(models.Model):
nid = models.AutoField(primary_key=True)
user_info = models.ForeignKey('UserInfo')
news = models.ForeignKey('News')
up = models.IntegerField(default=0)
down = models.IntegerField(default=0)
ctime = models.DateTimeField()
device = models.CharField(max_length=16)
content = models.CharField(max_length=150)
reply_id = models.ForeignKey('Comment', related_name='b', null=True, blank=True)
自定义扩展simple_tag函数
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
TEMP1 = """
<div class='content' style='margin-left:%s;'>
<span>%s</span>
"""
def generate_comment_html(sub_comment_dic, margin_left_val):
html = '<div class="comment">'
#遍历子元素
for k, v_dic in sub_comment_dic.items():
html += TEMP1 % (margin_left_val, k[1])
#假如子元素的值为真,说明有子评论
if v_dic:
#递归处理,直到全部处理完
html += generate_comment_html(v_dic, margin_left_val)
html += "</div>"
html += "</div>"
return html
@register.simple_tag
def tree(comment_dic):
html = '<div class="comment">'
for k, v in comment_dic.items():
html += TEMP1 % (0, k[1])
#设置向右偏移30个像素
html += generate_comment_html(v, 30)
html += "</div>"
html += '</div>'
return mark_safe(html)
comment.html
{% load xx %}
{% tree comment_dict %}