SQLAlchemy从数据库内读取出树形结构菜单

2 篇文章 0 订阅
2 篇文章 0 订阅

首先Sqlalchemy是不可以直接读取出有条件限制的树形结构菜单,只能自己实现一个

分析

首先分析一下树状结构,树状结构由多个互相关联的节点组成,所以需要一个节点类,节点类里面字段必须与菜单表里面的必要字段一样

class TreeMenuNode:
    """树形菜单节点"""

    def __init__(self, pk, title, code, icon_class, url, order, child, parent):
        self.pk = pk
        self.title = title
        self.code = code
        self.icon_class = icon_class
        self.url = url
        self.order = order
        self.child = child
        self.parent = parent

    def count(self):
        if not self.child:
            return 0
        return len(self.child)


class HandleTreeMenu:
    """处理树形侧边栏菜单"""

    def __init__(self, menus):
        self.menus = menus
        self.tree_menu = []

    def __iter__(self):
        if self.tree_menu:
            return iter(self.tree_menu)
        return iter([])

    @staticmethod
    def get_complete_menu_structure(_menu_list):
        """得到完整的菜单结构"""
        menu_list = copy.copy(_menu_list)
        for menu in menu_list:
            if menu.parent and menu.parent not in menu_list:
                menu_list.append(menu.parent)
                menu_list.extend(HandleTreeMenu.get_complete_menu_structure(menu_list))
        return menu_list

    def convert_to_tree(self):
        """转换BaseQuery为MenuTree结构"""
        complete_menu = HandleTreeMenu.get_complete_menu_structure(self.menus)
        # 所有顶级菜单
        top_menu = [menu for menu in complete_menu if not menu.parent]
        for menu in top_menu:
            current_menu = TreeMenuNode(menu.pk, menu.title, menu.code, menu.icon_class, menu.url, menu.order, [], None)
            current_menu = self._recursive_menu(menu, current_menu)
            self.tree_menu.append(current_menu)

    def _recursive_menu(self, base_menu, base_tree_menu):
        """由上往下递归菜单得到所有菜单并转换为TreeMenuNode格式"""
        complete_menu = HandleTreeMenu.get_complete_menu_structure(self.menus)
        child_menu = [menu for menu in complete_menu if menu.parent == base_menu]  # 父节点为base_menu的子节点

        for menu in child_menu:
            current_menu = TreeMenuNode(menu.pk, menu.title, menu.code, menu.icon_class, menu.url, menu.order, [], base_tree_menu)
            current_menu = self._recursive_menu(menu, current_menu)
            base_tree_menu.child.append(current_menu)
        return base_tree_menu

# 菜单表
class Menu(BaseModel):
    """侧边栏菜单模型"""
    JK__model_name = '菜单'

    pk = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String, nullable=False, comment='菜单标题')
    code = db.Column(db.String, nullable=False, comment='权限代码')
    icon_class = db.Column(db.String, nullable=True, comment='图标类')
    url = db.Column(db.String, nullable=True, comment='链接地址')
    order = db.Column(db.Integer, default=0, comment='排列顺序')

    child_pk = db.Column(db.Integer, db.ForeignKey('menu.pk'))

    parent = db.relationship(
        'Menu',
        remote_side=[pk],
        backref=backref('child', lazy='dynamic'),
    )

    def __init__(self, title, code, icon_class, url, order):
        self.title = title
        self.code = code
        self.icon_class = icon_class
        self.url = url
        self.order = order


if main == '__main__':
	# 使用方法
	menus = Person.menu.all()  # 这里是直接在数据库里面查询出来的, 用户私有权限表
	tree_menu = HandleTreeMenu(menus)# 创建一个对象
    tree_menu.convert_to_tree() # 执行转换方法
    print(tree_menu.tree_menu) # 得到已经转换的菜单
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值