Implement Hierarchical Comments

Implement Hierarchical Comments

1. Warm up

Write a function that takes an integer n and outputs the nth value in the Fibonacci sequence.

2. Analysis-level comments

From the analysis of the phenomenon:

We can abstract each comment as a letter. For the convenience of identification, we agree that the first-level comments are letters without numbers such as A, B, C, and D.

Direct subcomments of ABCD are A1, A2, B1, B2 etc. Subcomments of A1 A2, B1, B2 are A1-1, A1-2, B1-1, B1-2. . A1-1's subcomments are A1-1-1, A1-1-2, and so on

Then we can simply abstract an example like this:

The list of comments for each of our posts is a queryset that looks like this:

<QuerySet [<Comment: A>, <Comment: A1>, <Comment: A2>, <Comment: A1-1>, <Comment: A2-1>, <Comment: A1-1-1>, <Comment: A2-1-1>, <Comment: B>, <Comment: B1>, <Comment: A1-1-2>, <Comment: B2>, <Comment: C>]>

Now the problem is, how to display the above queryset into the hierarchical relationship in the above figure.

Further analysis found that if the hierarchical relationship in the above figure is represented by a python dictionary, it can be expressed as:

{

A : {A1:{A1-1:{A1-1-1:{},A1-1-2:{}}}, A2:{A2-1:{A2-1-1:{}}}},

B: {B1: {}, B2: {}},

C: {}

}

In each line, a pair of relationships can actually be found: the relationship between the current node and the parent node, for example, the parent node in the first line is None, and the child node is A. The parent node of the second line is A, and the child node is A1. Then the relationship in the above figure can be converted into a list:

[(None, A),

(A, A1),

(A1, A1-1),

(A1-1, A1-1-1),

(A1-1, A1-1-2),

(A,A2),(A2, A2-1),

(A2-1,A2-1-1),

(None,B),

(B, B1),

(B,B2),

(none,C)]

In our comment list, each comment object contains its own parent comment, that is, there is such a relationship (comment_obj.parent_comment, comment_obj), then we can convert the queryset of comments into a list similar to the above. If you can find a dictionary that converts the above list into a hierarchical display, the hierarchical comment display of our comment list queryset can be realized.

The basic idea:

Creates an empty dictionary to hold the result of converting the list of comments to a dictionary of comments.

If a comment has no parent node, then use this comment as the root node and store it as a comment dictionary. If there is a parent node, then recursively search for the parent node. If the parent node is found, insert itself under the parent node. After the comment dictionary is correctly generated, recursively output the dictionary. We customize the function that outputs the dictionary as a simple_tag, which is convenient for us to call on the front end.

code show as below:

from django.utils.safestring import mark_safe
# Recursively find parent node
def find_father(dic, comment_obj):
    # Loop through each set of elements in the dictionary
    for k, v_dic in dic.items():
        # If k is equal to the parent node of comment_obj, then the parent is found.
        if k == comment_obj.parent_comment:
            # I found my father, recognized my ancestors, put myself under my father, and left a place for my future son
            dic[k][comment_obj] = {}
            # Find the father, process it, return
        else:
            # I didn't find it just now, peel off one layer, and then look down.
            find_father(dic[k], comment_obj)


# recursively generate html string
def generate_comment_html(sub_comment_dic, margin_left_val):
    # First create an empty string
    html = ""
    # Loop over the incoming dictionary
    for k, v_dic in sub_comment_dic.items():
        html += "<div style='margin-left:%spx'><span class='nickname'>" % margin_left_val + k.name + "</span>" + "<time class='submit-date'>" + str(k.created_time.strftime('%Y-%m-%d %H:%M:%S')) + "<div class='text'>" + k.text + '</div></div><hr>'
        # html += "<div style='margin-left:%spx' class='comment-node'>" % margin_left_val + k.text + "</div>"
        # It is possible that there are still elements in v_dic, recursively continue to add
        if v_dic:
            html += generate_comment_html(v_dic, margin_left_val+35)
    # The loop is completed and finally return to html
    return html


# Generate hierarchical comments
@register.simple_tag
def build_comment_tree(comment_list):
    # Define an empty dictionary to store the converted result
    comment_dic = {}
    # Loop through each element in comment_list
    for comment_obj in comment_list:
        # Determine whether comment_obj has a parent node. If not, this puts that comment as the first node
        if comment_obj.parent_comment is None:
            comment_dic[comment_obj] = {}
        else:
            # Otherwise go to the parent node of the object.
            find_father(comment_dic, comment_obj)

    # After the above execution is completed, there will be a converted result in comment_dic
    # Start concatenating html strings
    html = "<ul class='comment-list list-unstyled'>"
    # Specify a margin left, indent a little to the right every time there is recursion.
    margin_left = 0
    # Operate on each set of elements in comment_dic
    for k,v in comment_dic.items():
        # first layer html
        html += "<li class='comment-item'><span class='nickname'>" + k.name + "</span>" + "<time class='submit-date'>" + str(k.created_time.strftime('%Y-%m-%d %H:%M:%S')) + "<div class='text'>" + k.text + '</div></li>'
        # Add his son by recursion
        html += generate_comment_html(v, margin_left+35)
    # Finally close ul
    html += " </ul>"
    # turn off escaping
    return mark_safe(html)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324664056&siteId=291194637