上一篇文章《django树形结构之博客评论案例-基础篇》 介绍了评论的基本实现,包含回复功能
, 但是美中不足的是页面展示无法实现树状层级化展示。
其实说不能实现,也不全对,因为Django默认提供了一个内置过滤器unordered_list
,官网说明参考 。但是 unordered_list
存在两个限制
1、需要单独定义一个递归行数,把数据库中的结果重新保存为嵌套结构,同时需要在view视图中先获取顶层记录
# views.py
def recurse_display(data):"""递归展示"""display_list = []for item in data:display_list.append(item)children = item.children.all()if len(children) > 0:display_list.append(recurse_display(children))return display_listdef detail(request, id):post = (pk=id)top_comoments = Comments.objects.filter(parent_comment=None)comoments = recurse_display(top_comments)return render(request, 'comment/detail.html', {'comoments': comoments, "post": post})
2、在template中使用 unordered_list
可以进行树状层级展示,但是无法添加样式
1、安装
pip install django-mptt
2、配置
# settings.py
INSTALLED_APPS = [... ...,'mptt',
]
3、模型定义
# models.py
dels import MPTTModel, TreeForeignKey
class CommentMPTT(MPTTModel):# 注意这里使用 TreeForeignKeypost = models.TreeForeignKey(Post, on_delete=models.DO_NOTHING, verbose_name="评论的文章")... ...# 建议默认取名 parentparent_comment = models.ForeignKey('self', null=True, on_delete=models.DO_NOTHING, verbose_name="回复的评论")class MPTTMeta:# 如果关联自身的属性不是 `parent` 则需要特殊指定parent_str = 'parent_comment'
3、视图函数
def detail(request, id):def detail(request, id):post = (pk=id)comoments = Comments.objects.all()return render(request, 'comment/detail.html', {'comoments': comoments, "post": post})
4、template模板
<!-- 需要在页面最开始配置加载 mptt_tags 标签 -->
{% load mptt_tags %}<!-- 在页面需要展示 评论列表的地方 -->
<!-- comment list -->
<div class="row"><h5>评论列表, 总 <span>{{ unt }}</span> 条评论</h5>{% recursetree comments %}{% with comment=node %}<div class="{% if comment.parent_comment %} offset-1 col-11 {% else %} col-12{% endif %}"><hr><p><strong style="color: orange;">{{ commentment_user }}</strong>{% if comment.parent_comment %}<strong style="color: orange;">=> {{ comment.parent_commentment_user }}</strong>{% endif %}</p><div>{{ commentment_body|safe }}</div><div><span style="color: gray;">{{ commentment_time|date:"Y-m-d H:i" }}</span><button class="reply" username="{{ commentment_user }}" pk="{{ comment.pk }}">Reply</button></div>{% if not comment.is_leaf_node %}<div class="children">{{ children }}</div>{% endif %}</div>{% endwith%}{% endrecursetree %}
</div>
然后进行评论
和回复评论测试
,效果如下
这里发现,针对同一个顶级评论下的多次评论然后产生多级层次,如果回复很多,将会导致
无限层级
在页面展示上也不美观
所以一般我们都是按照两级层级展示
,所以这里需要对comment
视图函数做修改
# views.py
# 这里只展示核心变动
if pid:## 添加代码进行层级转化,大于2层的都转化为2层parent_comment = (id=pid)new_comment.parent_comment_id = _root().id# new_comment.parent_comment_id = pid
然后进行评论
和回复评论测试
,效果就按照如期的两级层级
展示了
至此,大家是不是觉得完美了呢?
其实还是有个小问题的,不知道大家发现没有
李四回复张三的时候,消息显示
@张三 xxxx
是没有问题,但是在消息头谁回复谁
这里是不是都成了 回复 Colin, 也就是全部回复顶级父节点
了
两种解决办法
1、不展示消息头部的 谁回复谁
,因为在回复消息的时候,已经 @
回复的人了。
同时这里可以从页面设置不同颜色来体现,然后再后台也针对回复的人发送消息
2、如果非要展示,那就在模型中在添加一个字段属性 reply_to ,然后在 comment
视图函数中修改 reply_to的具体人
# views.py
# views.py
# 这里只展示核心变动
if pid:## 添加代码进行层级转化,大于2层的都转化为2层parent_comment = (id=pid)new_comment.parent_comment_id = _root().id# 回复人ply_to = parent_commentment_user# new_comment.parent_comment_id = pid
然后在template模型中修改
{% if comment.parent_comment %}
<strong style="color: orange;">=> {{ ply_to }}
</strong>
{% endif %}
最终的效果如下
完美实现~ 项目源码详见
/
如果觉得文章对你有用,请不吝点赞和关注公众号搜索 全栈运维
或者 DailyJobOps
个人博客 /
知乎平台
CSDN平台
简书平台
本文发布于:2024-02-02 05:48:09,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170682409041763.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |