SQLAlchemy菜单项层次结构/排序

时间:2012-06-30 09:29:00

标签: python sqlalchemy flask flask-sqlalchemy

我是ORM的新手,所以我需要一些帮助来为我的Flask应用程序创建菜单。我已经实现了模型MenuItem(src在下面)。

子弹点是:

  • 它与自身有一对多的关系。
  • 它与模型Role
  • 有多对多的关系

我的问题:

  1. 我可以跳过在generate_menu fn中删除不可访问的子对象吗?这段代码(调用递归方法mark_restricted)看起来太复杂了,我想知道它是否可以在ORM查询中完成?

  2. 实施菜单项目排序的最佳做法是什么?

  3. Thx伙计们!

    class MenuItem(db.Model):
        """
        Menu item model
    
        """
    
        __tablename__ = 'sa_menu_item'
    
        id = db.Column(db.Integer, primary_key=True)
        parent_id = db.Column(db.Integer, db.ForeignKey('sa_menu_item.id'))    
        text = db.Column(db.String(100))
        view = db.Column(db.String(100))
        icon = db.Column(db.String(50))
        active = db.Column(db.Boolean)
        children = db.relationship('MenuItem')
        allowed_roles = db.relationship('Role',
                        secondary=menu_role
                        ,backref='menu_item')
    
        def __init__(self, text, view=None, icon=None):
    
            self.text = text
            self.view = view
            self.icon = icon
    
        def accessible_for(self, provided_set):
    
            for role in self.allowed_roles:
                if role.match(provided_set): return True
            return False
    
        def mark_restricted(self, lst, priv, not_allowed):
            """ Adds menu items restricted by priv to not_allowed list  """
    
            if not self.accessible_for(priv):
                if self in lst:
                    not_allowed.append(lst.index(self))
                return
    
            if self.children is not None:
                for child in self.children:
                    if not child.accessible_for(priv):
                        self.children.remove(child)
                    else:
                        child.mark_restricted(lst, priv,not_allowed)
    
        @classmethod
        def generate_menu(cls, provided_set):
            """Generates menu based on provided_set of permissions""" 
    
            not_allowed = []
    
            lst = MenuItem.query.filter(MenuItem.parent_id == None, MenuItem.active == True, MenuItem.children != None).all()
    
            for item in lst:
                item.mark_restricted(lst,provided_set,not_allowed)
    
            lst = [i for j, i in enumerate(lst) if j not in not_allowed]
    
            return lst
    

1 个答案:

答案 0 :(得分:0)

我已经通过添加其他属性order = db.Column(db.Integer)并将以下行添加到generate_menu fn来实现自定义菜单项排序:

item.children.sort(key=operator.attrgetter('order'))