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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/eaglecolin/article/details/127369340
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/510323

相关文章

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

Python通过模块化开发优化代码的技巧分享

《Python通过模块化开发优化代码的技巧分享》模块化开发就是把代码拆成一个个“零件”,该封装封装,该拆分拆分,下面小编就来和大家简单聊聊python如何用模块化开发进行代码优化吧... 目录什么是模块化开发如何拆分代码改进版:拆分成模块让模块更强大:使用 __init__.py你一定会遇到的问题模www.

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.