前言
我们经常会有这样的需求,比如评论功能,每个评论都有可能会有自己的子评论,如果在界面只展示成一列的话非常不美观,也不能体现出他们的层级关系。那么我们今天就来看看如何使用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