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 %}