美文网首页
django树形结构展示

django树形结构展示

作者: 菩提老鹰 | 来源:发表于2022-04-22 17:52 被阅读0次

    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、效果如下:

    1650616476299-3a3cf368-cd81-41b9-a0cf-7f33ff54c733.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/

    相关文章

      网友评论

          本文标题:django树形结构展示

          本文链接:https://www.haomeiwen.com/subject/ygmnertx.html