Python メニューの再帰クエリと JSON へのデータ変換の例

Y2J
リリース: 2017-04-21 16:18:21
オリジナル
2658 人が閲覧しました

この記事では主にPythonの再帰クエリメニューを紹介し、それをJSONのサンプルに変換します。興味のある方は参考にしてください。

最近、Python でメニューを書く必要がありましたが、完了するまでに 2 ~ 3 日かかりました。今はそれをここに記録し、必要な友人がそこから学ぶことができます。

注: この記事では、実行不可能な完全なコードを引用しています。コードの重要な部分のみを抜粋しています

環境

  • データベース: mysql

  • Python: 3.6

T有能な構造

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)
ログイン後にコピー

注: 基本的な処理は: 最初に第 1 レベルのメニューをクエリし、次にこのレベルのメニューの 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 値に変換するときに空が表示されますelmodel_list_2_dto_list メソッドは、メニューリストを menudto リストに変換できます。
  1. to_pinyin は、JSON に戻るときに JSON を返すメソッドに注意する必要はありません。 json と Python の辞書は似ています。最終的に json がページに返されるときは、まず json_dict メソッドを使用して dict 型に変換する必要があります。そうしないと、返される文字列は ""
  2. クエリ結果

  3. になります。

以上がPython メニューの再帰クエリと JSON へのデータ変換の例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート