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 %}
原文地址:https://www.cnblogs.com/ccorz/p/5985534.html