当前位置: 首页 > 面试题库 >

在SQLalchemy中从自引用表创建树

皇甫伟彦
2023-03-14
问题内容

我正在为面向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

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

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


 类似资料:
  • 问题内容: 我正在尝试集成PostgreSQL和SQLAlchemy,但是SQLAlchemy.create_all()并未从我的模型中创建任何表。 我的代码: 但是我得到这个错误: 我怎样才能解决这个问题? 问题答案: 您应该在调用之前放置模型类,如下所示: 如果您的模型是在单独的模块中声明的,请在调用之前将其导入。 说,模型在名为的文件中, 重要说明: 在初始化对象之后导入模型很重要,因为在_

  • 问题内容: 我可以这样创建一个临时表: 但是新表不可读,因为它说它没有主键。 是exisitingtable的主键,因此我希望它在temp表中得到相同的处理。 但是,无论如何,我宁愿找到某种ORM方式来执行此操作。鉴于: 如何在不执行100000命令的情况下填充一些选定的内容?还是有一种方法可以通过类似于上面的普通SQL版本的查询来创建表? 问题答案: 它不完全是ORM,但为了最初创建表,我将克隆

  • 问题内容: SQLAlchemy支持在postgresql中创建部分索引。 是否可以通过SQLAlchemy创建部分 唯一 索引 ? 像这样想象一个表/模型: 我想要一个唯一的索引,对于给定的发票,该索引只能有一个“活动”的ScheduledPayment。 我可以在postgres中手动创建它: 我想知道如何使用SQLAlchemy 0.9将其添加到我的SQLAlchemy模型中。 问题答案:

  • 我在<code>Spring</code>和<code>PostgreSQL</code>之间的“通信”方面有问题。 我的类<code>User.java</code>: 为创建表脚本: 类Department.java 为创建表脚本: 班级Organization.java 为< code >组织创建表脚本: 当我运行程序时, 在 中创建“own”列,它看起来像: 怎么修啊?应该是没有立柱的 注

  • 问题内容: 是否可以使用sqlalchemy在SQLite中创建JSON类型的Column?我试过了 和 两者都收到错误消息: 编译器无法呈现类型的元素 想知道sqlalchemy中是否有任何解决方案,或者我应该改为使用SQL。提前致谢。 [更新] SQLite版本3.16.0 问题答案: 直到3.9版才将JSON添加到SQLite中。您将需要升级SQLite或将json转换为字符串并将其保存,同

  • null 帮我处理一下这种情况吧。谢谢你。