이 글은 Python 재귀 쿼리 메뉴를 주로 소개하고 이를 json 예제로 변환한 것입니다. 관심 있는 친구들이 참고할 수 있습니다.
최근에 Python으로 메뉴를 작성해야 했는데 작성하는 데 2~3일이 걸렸습니다. 이제는 여기에 기록하고 필요한 친구들이 배울 수 있습니다.
참고: 이 기사에서는 실행 불가능한 코드 전체를 인용하고 코드의 핵심 부분만 발췌했습니다.
환경
데이터베이스: 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 코드
메뉴 개체에는 하위 메뉴 목록 "subMenus"에 대한 참조가 있으며 유형은 목록입니다
Core 코드
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를 전달하는 기능을 지원합니다. null 문자를 전달하면 루트 디렉터리에서 쿼리가 시작됩니다.
"rootMenus" 객체에서 전체 메뉴 트리 구조를 볼 수 있습니다
Json으로 변환
내가 사용하는 ORM 프레임워크는 sqlalchemy입니다. 데이터베이스에서 직접 쿼리한 Menu 개체는 Json으로 변환될 때 오류를 보고합니다. Menu 개체를 Dto 개체로 변환하려면 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
비고:
메뉴에 하위 메뉴가 없으면 "subMenus" 속성을 삭제하세요. 그렇지 않으면 Json으로 변환할 때 null 값이 나타납니다
model_list_2_dto_list 메소드는 Menu 목록을 MenuDto 목록으로 변환할 수 있습니다
to_pinyin은 한자를 병음으로 변환하는 메소드이므로 여기서는 주의할 필요가 없습니다
뷰 레이어는 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과 Dictionary의 의미는 최종적으로 json이 반환될 때 비슷합니다. 먼저 json_dict 메소드를 사용하여 dict 유형으로 변환해야 합니다. 그렇지 않으면 반환된 문자열에 ""
쿼리 결과
위 내용은 Python 재귀 쿼리 메뉴에 대한 자세한 설명 및 json 예제 코드로 변환의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!