django树形结构之博客评论案例-优化篇mptt

2023-12-19 00:30

本文主要是介绍django树形结构之博客评论案例-优化篇mptt,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

小猫咪

前言说明

上一篇文章《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 = Post.objects.get(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 可以进行树状层级展示,但是无法添加样式

MPTT使用

1、安装

pip install django-mptt

2、配置

# settings.py
INSTALLED_APPS = [... ...,'mptt',
]

3、模型定义

# models.py
from mptt.models 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 = Post.objects.get(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>{{  comments.count }}</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;">{{ comment.comment_user }}</strong>{% if comment.parent_comment %}<strong style="color: orange;">=> {{ comment.parent_comment.comment_user }}</strong>{% endif %}</p><div>{{ comment.comment_body|safe }}</div><div><span style="color: gray;">{{ comment.comment_time|date:"Y-m-d H:i" }}</span><button class="reply" username="{{ comment.comment_user }}" pk="{{ comment.pk }}">Reply</button></div>{% if not comment.is_leaf_node %}<div class="children">{{ children }}</div>{% endif %}</div>{% endwith%}{% endrecursetree %}
</div>

然后进行评论回复评论测试 ,效果如下

django-blog-comment-03

这里发现,针对同一个顶级评论下的多次评论然后产生多级层次,如果回复很多,将会导致无限层级 在页面展示上也不美观

所以一般我们都是按照两级层级展示 ,所以这里需要对comment 视图函数做修改

# views.py 
# 这里只展示核心变动
if pid:## 添加代码进行层级转化,大于2层的都转化为2层parent_comment = CommentMPTT.objects.get(id=pid)new_comment.parent_comment_id = parent_comment.get_root().id# new_comment.parent_comment_id = pid

然后进行评论回复评论测试 ,效果就按照如期的两级层级展示了

django-blog-comment-04

至此,大家是不是觉得完美了呢?

其实还是有个小问题的,不知道大家发现没有

李四回复张三的时候,消息显示@张三 xxxx 是没有问题,但是在消息头 谁回复谁 这里是不是都成了 回复 Colin, 也就是全部回复顶级父节点

扩展

两种解决办法

1、不展示消息头部的 谁回复谁 ,因为在回复消息的时候,已经 @ 回复的人了。

同时这里可以从页面设置不同颜色来体现,然后再后台也针对回复的人发送消息

2、如果非要展示,那就在模型中在添加一个字段属性 reply_to ,然后在 comment 视图函数中修改 reply_to的具体人

# views.py
# views.py 
# 这里只展示核心变动
if pid:## 添加代码进行层级转化,大于2层的都转化为2层parent_comment = CommentMPTT.objects.get(id=pid)new_comment.parent_comment_id = parent_comment.get_root().id# 回复人new_comment.reply_to = parent_comment.comment_user# new_comment.parent_comment_id = pid

然后在template模型中修改

{% if comment.parent_comment %}
<strong style="color: orange;">=> {{ comment.reply_to }}
</strong>
{% endif %}

最终的效果如下

image-20221014121513820


完美实现~ 项目源码详见
https://gitee.com/colin5063/django_learning_v2/tree/django_blog_comment_v2/

如果觉得文章对你有用,请不吝点赞和关注公众号搜索 全栈运维 或者 DailyJobOps

个人博客 http://blog.colinspace.com/

知乎平台 https://www.zhihu.com/people/colin-31-49

CSDN平台 https://blog.csdn.net/eagle5063

简书平台 https://www.jianshu.com/u/6d793fbacc88

这篇关于django树形结构之博客评论案例-优化篇mptt的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/510323

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Golang操作DuckDB实战案例分享

《Golang操作DuckDB实战案例分享》DuckDB是一个嵌入式SQL数据库引擎,它与众所周知的SQLite非常相似,但它是为olap风格的工作负载设计的,DuckDB支持各种数据类型和SQL特性... 目录DuckDB的主要优点环境准备初始化表和数据查询单行或多行错误处理和事务完整代码最后总结Duck

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

MySQL不使用子查询的原因及优化案例

《MySQL不使用子查询的原因及优化案例》对于mysql,不推荐使用子查询,效率太差,执行子查询时,MYSQL需要创建临时表,查询完毕后再删除这些临时表,所以,子查询的速度会受到一定的影响,本文给大家... 目录不推荐使用子查询和JOIN的原因解决方案优化案例案例1:查询所有有库存的商品信息案例2:使用EX

MySQL中my.ini文件的基础配置和优化配置方式

《MySQL中my.ini文件的基础配置和优化配置方式》文章讨论了数据库异步同步的优化思路,包括三个主要方面:幂等性、时序和延迟,作者还分享了MySQL配置文件的优化经验,并鼓励读者提供支持... 目录mysql my.ini文件的配置和优化配置优化思路MySQL配置文件优化总结MySQL my.ini文件

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

Django中使用SMTP实现邮件发送功能

《Django中使用SMTP实现邮件发送功能》在Django中使用SMTP发送邮件是一个常见的需求,通常用于发送用户注册确认邮件、密码重置邮件等,下面我们来看看如何在Django中配置S... 目录1. 配置 Django 项目以使用 SMTP2. 创建 Django 应用3. 添加应用到项目设置4. 创建