[英]Creating a tree from self referential tables in SQLalchemy
我正在為一個面向iPhone的網站建立一個基本的CMS瓶,我遇到了一些麻煩。 我有一個非常小的數據庫,只有1個表(頁面)。 這是模型:
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)
如您所見,對於子頁面,它們只是在parent_id
字段中引用另一個頁面對象。 我在管理面板中嘗試做的是有一個嵌套的無序列表,其中所有頁面都嵌套在其父頁面中。 我對如何做到這一點知之甚少。 所有我能想到的是以下(這只會起作用(可能 - 我沒有測試過)2級下來):
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)
然后我會將其格式化為模板中的列表。 如何使用可能超過10個嵌套頁面來完成此工作?
謝謝你提前!
編輯:我看了一下,發現http://www.sqlalchemy.org/docs/orm/relationships.html#adjacency-list-relationships ,所以我添加了
children = db.relationship("Page", backref=db.backref("parent", remote_side=id))
到我的Page
模型的底部。 而且我正在尋找遞歸遍歷所有內容並將其添加到對象樹中。 我可能沒有任何意義,但這是我描述它的最佳方式
編輯2:我做了一個遞歸函數來運行所有頁面並生成一個包含所有頁面及其子項的大型嵌套字典,但它不斷崩潰python所以我認為它只是一個無限循環...這里是功能
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
和我正在測試它的頁面:
@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)
有人有任何想法嗎?
看看http://sqlamp.angri.ru/index.html
或http://www.sqlalchemy.org/trac/browser/examples/adjacency_list/adjacency_list.py
UPD:用於adjacency_list.py聲明性示例
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
)
修復遞歸
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
在示例中使用查詢來從db中遞歸獲取數據:
# 4 level deep
node = session.query(TreeNode).\
options(joinedload_all("children", "children",
"children", "children")).\
filter(TreeNode.name=="rootnode").\
first()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.