python菜单递归查询以及将数据进行json转化的实例

Y2J
发布: 2017-04-21 16:18:21
原创
2997人浏览过

本篇文章主要介绍了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 ”对象中,可以看到完整的菜单树形结构

Find JSON Path Online
Find JSON Path Online

Easily find JSON paths within JSON objects using our intuitive Json Path Finder

Find JSON Path Online 30
查看详情 Find JSON Path Online

转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
登录后复制

备注:

  1. 当一个菜单没有子菜单时,删除掉“subMenus”属性,否则转Json时会出现空值

  2. model_list_2_dto_list 方法可以把Menu列表转成MenuDto列表

  3. to_pinyin 是把汉字转成拼音的方法,在这里不用关注

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类型,否则返回的字符串中会带有“\”

查询结果

以上就是python菜单递归查询以及将数据进行json转化的实例的详细内容,更多请关注php中文网其它相关文章!

相关标签:
python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号