Vytvoření stromu z vlastního referenčních tabulek v SQLalchemy

hlasů
11

Stavím základní CMS v baňce pro iPhone orientované stránky a mám trochu problémy s něčím. Mám velmi malou databázi jen 1 stůl (stran). Zde je model:

class Page(db.Model):
    __tablename__ = 'pages'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    parent_id = db.Column(db.Integer, db.ForeignKey(pages.id), nullable=True)

Jak můžete vidět, podstránek, prostě odkazovat jiný objekt stránky v parent_idpoli. Co se snažím dělat v admin panelu, je mít vnořené neuspořádanou seznam se všemi stránkami uspořádaných ve svých mateřských stran. Mám velmi malou představu o tom, jak to udělat. Vše, co mohu myslet, je následující (který bude fungovat pouze tehdy, (možná, já nebyly testovány to) 2 úrovně dolů):

pages = Page.query.filter_by(parent_id=None)
for page in pages:
    if Page.query.filter_by(parent_id=page.id):
        page.sub_pages = Page.query.filter_by(parent_id=page.id)

Já bych pak už jen formátovat jej do seznamu v šabloně. Jak bych, aby to fungovalo s potenciálně více než 10 vnořených stránek?

Díky hromady předem!


EDIT: Díval jsem se asi trochu a zjistil http://www.sqlalchemy.org/docs/orm/relationships.html#adjacency-list-relationships , takže jsem přidal

children = db.relationship(Page, backref=db.backref(parent, remote_side=id))

do dolní části mého Pagemodelu. a já jsem při pohledu na rekurzivně prochází vším a přidáním do stromu objektů. Jsem asi nedávalo smysl, ale to je nejlepší způsob, jak to můžu popsat


EDIT 2: Měl jsem jít na to, aby rekurzivní funkce ke spuštění přes všechny stránky a generovat velké vnořené slovník se všemi stránkami a jejich dětem, ale stále to shazovat pythonu, takže si myslím, že je to jen nekonečné smyčce ... tady je funkce

def get_tree(base_page, dest_dict):
    dest_dict = { 'title': base_page.title, 'content': base_page.content }
    children = base_page.children
    if children:
        dest_dict['children'] = {}
        for child in children:
            get_tree(base_page, dest_dict)
    else:
        return

a stránka já jsem to testování s:

@app.route('/test/')
def test():
    pages = Page.query.filter_by(parent_id=None)
    pages_dict = {}
    for page in pages:
        get_tree(page, pages_dict)
    return str(pages_dict)

někdo nějaké nápady?

Položena 04/02/2011 v 09:51
zdroj uživatelem
V jiných jazycích...                            


1 odpovědí

hlasů
14

Podívejte se na http://sqlamp.angri.ru/index.html

nebo http://www.sqlalchemy.org/trac/browser/examples/adjacency_list/adjacency_list.py

UPD: Pro adjacency_list.py deklarativní například

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base(metadata=metadata)

class TreeNode(Base):

    __tablename__ = 'tree'

    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('tree.id'))
    name = Column(String(50), nullable=False)

    children = relationship('TreeNode',

                        # cascade deletions
                        cascade="all",

                        # many to one + adjacency list - remote_side
                        # is required to reference the 'remote' 
                        # column in the join condition.
                        backref=backref("parent", remote_side='TreeNode.id'),

                        # children will be represented as a dictionary
                        # on the "name" attribute.
                        collection_class=attribute_mapped_collection('name'),
                    ) 

    def __init__(self, name, parent=None):
        self.name = name
        self.parent = parent

    def append(self, nodename):
        self.children[nodename] = TreeNode(nodename, parent=self)

    def __repr__(self):
        return "TreeNode(name=%r, id=%r, parent_id=%r)" % (
                    self.name,
                    self.id,
                    self.parent_id
                )    

Fix rekurze

def get_tree(base_page, dest_dict):
    dest_dict = { 'title': base_page.title, 'content': base_page.content }
    children = base_page.children
    if children:
        dest_dict['children'] = {}
        for child in children:
            get_tree(child, dest_dict)
    else:
        return

Použijte dotaz v příkladu pro rekurzivní načtení dat z db:

 # 4 level deep
 node = session.query(TreeNode).\
                        options(joinedload_all("children", "children", 
                                                "children", "children")).\
                        filter(TreeNode.name=="rootnode").\
                        first()
Odpovězeno 04/02/2011 v 10:15
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more