2012-06-30 3 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

Моим подходом было бы применить ограничение на атрибут роли объединенных таблиц. Я не настаиваю на том, чтобы делать # 1 через SQLAlchemy, меня больше интересовали лучшие практики SA. – 1osmi

ответ

0

Я выполнил заказ заказ пункт меню путем добавления дополнительного атрибута order = db.Column(db.Integer) и добавив следующую строку в generate_menu Fn:

item.children.sort(key=operator.attrgetter('order')) 
Смежные вопросы