django+vue3+el-tree树形组件菜单

前言

在一些消费的app,eg京东,淘宝。我们经常在pc端上面会出现点击电视 ,就会有小米、海尔、等各种品牌的电视。这也就是咱们说的树形组件 --也就是一级标签,二级标签,三级标签。(以上是小编举的例子,如有不对请多指教包容)


这个篇文章主要的效果图

django+vue3+el-tree树形组件菜单_第1张图片

既然说了是Django+vue3+el-tree就了一列大纲他的步骤分那些

1.分析django 中所需要的表

2.django 中主要实现的业务逻辑

2.1django 重写后台管理

3.vue3中使用elementUI配置

4.vue3使用el-tree的布局

5.el-tree上附加的功能


那小编带着来第一步

1.分析django 中所需要的表

1.菜单表:id,name(菜单名),pid(父类),status(1显示0不显示)

class Menu(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=38, verbose_name='菜单名称')
    pid = models.IntegerField(default=0, verbose_name='父id')
    status = models.IntegerField(default=1, verbose_name='显示1不显示0')

    def __str__(self):
        return self.name

    class Meta:
        db_table = 'meum_menu'

2.django 中主要实现的业务逻辑

增加菜单

查看菜单

修改菜单

删除菜单


添加菜单接口

  1. 请求:post
  2. Api:http://127.0.0.1:8000/meum/add_menu/
  3. 描述:添加菜单名,父类,状态(显示不显示)
  4. 添加条件         获取前端传来的数据,
                          判断 菜单名字是空的?
                          判断 改子类的父类是否存在 id=pid  

参数名称

参数类型

参数描述

实例

name

string

菜单名称

冰箱

Pid

int

父类id,默认0

0

status

int

状态0不显示1显示

1

返回值:

成功返回:{“code”:”200”,’msg’:”添加成功”}

失败返回:{“code”:”500”,”msg”:”添加失败”}

class AddMenuViews(APIView):
    """添加菜单
    获取前端传来的数据,
    判断 菜单名字是空的?
    判断 改子类的父类是否存在 id=pid
    """

    def post(self, request):
        name = request.data.get('name')
        pid = request.data.get('pid', 0)
        print('pid>>>>>>>>>', pid)
        status = request.data.get('status', 1)
        if not all([name]):
            return Response({'msg': '菜单名称为空', 'code': 500})
        if pid:
            pid_count = Menu.objects.filter(id=pid).count()
            if pid_count == 0:
                return Response({'msg': '该类别的父类id不存在', 'code': 500})
        menu = Menu.objects.create(name=name, pid=pid, status=status)
        menu.save()
        return Response({'msg': '添加成功', 'code': 200})

查看菜单接口

1.请求:get

2.Api:http://127.0.0.1:8000/meum/get_menu/

3.描述:获取菜单中status=1的数据,进行排列根据pid进行分级

过滤条件

Status=1

Pid布局

查看pid 是否是0,0 为一级标签,添加并返回

判断此子类的父类下面是否已经有了子类,如果没有就初始化

返回值:

成功返回:{“code”:”200”,’msg’:”查看成功”}/{“code”:200,”data”:result}

                                                                     result承接的是序列化之后返回的数据

失败返回:{“code”:”500”,”msg”:”查看失败”}

其实难点还是在获取数据 因为他需要按照pid的来排序----小编刚接触的时候也比较迷糊慢慢就好了

class GetMenuViews(APIView):
    def get(self, request):
        # 获取显示的菜单
        menu = Menu.objects.filter(status=1)
        # 将获取的数据转换为json数据 对象名=序列化器(内容)
        #多个数据是many=True
        ser = MenuSer(menu, many=True)
        #.data 是返回数据
        print('ser.data', ser.data)
        result = xtree(ser.data)
        return Response({'code': 200, 'data': result})

序列化---在django中序列化是需要自己写的

小编在这用的是模型类序列化器

from rest_framework import serializers
from meum.models import Menu


class MenuSer(serializers.ModelSerializer):
    class Meta:
        model = Menu  # 指明需要序列化的模型类
        fields = '__all__'   # 指明模型类的全部字段参数序列化和反序列化

其实那可能在我看来最重要的不是这些  而是在展示的时候的思路  怎样把一级标签相连的二级标签 展示出来 用了什么思路  那就具体问题具体分析

在代码具体解析

tree = {}
for i in data:
    # 数的第一条数据就 变成data中i循环的第一条数据
    tree[i['id']] = i

然后在重新循环data数据

查看pid 是不是0 如果是0则是一级标签

如果不是就判断下  ----子类的父类下面是否有了子类

如果没有就在子类下面添加一个空列表

如果有 就在父类下面添加子类这条数据

def xtree(data):
    # 如果数据长度小于0,则返回数据
    if len(data) <= 0:
        return data
    # 如果长度>0 则进行下面的
    # 对数据重新布局
    tree = {}
    for i in data:
        # 数的第一条数据就 变成data中i循环的第一条数据
        # print('i', i)
        # print('i["id"]', i['id'])
        tree[i['id']] = i
        # print('tree[i["id"]]', tree[i['id']])
    dlist = []
    for j in data:
        # 查看pid是否是0,0为一级标签
        #  j['pid'] 就是data 数据中  每循环一条的数据中的pid
        print('j',j)
        pid = j['pid']
        if pid == 0:
            dlist.append(j)
        else:
            # 判断此子类的父类下面是否已经有了子类
            # 如果没有得到这pid 就跳出本次循环进入下一次循环
            if not tree.get(pid,None):
                continue
             # 如果children不在tree[pid]里面
            #    则就添加一个空列表
            # 否则就是在添加children一条数据
            if 'children' not in tree[pid]:
                tree[pid]['children'] = []
            tree[pid]['children'].append(j)
    return dlist

