python递归查询菜单并转换成json实例


Posted in Python onMarch 27, 2017

最近需要用python写一个菜单,折腾了两三天才搞定,现在记录在此,需要的朋友可以借鉴一下。

备注:文章引用非可执行完整代码,仅仅摘录了关键部分的代码

环境

  • 数据库:mysql
  • python:3.6

表结构

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

备注:

  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实例

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python求crc32值的方法
Oct 05 Python
Python脚本判断 Linux 是否运行在虚拟机上
Apr 25 Python
Python中函数的参数定义和可变参数用法实例分析
Jun 04 Python
Python使用numpy模块创建数组操作示例
Jun 20 Python
Python实现的旋转数组功能算法示例
Feb 23 Python
Python的历史与优缺点整理
May 26 Python
Python3 pywin32模块安装的详细步骤
May 26 Python
PyInstaller的安装和使用的详细步骤
Jun 02 Python
OpenCV 之按位运算举例解析
Jun 19 Python
pymongo insert_many 批量插入的实例
Dec 05 Python
详解pandas apply 并行处理的几种方法
Feb 24 Python
Python面试不修改数组找出重复的数字
May 20 Python
Python中的命令行参数解析工具之docopt详解
Mar 27 #Python
Python使用PDFMiner解析PDF代码实例
Mar 27 #Python
详解python并发获取snmp信息及性能测试
Mar 27 #Python
使用Python写CUDA程序的方法
Mar 27 #Python
pyenv命令管理多个Python版本
Mar 26 #Python
Django实现自定义404,500页面教程
Mar 26 #Python
Python 多线程实例详解
Mar 25 #Python
You might like
php处理文件的小例子(解压缩,删除目录)
2013/02/03 PHP
php实现通过soap调用.Net的WebService asmx文件
2017/02/27 PHP
通用javascript脚本函数库 方便开发
2009/10/13 Javascript
从零开始学习jQuery (四) jQuery中操作元素的属性与样式
2011/02/23 Javascript
打印json对象的内容及JSON.stringify函数应用
2013/03/29 Javascript
js调用iframe实现打印页面内容的方法
2014/03/04 Javascript
原生javascript实现DIV拖拽并计算重复面积
2015/01/02 Javascript
jQuery添加和删除输入文本框标签代码
2016/05/20 Javascript
浅谈JS中逗号运算符的用法
2016/06/12 Javascript
vue组件实现弹出框点击显示隐藏效果
2020/10/26 Javascript
JavaScript中 ES6变量的结构赋值
2018/07/10 Javascript
细说Vue组件的服务器端渲染的过程
2019/05/30 Javascript
微信小程序实现滚动加载更多的代码
2019/12/06 Javascript
Vue数字输入框组件示例代码详解
2020/01/15 Javascript
Vue——前端生成二维码的示例
2020/12/19 Vue.js
python开发之tkinter实现图形随鼠标移动的方法
2015/11/11 Python
Python中列表、字典、元组数据结构的简单学习笔记
2016/03/20 Python
Python3 replace()函数使用方法
2018/03/19 Python
解决Pycharm中import时无法识别自己写的程序方法
2018/05/18 Python
机器学习之KNN算法原理及Python实现方法详解
2018/07/09 Python
Python3如何判断三角形的类型
2020/04/12 Python
Python xpath表达式如何实现数据处理
2020/06/13 Python
利用CSS3实现文字折纸效果实例代码
2018/07/10 HTML / CSS
HTML5 video播放器全屏(fullScreen)方法实例
2015/04/24 HTML / CSS
班长岗位职责
2013/11/10 职场文书
蔬菜基地的创业计划书
2014/01/06 职场文书
个人函授自我鉴定
2014/03/25 职场文书
舞蹈教育学专业自荐信
2014/06/15 职场文书
考试作弊万能检讨书
2014/10/19 职场文书
2015年计生协会工作总结
2015/04/24 职场文书
2015小学五年级班主任工作总结
2015/05/21 职场文书
趣味运动会通讯稿
2015/07/18 职场文书
婚宴新郎致辞
2015/07/28 职场文书
2015年社区反邪教工作总结
2015/10/14 职场文书
2016新教师培训心得体会范文
2016/01/08 职场文书
党风廉洁教育心得体会
2016/01/20 职场文书