2012-06-30 251 views
0

我對ORM來說很新,所以我需要一些幫助來爲我的Flask應用程序創建菜單。我已經實現了模型MenuItem(src在下面)。SQLAlchemy菜單項層次結構/排序

子彈點是:

  • 它有本身一個一對多的關係。
  • 它有許多到許多與模型Role

我的問題關係:

  1. 我可以跳過generate_menu FN除去未訪問的子對象?這段代碼(調用遞歸方法mark_restricted)看起來太複雜了,我不知道它是否可以在ORM查詢中完成?

  2. 實現菜單項目排序的最佳做法是什麼?

Thx guys!

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 
+0

一個ORM查詢將被翻譯成一個SQL查詢。如果你相信這可以完成,爲什麼不發佈一個SQL查詢來完成這個工作,並且我們將弄清楚如何從SA ORM中完成它。 – van

+0

我的方法是對連接的表的角色屬性應用限制。我不堅持通過SQLAlchemy做第一次,我對SA最佳實踐更感興趣。 – 1osmi

回答

0

我已經通過添加附加屬性order = db.Column(db.Integer),並通過添加以下行generate_menu FN實現自定義菜單項排序:

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