django树形结构展示

1、使用Django自带的标签 unordered_list

1.1、定义模型
class Department(models.Model):
	name = models.CharField(max_length=64, unique=True, verbose_name="部门名称")
	# db_constraint 控制是否在数据库中为此外键创建约束,默认为True。在数据库中创建外键约束是数据库规范中明令禁止的行为
	# 但是不影响Django的关联查询
	parent = models.ForeignKey('Department', 
		on_delete=models.PROTECT, 
		null=True, blank=True, 
		db_constraint=False,
		related_name='children', 
		verbose_name="父级部门")

	def __str__(self):
		return self.name
1.2、自定义递归获取函数和view
from app.models import Department

def recurse_display(data):
    """递归展示"""
    display_list = []
    for item in data:
        display_list.append(item.name)
        children = item.children.all()
        if len(children) > 0:
            display_list.append(recurse_display(children))
    return display_list


def depart_tree(request):
    # 核心是filter(parent=None) 查到最顶层的那个parent节点
    departs = Department.objects.filter(parent=None)
    data = recurse_display(departs)
    return render(request, 'app/tree.html', {'data': data})

1.3、页面 template中使用
The Tree:

{{ data|unordered_list }}
1.4、效果如下:

django-tree.png

2、使用django-mptt

使用前先安装模块

pip install django-mptt

然后需要在 INSTALLED_APPS 中配置上

INSTALLED_APPS = [
    ... ...
    'mptt',
]
2.1、定义模型
from mptt.models import MPTTModel


class DepartMPTT(MPTTModel):
    name = models.CharField(max_length=64, unique=True, verbose_name="部门名称")
    # db_constraint 控制是否在数据库中为此外键创建约束,默认为True。在数据库中创建外键约束是数据库规范中明令禁止的行为
    # 但是不影响Django的关联查询
    parent = models.ForeignKey('DepartMPTT', 
        on_delete=models.PROTECT, 
        null=True, blank=True, 
        db_constraint=False,
        related_name='children', 
        verbose_name="父级部门")

    # if parent filed name is not parent, e.g. depart_parent
    # class MPTTMeta:
    #     parent_attr = 'depart_parent'

    def __str__(self):
        return self.name

注意在model中的 MPTTMeta如果父字段使用的不是parent名称,就需要单独在 MPTTMeta 中说明

2.2、定义view
from app.models import DepartMPTT

def depart_mptt_tree(request):
    departs = DepartMPTT.objects.all()
    return render(request, 'app/mptt.html', {'departs': departs})

这里网上有些文章说必须在context中使用nodes 才可以,即 {'nodes': departs};其实进过验证不必非得是nodes才行,比如这里的 departs

2.3、在template中使用

<!-- 首先要导入对应的标签 -->
{% load mptt_tags %} 

{% recursetree departs %}
<li>
    <!-- 这里可以使用with把node赋值给其他的变量名 -->
    {% if node.is_leaf_node %}
    <span style="color: orange;">{{ node.name }}</span>
    {% else %}
    <span style="color: red;">{{ node.name }}</span>
        <ul>
            {{ children }}
        </ul>
    {% endif %}
</li>
{% endrecursetree %}

这里需要注意的是,在前端代码中node有时候有特殊含义,可以使用 with 标签进行替换,注意标记要闭合结束 {% endwith %}

2.4、扩展admin

mptt提供了对应的admin类,在后台添加和展示 MTPPModel 的时候会更友好些

from .models import DepartMPTT
from mptt.admin import MPTTModelAdmin

admin.site.register(DepartMPTT, MPTTModelAdmin)

具体效果就不给大家展示,可以自己尝试下

最终效果和上面第一种方式的效果类似。

3、项目代码

具体的源码和使用说明详见 https://gitee.com/colin5063/django_learning/tree/django_tree/

感兴趣的可以扫码关注个人微信公众号,文章首发
在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值