gpt4 book ai didi

python - 从 SQLalchemy 中的自引用表创建树

转载 作者:太空狗 更新时间:2023-10-29 18:01:51 27 4
gpt4 key购买 nike

我正在为一个面向 iPhone 的网站在 Flask 中构建一个基本的 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

在示例中使用查询从数据库中递归获取数据:

 # 4 level deep
node = session.query(TreeNode).\
options(joinedload_all("children", "children",
"children", "children")).\
filter(TreeNode.name=="rootnode").\
first()

关于python - 从 SQLalchemy 中的自引用表创建树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4896104/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com