修改菜单接口

  1. 请求:post
  2. Api:http://127.0.0.1:8000/meum/update_menu/
  3. 描述修改:根据id  菜单名称
  4. 修改条件  根据id进行查找这条要修改的数据是否存在,
  5.           根据name查找数据库中是否有重复名字
  6.           然后进行修改menu.objects.filter(id=id).update(name=name)

参数

类型

参数描述

实例

Id

int

菜单id

1

name

string

菜单名字

冰箱

返回值:

成功返回:{“code”:”200”,’msg’:”修改成功”}

失败返回:{“code”:”500”,”msg”:”修改失败”}

class UpdateMenuViews(APIView):
    """修改菜单
    判断 是否有空
    判断 是否有这条数据
    判断 这修改的名字是否重复
    获取到这个对象get
    进行修改
    """

    def post(self, request):
        id = request.data.get('id')
        name = request.data.get('name')
        if not all([name, id]):
            return Response({'msg': '菜单信息不能为空', 'code': 500})
        menu = Menu.objects.filter(id=id).first()
        if not menu:
            return Response({'msg': '没有该菜单,请输入正确的菜单id', 'code': 500})
        name_num = Menu.objects.filter(name=name).count()
        if name_num != 0:
            return Response({'msg': '该菜单名字已经重复,请重新输入', 'code': 500})
        menu.name = name
        menu.save()
        return Response({'msg': '该菜单修改成功', 'code': 200})

删除菜单接口

1.请求put

2.apI:http://127.0.0.1:8000/meum/delete_menu/

3.描述删除:通过传参id的形式进行删除--把状态改为status=0

4.删除的条件:根据id进行查找这条要修改的数据是否存在,

                       然后进行修改menu.objects.filter(id=id).update(status=0)

参数

类型

参数描述

修改为

status

int

状态

0(不显示)

返回值:

成功返回:{“code”:”200”,’msg’:”删除成功”}

失败返回:{“code”:”500”,”msg”:”删除失败”}


class DeleteMenuViews(APIView):
    """删除
    通过id进行删除
    判断改id是否存在
    存在了然后把状态修改为不显示
    """

    def put(self, request, id):
        try:
            menu = Menu.objects.filter(id=id).first()
            if not menu:
                return Response({'msg': "没有该菜单id,请输入正确的id", 'code': 500})
            # 相当删除 ---把修改的数据状态改了
            menu = Menu.objects.filter(id=id).update(status=0)
            # menu.save()
            # ser = MenuSer(menu, many=True)
            return Response({'msg': "删除成功"})
        except:
            error = traceback.format_exc()
            print('error', error)
            return Response({'code': 500, 'error': error})

2.1django 重写后台管理

其实简单的肯定在学的时候都接触过  admin.site.register(models)

from django.contrib import admin

# Register your models here.
# 在应用app中的admin.py中导入注册要管理的模型models类
from .models import Book
# 调用admin.site.register方法进行注册
admin.site.register(Book)

还有一种叫做模型类管理器

我也不具体说了 ----有需要点击这个链接http://t.csdn.cn/pYrsf

from django.contrib import admin
from meum.models import Menu


# Register your models here.
@admin.register(Menu)
class MenuAdmin(admin.ModelAdmin):
    """账号后台管理"""
    list_display = ('id', 'name', 'pid', 'status')  # 展示字段
    list_filter = ('name', 'pid', 'status')#过滤字段
    list_per_page = 20  # 分页
    search_fields = ('name', 'pid', 'status')#搜索字段

3.vue3中使用elementUI配置

如果刚安装的小伙伴 肯定是没有elementui组件 下载的命令来了npm install element-plus --save

在main.js里就要加上下面代码

import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
const app = createApp(App);
app.use(ElementPlus)

如果没有下载vant   下载的命令来了npm i vant -S

在main.js里就要加上下面代码

import Vant from 'vant';
import 'vant/lib/index.css';
app.use(Vant)

4.vue3使用el-tree的布局

肯定小伙伴们第一时间想到的是官方Tree 树形控件 | Element Plus

那咱就说说简单的tree


 








5.el-tree上附加的功能

这个功能能肯定 和后端挂钩啊

具体的解释都在代码块中

vue2中el-tree中是使用 scoped slot 会传入两个参数node和data,分别表示当前节点的 Node 对象和当前节点的数据。
vue2中的 scoped slot 位于span标签内
vue3中el-tree则是使用#default传入两个参数node和data,分别表示当前节点的 Node 对象和当前节点的数据。
vue3中的#default位于template标签内
vue3在使用elemnt ui是应该参考element plus的官方文档





文章到这也就结束,也希望可以帮助到大家,有问题请多多指教

你可能感兴趣的:(django+vue3,vue.js,javascript,django,python)