前言
我们经常会有这样的需求,比如评论功能,每个评论都有可能会有自己的子评论,如果在界面只展示成一列的话非常不美观,也不能体现出他们的层级关系。那么我们今天就来看看如何使用django的模版来生成树状结构,以本站为例,效果如下图所示:
那么我们要怎么实现呢?首先先看看评论实体的定义,如下所示:
1
2
3
4
5
|
class comment(models.model): body = models.textfield( '正文' , max_length = 300 ) author = models.foreignkey(settings.auth_user_model, verbose_name = '作者' , on_delete = models.cascade) article = models.foreignkey(article, verbose_name = '文章' , on_delete = models.cascade) parent_comment = models.foreignkey( 'self' , verbose_name = "上级评论" , blank = true, null = true, on_delete = models.cascade) |
可以看到,有一个parent_comment字段,关联自己。这样就可以根据这个字段来生成层级关系。 为了方便我们使用,我们自定义了一个叫query的tag,也可以叫修饰器。定义tag的代码如下,tag的定义应该定义在app/templatetags目录下,这里py文件命名为blog_tags.py:
1
2
3
4
5
6
7
8
9
|
@register .simple_tag def query(qs, * * kwargs): """ template tag which allows queryset filtering. usage: {% query books author=author as mybooks %} {% for book in mybooks %} ... {% endfor %} """ return qs. filter ( * * kwargs) |
接下来下面这段代码是树节点的模版代码。
1
2
3
4
5
6
7
8
9
10
11
12
|
{ % load blog_tags % } { % load comments_tags % } <div id = "commentlist-container" class = "comment-tab" style = "display: block;" > <ol class = "commentlist" > { % query article_comments parent_comment = none as parent_comments % } { % for comment_item in parent_comments % } { % with 0 as depth % } { % include "comments/tags/comment_item_tree.html" % } { % endwith % } { % endfor % } < / ol> < / div> |
其中的{% query article_comments parent_comment=none as parent_comments %}
的功能就是从评论中筛选出来是父级的评论。 comment_item_tree.html的实现也很简单:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
{ % load blog_tags % } <li class = "comment even thread-even depth-{{ depth }} parent" id = "comment-{{ comment_item.pk }}" style = "margin-left: {% widthratio depth 1 3 %}rem" > <div id = "div-comment-{{ comment_item.pk }}" class = "comment-body" > <div class = "comment-meta commentmetadata" > {{ comment_item.created_time }} < / div> <p>{{ comment_item.body |escape|custom_markdown }}< / p> <div class = "reply" ><a class = "comment-reply-link" href = "javascript:void(0)" rel = "external nofollow" onclick = "do_reply({{ comment_item.pk }})" aria - label = "回复给{{ comment_item.author.username }}" >回复< / a>< / div> < / div> < / li><! - - #comment-## --> { % query article_comments parent_comment = comment_item as cc_comments % } { % for cc in cc_comments % } { % with comment_item = cc template_name = "comments/tags/comment_item_tree.html" % } { % with depth = depth|add: 1 % } { % include template_name % } { % endwith % } { % endwith % } { % endfor % } |
其中最主要的部分就是</li>标签后面那段。这里使用with和include配合来在每一次循环里面重复的引入comment_item_tree.html,并且每次引入时赋予当前的评论变量和depth(每层循环depth会+1)。然后在每个评论处使用style="margin-left: {% widthratio depth 1 3 %}rem"
来实现缩进,这样就实现了树状显示。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对服务器之家的支持。
原文链接:https://www.lylinux.net/article/2019/2/28/55.html