【问题标题】:How to determine direction in self-referential one-to-many relationship in SQLAlchemy如何在 SQLAlchemy 中确定自引用一对多关系的方向
【发布时间】:2019-08-31 17:30:33
【问题描述】:

我正在尝试使用 SQLAlchemy 在 Flask 应用程序中建立自引用的一对多关系。

from app import db
[...]
class Task(db.Model):
    __tablename__ = 'tasks'
    id = db.Column(db.Integer, primary_key=True)
    [...]
    parent_id = db.Column(db.Integer, db.ForeignKey('tasks.id'))
    children = db.relationship("Task", backref='parent',
                               remote_side=[id])

我正在尝试在 SQLAlchemy 教程的邻接列表关系中实现类似于 this page 中的示例。每个任务节点可能有许多子节点,而父节点只有一个。

这种关系现在正在发挥作用,但与我原本的意图相反。 parent_id 为 1 的任务将列出 id = 1 的任务作为其子任务。同样,Task.parent 返回一个列表。

迁移工具 Alembic 将上述代码编码如下:

    op.add_column('tasks', sa.Column('parent_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'tasks', 'tasks', ['parent_id'], ['id'])

我的假设是我为上面没有的 remote_side 声明提供了错误的语法。不幸的是,自我参照关系每次都让我感到困惑,我无法理解这是如何工作的。任何帮助或指点将不胜感激。

【问题讨论】:

  • 我不熟悉你使用的所有模块,所以我不会把完整的答案放在一起。我认为你最好给每个任务自己的父级,所以将children 切换到parent。基本上,当你创建一个新任务时,你不是说“这里有 n 个孩子”,而是说“任务​​的父级是 x”。然后,您可以使用parent.id = 1 找到所有任务。如果您现在转换“父母”和“孩子”这两个词的心态,它实际上可能会按预期工作。 Task.parent 返回一个列表,也就是一个子列表,对吧?
  • 感谢您的指点。我确实想知道这是否可能是我转变心态的问题。不过,最后,下面的答案就我正在寻找的东西而言。

标签: python sqlalchemy


【解决方案1】:

根据您链接的文档,声明您的关系可以通过以下方式完成:

class Task(db.Model):
    __tablename__ = 'tasks'
    id = db.Column(db.Integer, primary_key=True)
    [...]
    parent_id = db.Column(db.Integer, db.ForeignKey('tasks.id'))
    parent = db.relationship("Task", backref='children',
                               remote_side=[id])

class Task(db.Model):
    __tablename__ = 'tasks'
    id = db.Column(db.Integer, primary_key=True)
    [...]
    parent_id = db.Column(db.Integer, db.ForeignKey('tasks.id'))
    children = db.relationship("Task", backref=backref('parent',
                               remote_side=[id]))

请注意,在第二种情况下,remote_side 参数是提供给 backref 函数的,而不是提供给关系的。您显示的代码是两者的混合体(您声明了 children 关系,但 remote_side 声明在 backref 调用之外)。

这是因为remote_side=['id'] 声明的字段是由 foreign_key 引用的键,因此必须将其添加到指向关系(父)的“1”侧的关系中。

【讨论】:

  • 完美,谢谢!是的,我从文档中对其进行了一些修改。这是我假设我无法理解的情况之一;它变成了一个自我实现的预言。您对 remote_side 的解释正是我所需要的。 SQLAlchemy 教程非常好,但是我无法从中掌握一些东西。
猜你喜欢
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 2018-10-02
  • 2020-11-12
  • 1970-01-01
  • 2021-05-31
  • 2016-08-26
相关资源
最近更新 更多