这里有新鲜出炉的 Python 多线程编程,程序狗速度看过来!
Python 是一种面向对象、解释型计算机程序设计语言,由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。Python 语法简洁而清晰,具有丰富和强大的类库。它常被昵称为胶水语言,它能够把用其他语言制作的各种模块(尤其是 C/C++)很轻松地联结在一起。
本篇文章主要介绍了 python 递归查询菜单并转换成 json 实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
最近需要用 python 写一个菜单,折腾了两三天才搞定,现在记录在此,需要的朋友可以借鉴一下。
备注:文章引用非可执行完整代码,仅仅摘录了关键部分的代码
环境
表结构
- CREATE TABLE `tb_menu` (
- `id` varchar(32) NOT NULL COMMENT '唯一标识',
- `menu_name` varchar(40) DEFAULT NULL COMMENT '菜单名称',
- `menu_url` varchar(100) DEFAULT NULL COMMENT '菜单链接',
- `type` varchar(1) DEFAULT NULL COMMENT '类型',
- `parent` varchar(32) DEFAULT NULL COMMENT '父级目录id',
- `del_flag` varchar(1) NOT NULL DEFAULT '0' COMMENT '删除标志 0:不删除 1:已删除',
- `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
- `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
- PRIMARY KEY (`id`) USING BTREE
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单表';
Python 代码
Menu 对象中,有一个子菜单列表的引用 "subMenus",类型为 list
核心代码
- def set_subMenus(id, menus):
- """
- 根据传递过来的父菜单id,递归设置各层次父菜单的子菜单列表
- :param id: 父级id
- :param menus: 子菜单列表
- :return: 如果这个菜单没有子菜单,返回None;如果有子菜单,返回子菜单列表
- """
- # 记录子菜单列表
- subMenus = []
- # 遍历子菜单
- for m in menus:
- if m.parent == id:
- subMenus.append(m)
- # 把子菜单的子菜单再循环一遍
- for sub in subMenus:
- menus2 = queryByParent(sub.id)
- # 还有子菜单
- if len(menus):
- sub.subMenus = set_subMenus(sub.id, menus2)
- # 子菜单列表不为空
- if len(subMenus):
- return subMenus
- else: # 没有子菜单了
- return None
测试方法
- def test_set_subMenus(self):
- # 一级菜单
- rootMenus = queryByParent('')
- for menu in rootMenus:
- subMenus = queryByParent(menu.id)
- menu.subMenus = set_subMenus(menu.id, subMenus)
备注:基本流程是:先查询一级菜单,然后分别把该级菜单的 id、和这级菜单的子菜单列表传入 set_subMenus 方法,递归进行子菜单列表的下级菜单设置;
支持传递菜单 Id,查询该菜单下面的所有子菜单。传递空字符,则从根目录开始查询
在 "rootMenus" 对象中,可以看到完整的菜单树形结构
转 Json
我采用的 ORM 框架是:sqlalchemy,直接从数据库中查询出来的 Menu 对象,转 Json 时会报错。需要重新定义一个 DTO 类,来把 Menu 对象转成 Dto 对象。
MenuDto
- class MenuDto():
- def __init__(self, id, menu_name, menu_url, type, parent, subMenus):
- super().__init__()
- self.id = id
- self.menu_name = menu_name
- self.menu_url = menu_url
- self.type = type
- self.parent = parent
- self.subMenus = subMenus
- def __str__(self):
- return '%s(id=%s,menu_name=%s,menu_url=%s,type=%s,parent=%s)' % (
- self.__class__.__name__, self.id, self.menu_name, self.menu_url, self.type, self.parent)
- __repr = __str__
于是,重新定义了递归设置子菜单的方法
- def set_subMenuDtos(id, menuDtos):
- """
- 根据传递过来的父菜单id,递归设置各层次父菜单的子菜单列表
- :param id: 父级id
- :param menuDtos: 子菜单列表
- :return: 如果这个菜单没有子菜单,返回None;如果有子菜单,返回子菜单列表
- """
- # 记录子菜单列表
- subMenuDtos = []
- # 遍历子菜单
- for m in menuDtos:
- m.name = to_pinyin(m.menu_name)
- if m.parent == id:
- subMenuDtos.append(m)
- # 把子菜单的子菜单再循环一遍
- for sub in subMenuDtos:
- menus2 = queryByParent(sub.id)
- menusDto2 = model_list_2_dto_list(menus2,
- "MenuDto(id='', menu_name='', menu_url='', type='', parent='', subMenus='')")
- # 还有子菜单
- if len(menuDtos):
- if len(menusDto2):
- sub.subMenus = set_subMenuDtos(sub.id, menusDto2)
- else: # 没有子菜单,删除该节点
- sub.__delattr__('subMenus')
- # 子菜单列表不为空
- if len(subMenuDtos):
- return subMenuDtos
- else: # 没有子菜单了
- return None
备注:
View 层返回 Json 的方法
- def get(self):
- param = request.args
- id = param['id']
- # 如果id为空,查询的是从根目录开始的各级菜单
- rootMenus = queryByParent(id)
- rootMenuDtos = model_list_2_dto_list(rootMenus,
- "MenuDto(id='', menu_name='', menu_url='', type='', parent='', subMenus='')")
- # 设置各级子菜单
- for menu in rootMenuDtos:
- menu.name = to_pinyin(menu.menu_name)
- subMenus = queryByParent(menu.id)
- if len(subMenus):
- subMenuDtos = model_list_2_dto_list(subMenus,
- "MenuDto(id='', menu_name='', menu_url='', type='', parent='', subMenus='')")
- menu.subMenus = set_subMenuDtos(menu.id, subMenuDtos)
- else:
- menu.__delattr__('subMenus')
- menus_json = json.dumps(rootMenuDtos, default=lambda o: o.__dict__, sort_keys=True, allow_nan=false,
- skipkeys=true)
- # 需要转字典,否则返回的字符串会带有"\"
- menus_dict = json_dict(menus_json)
- return fullResponse(menus_dict)
- fullResponse
- from flask import jsonify
- def fullResponse(data='', msg='', code=0):
- if msg == '':
- return jsonify({'code': code, 'data': data})
- elif data == '':
- return jsonify({'code': code, 'msg': msg})
- else:
- return jsonify({'code': code, 'msg': msg, 'data': data})
备注:python 中 json 和字典的含义类似,在最后 json 返回给页面时,需要先使用 json_dict 方法转成 dict 类型,否则返回的字符串中会带有 "\"
查询结果
来源: http://www.phperz.com/article/17/0701/332930.html